はじめに
ある日、WSL 環境で CLI ツールを使っていたところ、突然 API に接続できなくなりました。
API Error: Unable to connect to API (ConnectionRefused)
最初に思ったのは、次のどちらかでした。
- ネットワークが不調なのかもしれない
- Codex や Claude Code 側、あるいは API 側で障害が起きているのかもしれない
でも実際は、WSL の DNS 設定が壊れていて、APIサーバーのFQDNを名前解決できなくなっていたのが原因でした。
この記事では、初心者向けにできるだけ噛み砕いて、
- 何が起きていたのか
- 原因は何だったのか
- どう直したのか
を順番にまとめます。
結論
結論だけ先に書くと、WSL が使う DNSサーバーを手動で固定したら解決しました。
やったことはこの 2 つです。
-
/etc/wsl.confでresolv.confの自動生成を止める -
/etc/resolv.confに DNS サーバーを手動で書く
まずは全体像
Claude Code や Codex に限らず、Web 通信では「ここにアクセスしたい」と FQDN を指定すると、まず DNS で IPアドレスに変換してから、その IPアドレスへ接続する流れで進みます。
そして今回は、この途中にある DNS での名前解決 がうまくいかず、APIサーバーの IPアドレスを取得できないまま止まっていました。
DNSとは
インターネット上のサーバーには、それぞれ IPアドレスという数字の住所 があり、コンピュータはその数字を使って通信しています。
でも人間は 142.250.196.78 のような数字を覚えにくいので、普段は google.com のような ドメイン名 を使います。
DNS は、スマホの連絡先のように、そうした名前を実際の数字の住所に変換してくれる仕組みです。
FQDNとは?
用語の関係をざっくり整理すると、ホスト名 + ドメイン名 = FQDN です。
たとえば www.google.com なら、www がホスト名、google.com がドメイン名、そして www.google.com 全体が FQDN(完全修飾ドメイン名) です。
| 部分 | 意味 |
|---|---|
www |
ホスト名 |
google.com |
ドメイン名 |
www.google.com |
FQDN(完全修飾ドメイン名) |
つまり DNS は、こうした名前全体を見て、最終的に通信先の IP アドレスを調べています。
今回の API でいうと、api.anthropic.com が APIサーバーのFQDN です。
この名前を DNS で引くと、たとえば 160.79.104.10 のような IP アドレスが分かり、そこで初めて実際の通信先が決まります。
原因
原因は、WSL 内で参照していた DNS の設定ファイル /etc/resolv.conf の中身が壊れていたことでした。
今回の直前には、PC の再起動に加えて Tailscale の導入もしていました。
Tailscale を入れると、Windows 側には仮想 NIC が追加され、DNS やルーティングの設定が変わることがあります。
WSL2 は起動時に、Windows 側の設定を見て /etc/resolv.conf を自動生成します。
このとき、WSL からは到達できない DNS サーバーや、Tailscale 側の値を拾ってしまうと、WSL 内だけ名前解決に失敗することがあります。
すると、
- Windows や PowerShell では普通に名前解決できる
- WSL の中だけ
Temporary failure in name resolutionやCould not resolve hostになる
という分離状態が起きます。
つまり今回壊れていたのは、DNS そのものというより、WSL が使う DNS サーバーの設定内容 でした。
実際にやった修正
1. wsl.conf を設定する
まず、WSL に「resolv.conf を自動生成しないで」と伝えます。
cd /etc
echo "[network]" | sudo tee wsl.conf
echo "generateResolvConf = false" | sudo tee -a wsl.conf
2. WSL を再起動する
Windows 側の PowerShell で次を実行します。
wsl --shutdown
そのあと、WSL を起動し直します。
3. DNS を手動で固定する
WSL 側で resolv.conf を作り直します。
sudo rm -f /etc/resolv.conf
echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf
echo "nameserver 8.8.8.8" | sudo tee -a /etc/resolv.conf
sudo chattr +i /etc/resolv.conf
今回使った DNS は次の 2 つです。
-
1.1.1.1(Cloudflare) -
8.8.8.8(Google)
chattr +i は「このファイルを勝手に書き換えないで」というロックです。
修正後の確認
もう一度、WSL 内で次を実行します。
ping api.anthropic.com
curl -v https://api.anthropic.com
すると ping が通るようになりました。
PING api.anthropic.com (160.79.104.10) ...
64 bytes from 160.79.104.10: icmp_seq=1 ttl=58 time=12.0 ms
ここまで来れば、名前解決は復旧しています。
あとは Codex や Claude Code など、実際に使っていた CLI ツールを起動して、通常どおり使えるか確認すれば完了です。
初心者向けの見分け方
同じように「API に接続できない」と出たときは、いきなりアプリ本体を疑う前に、次の順番で切り分けると分かりやすいです。
1. その環境だけで起きているか
- PowerShell では動くか
- WSL では動かないか
この差があるなら、アプリ全体ではなく 環境差分 を疑うべきです。
2. 名前解決できるか
ping api.anthropic.com
curl -v https://api.anthropic.com
ここで Could not resolve host が出たら、かなりの確率で DNS 問題です。
3. 接続先が分かっているのに届かないのか
もし DNS は引けるのにタイムアウトするなら、
- VPN
- プロキシ
- ファイアウォール
- IPv6
のような別のネットワーク問題の可能性が高いです。
ハマりどころ
今回ややこしかったのは、エラー文だけでは「DNS が原因」と分かりにくいことです。
Unable to connect to API と出ると、どうしても「API サーバーが悪いのかな」と考えがちです。
でも実際には、
- API サーバーが落ちていたわけではない
- WSL から名前解決できなかっただけ
でした。
こういうときは、アプリのログだけを見るよりも、
pingcurl- 別環境との差分
を見たほうが早く原因に近づけます。
まとめ
WSL で Codex や Claude Code のような CLI ツールが突然 API につながらなくなったとき、最初は API 障害や通信エラーを疑いました。
しかし実際は、WSL 内の DNS 設定が壊れていたため、APIサーバーのFQDNを名前解決できなかったのが原因でした。
今回の対応は次のとおりです。
-
/etc/wsl.confでgenerateResolvConf = falseを設定 -
wsl --shutdownで WSL を再起動 -
/etc/resolv.confに DNS を手動設定 -
pingとcurlで復旧確認
同じ症状で困っている人は、まず curl: (6) Could not resolve host が出ていないか確認してみてください。そこが出ていたら、API ではなく DNS が原因の可能性が高いです。