WSL2でCodex CLIにログインできない。原因は自宅のDNSだった

AI

はじめに

以前、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/token
SSL connection using TLSv1.3
SSL certificate verified via OpenSSL.
HTTP/2 405

405 Method Not Allowed はHEADリクエストに対する応答で、認証成功を示すものではありません。 ただし、IPv4での名前解決とTLS接続、証明書検証まではできています。

一方、IPv6を指定すると名前解決がタイムアウトしました。

curl -6 -Iv --connect-timeout 5 \
  https://auth.openai.com/oauth/token
curl: (28) Resolving timed out after 5000 milliseconds

IPv6で接続する前の名前解決で止まっています。 なお、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=true

IPv4アドレスを一時的に固定する

次に、接続を確認できた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/hosts

WSLの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の応答を分けて確認することが手がかりになりました。

参考リンク

コメント

タイトルとURLをコピーしました