Inspecting Claude Code’s Network Traffic with Linux Namespaces and MITM Proxying (Part 3)

Extracting hostnames from encrypted traffic

In the last post, we explored isolating traffic using namespaces. Now, we’ll explore pulling hostnames from an encrypted session.

The capture file contains Claude’s isolated traffic, but all of it is encrypted with TLS. We can’t read the contents of any request or response. However, we don’t need decryption to determine if WebFetch connects directly to target websites or routes through Anthropic. If example.com appears as a direct connection from the namespace, WebFetch is local. If only api.anthropic.com appears, it’s proxied.

TLS leaks destination hostnames in two places, and we can extract them from the encrypted capture.

Open the capture:

tcpdump -nr claude.pcap | head -30

You’ll see TCP handshakes, data transfers, and teardowns. But the payloads are encrypted. TLS protects them. You can’t see the URLs being fetched, the headers, or the response bodies because they’re encrypted in HTTPS transactions.

What TLS leaks: SNI and DNS

Even though the payload is encrypted, two pieces of metadata remain visible in plaintext:

  1. Server Name Indication (SNI): During the TLS handshake, the client sends the server hostname in cleartext as part of the ClientHello message. This is necessary because multiple HTTPS sites can share one IP address (virtual hosting), and the server needs to know which certificate to present before encryption begins.
  2. DNS queries: Before connecting to any hostname, the process resolves it via DNS. Standard DNS (UDP port 53) is unencrypted.

Example analogy:

TLS is like sending a letter in a sealed, opaque envelope. Nobody en route can read the contents. But the envelope still has the destination address written on the outside- the postal service needs it to deliver the letter. In TLS, the SNI field is equivalent to the delivery address. DNS queries are the phone book lookup you make before writing the address. DNS queries are also visible to anyone watching.

Where this analogy breaks down: With physical mail, you can send letters without a return address. With TLS, the client’s IP address is always visible (it has to be, for TCP to work), and the SNI hostname is structurally required in most configurations. There’s no “anonymous envelope” option in standard TLS. The Encrypted Client Hello (ECH) extension aims to seal the SNI, but it requires server-side support and isn’t widely deployed.

Together, these two metadata leaks tell you where claude connects, even though you can’t see what it sends.

Mental Model Check: “HTTPS hides everything.”

This is the most common misconception about TLS, and it’s important to correct because it affects how you reason about privacy and surveillance. TLS protects the contents of communication. This includes the URL path, headers, body, and cookies. But it does not protect the metadata: which server you’re connecting to (SNI), the IP addresses of both ends, the timing and volume of data transferred, and the DNS lookups that preceded the connection. A network observer who can’t read your HTTPS traffic can still build a detailed profile of which services you use, when, and how much data you exchange.

Extracting hostnames with sni.py

The repository includes sni.py, a pure-Python pcap parser that extracts SNI values from TLS ClientHello messages:

python3 sni.py claude.pcap

Output from a real capture (claude fetching example.com):

  8  api.anthropic.com                  -> 160.79.104.10
  3  docs.mcp.cloudflare.com            -> 104.18.24.159
  1  example.com                        -> 104.20.23.154
  1  http-intake.logs.us5.datadoghq.com -> 34.149.66.137

What this tells us

The output reveals four distinct destinations, each serving a different role:

SNI HostnamePurposeCount
api.anthropic.comModel API: inference requests and responses8
docs.mcp.cloudflare.comA configured MCP server, contacted at startup3
example.comThe WebFetch target: a direct connection1
http-intake.logs.us5.datadoghq.comTelemetry / usage logging1

Look at the third row. example.com appears as a direct TLS connection from the namespace. This means WebFetch initiated a TCP connection to example.com’s IP address from the local machine. The request was not proxied through api.anthropic.com. We can see this from metadata without decrypting a single byte of content.

WebFetch connects directly from your machine. Everything that follows confirms and enriches this finding, but the SNI evidence is sufficient on its own.

You can also examine DNS queries to confirm:

tcpdump -nr claude.pcap 'udp port 53'

This shows DNS lookups for each of those hostnames, confirming the process resolved them locally.

The partial finding

We now know WHERE claude’s traffic goes. We can see it contacts the target URL directly. But we still can’t see the HTTP request content . For that, we need to decrypt the TLS.

In the part 4, we’ll dig deeper into the details by decrypting HTTPS with MITM proxy.