Claude Watch: VPN-Aware Monitoring for AI Coding Agents on macOS
I noticed something odd about Claude’s VPN behavior on macOS. After running Claude Code through a WireGuard tunnel for weeks, I started seeing requests leak to Cloudflare IPs that had nothing to do with my configured proxy. The VPN was supposed to be the gatekeeper, but Claude was finding side doors.
Here is what I found and what I did about it. This is not a theoretical exercise — I caught the leak in my own traffic logs before it became a real problem. If you are running AI coding agents behind a VPN on macOS, read this carefully. The leak is probably already happening on your machine too.
The Leak
Claude Code on macOS uses an embedded browser component for some features. That component has its own network stack, completely separate from the main Claude process. When I routed all traffic through WireGuard, the main process respected the tunnel configuration perfectly. But the embedded browser component did not. It resolved DNS through the system resolver, which fell back to the default gateway when the VPN DNS server was unreachable or slow to respond.
The result was straightforward but concerning: DNS queries for GitHub API endpoints and various telemetry servers were leaking outside the VPN tunnel. Not encrypted payload data — just the domain names themselves. But domain names are metadata, and metadata is exactly what ISPs and network administrators use to profile traffic and build behavioral models of users.
Why This Happens on macOS
macOS handles VPN DNS differently than Linux or even Windows. When a VPN connection sets a custom DNS server, the system resolver does not always honor it for all processes uniformly. Electron-based applications and embedded browser views are notorious for bypassing VPN DNS settings entirely. The OS treats these processes as trusted local applications and routes their DNS queries outside the tunnel, assuming they know what they are doing.
The problem is compounded by the fact that AI coding agents like Claude Code are built on Electron and embed browser components for rendering and feature access. They inherit all the DNS resolution quirks of the Electron framework, which prioritizes speed and local responsiveness over respecting VPN routing rules.
The Fix I Applied
I solved this in three steps, each addressing a different layer of the problem:
- Split DNS configuration: I configured my WireGuard VPN to use a DNS server that only resolves internal and VPN-routed domains. All external DNS queries were forced through the tunnel using a firewall rule on the WireGuard endpoint, ensuring nothing bypasses the VPN.
- Process-level routing with pfctl: I used macOS’s built-in packet filter to create a rule that forces any process owned by the Claude Code application bundle to route through the WireGuard interface, regardless of its own DNS settings or network stack decisions.
- Active monitoring with tcpdump: I set up a simple tcpdump filter on the physical network interface to alert me whenever a DNS query for a known telemetry domain leaves the VPN tunnel. This gives me real-time visibility into any future leaks.
What I Learned From This
The VPN is not a silver bullet. It secures the pipe between you and the endpoint, but it does not control what happens inside the applications that use that pipe. AI coding agents are no different from any other software in this regard — they have their own network behaviors, their own DNS resolution paths, and their own ideas about what traffic should go where.
If you are running AI agents on macOS through a VPN, check your DNS leak today. The leak is probably already happening on your machine. The question is not whether you have a leak, but whether you have noticed it yet. I did not notice mine for three weeks, and that was three weeks too many.