anthropics / anthropics/claude-code

[BUG] macOS: hostnames from /etc/hosts and /etc/resolver/* fail with getaddrinfo ENOTFOUND while a VPN's DNS is active, breaking local HTTP MCP servers

オープン
#88,582 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
area:mcp area:networking bug has repro platform:macos
主要言語
Python
スター
145k
フォーク
23.1k
PR マージ指標
PR 指標を取得中

説明

### Preflight Checklist

- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code

### What's Wrong?

On macOS, when a corporate VPN is connected, Claude Code fails to resolve local development hostnames that the rest of the OS resolves fine, so HTTP MCP servers on those hostnames cannot connect or authenticate:

```
$ claude mcp login devpost
Starting authentication for "devpost"…
Couldn't complete authentication for "devpost": SDK auth failed: getaddrinfo ENOTFOUND devpost.test

$ claude mcp get devpost
Status: ✘ Failed to connect
Issue: ENOTFOUND: getaddrinfo ENOTFOUND devpost.test
```

At the same moment, in the same shell, every OS-resolver client resolves the name correctly:

```
$ dscacheutil -q host -a name devpost.test → ip_address: 127.0.0.1
$ node -e "require('dns').lookup('devpost.test',(e,a)=>console.log(e||a))" → 127.0.0.1
$ bun -e "console.log(await Bun.dns.lookup('devpost.test'))" → 127.0.0.1
$ curl -o /dev/null -w '%{http_code} %{remote_ip}\n' https://devpost.test/mcp → 401 127.0.0.1
```

The hostname is served three ways, all of which Claude Code appears to skip:

- `/etc/hosts`: `127.0.0.1 devpost.test`
- `/etc/resolver/test`: `nameserver 127.0.0.1` (macOS per-domain scoped resolver)
- dnsmasq on 127.0.0.1 with `address=/.test/127.0.0.1` (verified answering over UDP and TCP, v4 and v6)

**The VPN is the variable.** With the VPN disconnected, the same binary and the same config connect fine — even though the active nameservers are then `8.8.8.8`/`8.8.4.4`, which cannot answer `.test`. So in that state resolution must be coming from `/etc/hosts` or the scoped resolver. Connect the VPN (which installs its DNS-filtering resolvers as the system nameservers, and rewrites `/etc/resolv.conf` to point at them) and every lookup of `devpost.test` becomes `ENOTFOUND`, while `getaddrinfo` clients keep working.

Timeline from my machine today, correlating the VPN client's own log with Claude Code MCP calls:

```
12:29:21 VPN: Disconnected
12:56–12:59 devpost.test MCP tool calls succeed
13:05:37 VPN: connect, "using ThreatBlock config: (enabled: true, dnsServers: [...])"
13:05:39 VPN: Connected
13:19 onward every devpost.test lookup → ENOTFOUND
(now) VPN disconnected again → claude mcp get devpost → ✔ Connected
```

It is not connectivity or TLS — only name resolution. Pointing an MCP server at a *publicly* resolvable name that maps to loopback (`https://devpost.test.localtest.me/mcp`, which public DNS answers as `127.0.0.1`) connects even with the VPN up, failing later at `ERR_TLS_CERT_ALTNAME_INVALID` as expected. Likewise `https://127.0.0.1/mcp` reaches the server. Only names that require `/etc/hosts` or a scoped resolver fail.

Related, and probably the same underlying design: #78529 and #81521 both describe the embedded Bun resolver reading `/etc/resolv.conf` and querying nameservers itself rather than going through the OS resolver. On macOS that file is explicitly not authoritative — it even carries the comment "This file is not consulted for DNS hostname resolution … by most processes on this system" — and bypassing `getaddrinfo` there also loses `/etc/hosts` and all of `/etc/resolver/*`. This report is the user-visible macOS symptom of that: local dev hostnames break the moment a VPN's DNS becomes the resolv.conf nameserver.

Expected: Claude Code resolves hostnames the way the rest of macOS does — `/etc/hosts` first, then scoped resolvers from `/etc/resolver/*`, then system nameservers — so `.test`-style local development hosts keep working regardless of VPN state.

### Steps to Reproduce

Requires macOS and a VPN client that installs its own DNS servers (mine is a corporate NordLayer profile with ThreatBlock enabled; any VPN that pushes resolvers whose upstream returns NXDOMAIN for your local TLD should do).

1. Set up a local dev hostname the standard macOS way:
- `echo '127.0.0.1 myapp.test' | sudo tee -a /etc/hosts`
- `brew install dnsmasq`, `echo 'address=/.test/127.0.0.1' > $(brew --prefix)/etc/dnsmasq.conf`, start it
- `sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/test'`
2. Serve anything over HTTPS on `myapp.test` and add it as an MCP server: `claude mcp add -s local -t http myapp https://myapp.test/mcp`
3. With the VPN **disconnected**, run `claude mcp get myapp` → connects.
4. **Connect the VPN**, then run `claude mcp get myapp` → `ENOTFOUND: getaddrinfo ENOTFOUND myapp.test`.
5. In the same shell, confirm the OS still resolves it: `dscacheutil -q host -a name myapp.test` and `curl -v https://myapp.test/` both succeed.

### Environment

- Claude Code 2.1.238 (native install, `~/.local/share/claude/versions/`); also reproduced on 2.1.237, 2.1.236 and 2.1.233, so this is not a recent regression
- macOS, Darwin 25.5.0, arm64
- VPN: NordLayer with ThreatBlock DNS filtering enabled
- dnsmasq 2.x via Homebrew, `/etc/resolver/test` → 127.0.0.1

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

No source file or test is named. Start with the MCP HTTP connection path exercised by `claude mcp get` and `claude mcp login`, then reproduce the VPN-dependent failure while comparing it with macOS `dscacheutil`, Node, Bun, and `curl` lookups. Done means local names from `/etc/hosts` and `/etc/resolver/*` resolve through the same path as the macOS system resolver while the VPN is active.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
bun, macos
領域
networking, operating-systems
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
活発
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。