#なんかWSL2でネットワークが動かなくなった。
最近、WSL2をぼちぼち使っている中で、インターネットにアクセスできなくなりました。
そこで、魔法の呪文
$ wsl --shutdown
を発動しました。だけど動かない。
で、色々試行錯誤した結果、以下の方法で解決しました。
/etc/docker/daemon.jsonに
"bip": "172.20.0.254/24"
を追記する。というだけです。
この方法が万人にうまくいくわけではないと思いますが、どんな手順で解決に至ったか解説します。
また、他の解決策と、問題の調査方法も書いてあるので、参考になればと思います。
#WSL2 DNSがよく失敗する問題
WSL2が名前解決に失敗する。という問題は割と昔からありました。
名前解決とは、雑に言うと、ドメイン名からIPアドレスに変換することです。
適当なシェルで、pingを打つと、
$ ping google.com
PING google.com (142.250.206.238) 56(84) bytes of data.
64 bytes from kix06s10-in-f14.1e100.net (142.250.206.238): icmp_seq=1 ttl=116 time=4.51 ms
google.comが142.250.206.238に紐づけられていることが分かります。
これが、名前解決できないときは、
$ ping google.com
ping: google.com: Temporary failure in name resolution
という挙動になります。これが名前解決できていない状況です。しかし、これはインターネットにはつながってます。どういうことかというと、IP直指定でpingをすると
$ ping 142.250.206.238
PING 142.250.206.238 (142.250.206.238) 56(84) bytes of data.
64 bytes from 142.250.206.238: icmp_seq=1 ttl=116 time=4.75 ms
となります。したがって、IPアドレス直打ちでは動きます。これがインターネットはつながっているが、DNSが死んでいるために、ネットにつながらない状態です。
こういう状態はWSL2を使っているとしばしばあり、魔法の呪文で解決できることがありました。しかし、今回は違った。という話です。
/etc/resolv.confを変更?
こういう記事があります。
WSLの起動時にresolv.confを再生成されないようにする
大体のLinuxは/etc/resolv.confというところにDNSサーバーを記載します。
nameserver 8.8.8.8
という記述をすると、動いたりします。これは、8.8.8.8というDNSサーバーに先ほどのドメインの解決を依頼しています。
が、動かなかったというところがメインのお話。
Docker?
ふと不思議な挙動を見つけました。確かに、wsl --shutdown
をした後、名前解決できているのです。しかし、自分が適当に作業をしているうちに、いつのまにか名前解決できなくなっているのです。
そこで、自分がやっていることを見ているとあることに気が付きます。
$ ping google.com #つながる
$ sudo service docker start
$ ping google.com #つながらない
という謎の挙動を見つけます。そう。Dockerを起動すると名前解決が出来なくなるのです。
ここで、Windows側のPowershellでIPがどうなっているのかみましょう。
$ ipconfig
Windows IP 構成
(中略)
イーサネット アダプター vEthernet (WSL):
接続固有の DNS サフィックス . . . . .:
リンクローカル IPv6 アドレス. . . . .: fe80::85e4:9ead:71bb:6d6f%28
IPv4 アドレス . . . . . . . . . . . .: 172.17.0.1
サブネット マスク . . . . . . . . . .: 255.255.240.0
デフォルト ゲートウェイ . . . . . . .:
こうするとWSLには172.17.0.1割り当てられているのが分かります。ここで、WSL内の/etc/resolv.confを見ます。
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.17.0.1
なるほど、nameserverのアドレスとWindows側のIPv4は同一のものですね。
この時、ifconfigを見に行きます。
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.8.58 netmask 255.255.240.0 broadcast 172.17.15.255
(略)
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
(略)
まぁ特に面白いところは無いです。では、sudo service docker start
した後、ifconfigを見てみます。
$ ifconfig
br-fb02ec2e615e: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
(略)
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.255.0 broadcast 172.17.0.255
(略)
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.8.58 netmask 255.255.240.0 broadcast 172.17.15.255
(略)
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
(略)
なんかネットワークインターフェースが増えていて、docker0に172.17.0.1のIPアドレスが振られています。
これで、原因が分かりました。
- WSL2のネットワークが172.17.0.1に振られている
- Dockerを起動すると、内部的なネットワークが172.17.0.1に割り当てられる。
- 名前解決しようとすると、nameserverがあるべき172.17.0.1がDockerに乗っ取られており、エラーとなる。
では、そもそもdocker0は何なのか?というのはドキュメントを参考にしてください。
https://docs.docker.jp/engine/userguide/networking/default_network/custom-docker0.html
で、このdocker0のIPアドレスの設定を変えるのは何か。というと、最初に書いた、
/etc/docker/daemon.jsonに
"bip": "172.20.0.254/24"
を追記する。という方法になります。これで、WSLに割り当てられているIPアドレスと、docker0のIPアドレスが競合しないようにすることで、ネットワークが動くように調整しています。
分からねぇよそんなもん・・・
追記:それでもつながらなかったときは・・・?
その後、ややこしい問題を引き起こしました。
$ ping google.com #つながる
$ ping api.github.com #つながらない
Dockerのコンテナ内で特定のドメインだけつながらない。というパターンがありました。
これは、
/etc/docker/daemon.jsonに
"dns": ["8.8.8.8"]
を追記して、docker自体を再起動することで解決できるようになりました。
おそらくなんですが、WSL上でDockerを起動するとき、DockerはWSLのDNS設定を継承して、DNS設定を作ります。
しかし、WSLのDNS設定も特殊な構成になっている(Windowsとのブリッジなど)ので、その部分がうまく疎通取れないことがあるようです。そのため、/etc/docker/daemon.jsonに明示的にDNS設定を書き、コンテナはWSLのDNS設定ではなく、そちらの設定を見るように調整すると動きました。知るかよ。
感想
WSL2の魔法の呪文が微妙に伸びていたので、久々に書いてみました。
っていうか、いきなりdockerが動かなくなって、作業にならなくなったので、やらざるを得ませんでした・・・
今回、こういう方法を書いていますが、微妙にロジックが甘いところもあります。そもそもresolv.confに8.8.8.8を記述したタイミングで動く気がするんですよね。今回は、なぜ動かなかったのか・・・正直よく分からないです。
ちょこちょことWindows Insider Programで環境を破壊されたりするので、やはり玄人向きですね。私は2,3回ひどい目に遭いました。大体、WSLの機能自体は使えるようになったので、私はInsider Programは止めました。
こういう時に、技術力や自分の知識は試されるな・・・と、ひしひしと感じた事案でした。