63
62

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

なんかWSL2がインターネットにつながらなくなったときの解決方法

Last updated at Posted at 2021-05-31

#なんかWSL2でネットワークが動かなくなった。

最近、WSL2をぼちぼち使っている中で、インターネットにアクセスできなくなりました。
そこで、魔法の呪文

$ wsl --shutdown

WSL2で困ったときに使う魔法の呪文

を発動しました。だけど動かない。
で、色々試行錯誤した結果、以下の方法で解決しました。

/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を見ます。

/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を見に行きます。

/etc/resolv.conf
$ 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アドレスが振られています。

これで、原因が分かりました。

  1. WSL2のネットワークが172.17.0.1に振られている
  2. Dockerを起動すると、内部的なネットワークが172.17.0.1に割り当てられる。
  3. 名前解決しようとすると、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は止めました。
こういう時に、技術力や自分の知識は試されるな・・・と、ひしひしと感じた事案でした。

63
62
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
63
62

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?