はじめに
以前、WSLとSSH先でCodex CLIのログインにハマった話を書きました。 そのときはブラウザ認証もデバイスコード認証も失敗したため、Windows側で認証した情報をコピーして回避しました。
今回はその原因をもう少し調べました。ブラウザ認証は完了するものの、WSL2側のCLIでトークンを取得できない状態です。
調査の結果、DNSのAレコードは取得できる一方で、AAAAレコードの問い合わせがタイムアウトしていました。 Windows側のDNSを変更すると、Codex CLIのログインも成功しました。 この記事では、そこに至るまでの切り分けをまとめます。
使用環境
| 項目 | 環境 |
|---|---|
| OS | Windows 11(ビルド26200.9711) |
| WSL | 2.6.3.0(カーネル6.6.87.2-1) |
| Linux | WSL2 / Ubuntu 24.04 |
| Node.js | 24.15.0(mise管理) |
| CLI | OpenAI Codex CLI 0.166.0 |
| VPN | Tailscale(Windows・WSL両方) |
| ルーター | NEC |
| ローカルDNS | AdGuard Home |
| WSL DNS | DNS Tunneling有効 |
家庭内では 192.168.10.1 がAtermルーター、192.168.10.115 がAdGuard Homeです。 当初のWindows側の設定は、AdGuard Homeが優先DNS、ルーターが代替DNSでした。 以下のIPアドレスやインターフェース名は筆者の環境の例です。
ログインエラーとHTTPS接続を確認する
まず通常のログインを試しました。
codex loginブラウザでChatGPTアカウントの認証は進みますが、その後に次のエラーが出ました。
Token exchange error: error sending request for url
(https://auth.openai.com/oauth/token)
Error logging in: Token exchange failedデバイスコード認証も試しました。
codex login --device-authこちらはコードを取得するリクエストで失敗しました。
Error logging in: error sending request for url
(https://auth.openai.com/api/accounts/deviceauth/usercode)ブラウザ認証後には、CLIから認証サーバーへ接続してトークンを交換する必要があります。 今回は、そのCLI側の通信に問題がありそうです。
curlでIPv4とIPv6を比較する
まずWSLからIPv4を指定して接続しました。 -I はHEADリクエスト、-v は接続の詳細表示です。
curl -4 -Iv https://auth.openai.com/oauth/tokenSSL connection using TLSv1.3
SSL certificate verified via OpenSSL.
HTTP/2 405405 Method Not Allowed はHEADリクエストに対する応答で、認証成功を示すものではありません。 ただし、IPv4での名前解決とTLS接続、証明書検証まではできています。
一方、IPv6を指定すると名前解決がタイムアウトしました。
curl -6 -Iv --connect-timeout 5 \
https://auth.openai.com/oauth/tokencurl: (28) Resolving timed out after 5000 millisecondsIPv6で接続する前の名前解決で止まっています。 なお、AAAAはIPv6アドレスを返すレコードですが、問い合わせ自体はIPv4経由でも行えます。 この時点でIPv6の通信経路に問題があると決めつけずに、DNSを調べることにしました。
Codexのログとhostsによる切り分け
Codexのログでも、コールバック受信後のトークン交換で失敗していました。関連部分を抜粋します。
received login callback
has_code=true
state_valid=true
starting oauth token exchange
oauth token connection failed; retrying with system proxy
oauth token exchange transport failure
is_timeout=false
is_connect=true
is_request=trueIPv4アドレスを一時的に固定する
次に、接続を確認できたIPv4アドレスを /etc/hosts に一時的に追加しました。
注意:以下は調査時のIPアドレスです。
echo "104.18.41.241 auth.openai.com" |
sudo tee -a /etc/hosts続けて codex login --device-auth を実行すると、ログインに成功しました。 名前解決を迂回すると成功したため、DNSかその結果を使う接続処理が疑わしくなりました。
検証後は後片付けとして追加した行を削除します。
sudo sed -i \
'/^104\.18\.41\.241 auth\.openai\.com$/d' \
/etc/hostsWSLのDNS経路を調べる
当初の /etc/resolv.conf はTailscaleによって生成されていました。
# file generated by tailscale
nameserver 100.100.100.100
nameserver fd7a:115c:a1e0::53切り分けのため、WSL側でTailscaleからDNS設定を受け取らないようにしました。
注意:Tailscaleの名前解決や分割DNSに影響するため、元の設定を控えます。元が有効だった場合は
sudo tailscale set --accept-dns=trueで戻せます。
sudo tailscale set --accept-dns=false変更後の /etc/resolv.conf は次のようになりました。
nameserver 10.255.255.254これは今回の環境でDNS Tunnelingに使われていたアドレスです。 TailscaleのDNS設定を外してもエラーは解消しなかったため、この経路で調査を続けました。 以降は .wslconfig の dnsTunneling=true の状態で確認しています。
AレコードとAAAAレコードを個別に問い合わせる
WSLのDNSに対し、dig でレコードの種類を分けて確認しました。 Ubuntuで dig が見つからない場合は、dnsutils パッケージをインストールします。 +time=2 +tries=1 は待ち時間と試行回数を抑えるための指定です。
dig @10.255.255.254 auth.openai.com A +time=2 +tries=1
dig @10.255.255.254 auth.openai.com AAAA +time=2 +tries=1| 問い合わせ | 結果 |
|---|---|
| Aレコード | 成功(約3ms) |
| AAAAレコード | タイムアウト |
AAAAレコードが存在しないという応答ではなく、問い合わせ自体が時間内に完了していません。
外部DNSとWindows側を比較する
CloudflareのDNSを直接指定すると、AAAAレコードを正常に取得できました。 社内ネットワークなどでは、外部DNSの利用が許可されているかを確認してから試します。
dig @1.1.1.1 auth.openai.com AAAA +time=2 +tries=1応答時間は約7msでした。AAAAレコード自体は存在し、特定のDNS経路で問い合わせが失敗しているようです。
WindowsのPowerShellでも確認します。
Resolve-DnsName auth.openai.com -Type AAAA
Resolve-DnsName auth.openai.com -Type AAAA -Server 1.1.1.1通常の問い合わせはタイムアウトしましたが、Cloudflareを指定すると成功しました。 WSLだけではなく、Windowsが利用するDNS経路にも問題がありそうです。
続いて家庭内のDNSサーバーを個別に指定します。
Resolve-DnsName auth.openai.com -Type AAAA -Server 192.168.10.1
Resolve-DnsName auth.openai.com -Type AAAA -Server 192.168.10.115| DNSサーバー | AAAA問い合わせ |
|---|---|
Aterm(192.168.10.1) |
タイムアウト |
AdGuard Home(192.168.10.115) |
成功 |
Cloudflare(1.1.1.1) |
成功 |
ルーターのDNS中継、またはその上流DNSに問題がある可能性が高くなりました。 AdGuard Homeを優先DNSにしていても、ルーターを含む設定全体が正常とは限りません。 ただし、Windowsが各問い合わせでどのサーバーを選んだかは、この結果だけでは断定できません。
WindowsのDNSを変更して再確認する
イーサネット 3 は筆者の環境での名前です。 実行前に Get-DnsClientServerAddress で対象のアダプターと現在の設定を確認します。 元のDNSアドレスに加え、手動設定かDHCPによる自動取得かも控えておきます。
注意:外部DNSへ切り替えると、社内・ローカル名の解決やAdGuard Homeの広告ブロックなどに影響します。管理方針と影響を確認してから変更します。
管理者PowerShellで、有線LANアダプターのDNSをCloudflareに変更しました。
Set-DnsClientServerAddress `
-InterfaceAlias "イーサネット 3" `
-ServerAddresses ("1.1.1.1","1.0.0.1")
Clear-DnsClientCacheその後、WSLで再びデバイスコード認証を試しました。
codex login --device-auth今度は正常にログインできました。 WindowsのDNSをDHCPによる自動取得に戻すと、ルーターの 192.168.10.1 が配布され、AAAA問い合わせのタイムアウトが再発しました。
DHCPに戻す場合は、同じアダプターを指定して次のようにします。 以前の設定が手動だった場合は、DHCPに戻すのではなく、控えておいたアドレスを再設定します。
Set-DnsClientServerAddress -InterfaceAlias "イーサネット 3" -ResetServerAddresses
Clear-DnsClientCache最終的には、Windows側のDNSをAdGuard Homeに設定して使用しています。
同じ症状で困ったら何をすればよいか
今回と同じ原因かを確認するには、次の順で試すと切り分けやすくなります。
1. Windows側でDNSの応答を比較する
PowerShellで通常のDNSと別のDNSに同じ問い合わせを送ります。
Resolve-DnsName auth.openai.com -Type AAAA
Resolve-DnsName auth.openai.com -Type AAAA -Server 1.1.1.1通常の問い合わせだけがタイムアウトする場合は、現在使っているDNSの経路を疑います。 Get-DnsClientServerAddress でDNSの設定を確認し、ルーターが指定されていれば、そのアドレスへの問い合わせも比較します。
2. Windows側のDNSを変更する
前節の手順で、使用中のアダプターのDNSを正常に応答するサーバーへ変更します。 今回の検証ではCloudflareを使いましたが、AdGuard Homeなど普段の運用に合うDNSでも構いません。 問題のあるルーターDNSは代替DNSにも残さず、元の設定は控えておきます。
3. WSL側で名前解決とログインを再確認する
DNS Tunnelingを使っている場合は、WSL側でもAAAA問い合わせが完了するか確認します。
dig auth.openai.com AAAA +time=2 +tries=1
codex login --device-auth/etc/hosts に検証用の行を追加していた場合は、削除してから試します。 TailscaleがDNSを管理している場合はWindows側の変更だけでは経路が変わらないことがあるため、/etc/resolv.conf も確認します。 両方のDNSで問い合わせが失敗する場合や、DNSを変更してもログインできない場合は、今回とは別の原因も調べる必要があります。
まとめ
今回の原因は、自宅のルーターをDNSサーバーとして使っていた経路にありました。 ルーターへのAAAA問い合わせがタイムアウトしており、Windows側のDNSをCloudflareに変更するとCodex CLIのログインが成功しました。 最終的にはルーターDNSを使わず、AdGuard Homeを利用する構成にしています。
ただし、ルーター本体と上流DNSのどちらに問題があったかや、Codex内部の失敗箇所までは特定できていません。
今回はWSL内だけでなく、Windows側のDNS設定まで調べたことが解決につながりました。 IPv4で通信できても安心せず、AとAAAAの応答を分けて確認することが手がかりになりました。

コメント