私は普段、WSLでアプリ開発やデータ解析をしています。 そのときたまに、Windowsのブラウザは普通に使えるのに、WSLからは極端にインストールやダウンロードに時間がかかったり、タイムアウトしたりすることがありました。 特に明確なエラーメッセージはなかったので不思議に思いながら放置していましたが、その原因はWSL側のネットワークにあり、次のような解決策があることわかりました。
解決法
/etc/resolv.conf
を変更します(要root)。具体的には次のとおりです。
sudo vim /etc/resolv.conf
でファイルを開きます。
nameserver 8.8.8.8 # 1.1.1.1 でも可
と変更します。
どういった場合にこの異常を疑うか
この現象はエラーメッセージを表示しない事が多いので、とても分かりづらいです。インターネット接続や相手方のサーバーに問題があるように見えることもあります。 具体的には次のような場面で、このエラーを疑うことができると思います。
- “Failed to fetch XXX” や “timeout” といったネットワーク系のエラーが出る
- インストールなどの処理がいつまで経っても終わらない (pipやnpmなど)
- コマンドを打っても反応がない (初期化処理で引っかかっている可能性があります)
その他、インターネットへの接続を必要とする作業で不可解なエラーが出たときは、まずこの対処法を試してみても良いかと思われます。
設定の永続化
この問題が頻繁に生じる場合は、resolv.confの設定を永続化すると便利です。なぜなら、resolv.confはWSLによって毎回上書きされるためです。
永続化のためには、/etc/wsl.conf
を開き、次のように編集します。
[network]
generateResolvConf = false
続いて wsl --shutdown
でWSLを終了した後に起動し直して、先ほど説明したように resolv.conf
を編集します。
これで次回以降の起動時にresolv.confが上書きされることはないはずです。
調査: なぜ起こるのか
そもそも今回触った /etc/resolv.conf
とは何でしょうか? これは、名前解決に使用するDNSサーバを指定するファイルです。変更後の 8.8.8.8
と 1.1.1.1
はパブリックDNSサーバで、それぞれGoogleとCloudflareによって提供されています。
では、変更前の値 (私の場合 172.19.48.1
でした)は何を指しているのでしょうか? これは、WSLとWindowsのネットワークをつなぐアダプターのIPアドレスです。実際、Windows側からipconfigを叩くと次のように見えます。
PS > ipconfig
...
Ethernet adapter vEthernet (WSL):
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : (省略)
IPv4 Address. . . . . . . . . . . : 172.19.48.1
Subnet Mask . . . . . . . . . . . : 255.255.240.0
Default Gateway . . . . . . . . . :
つまり、デフォルトの状態では名前解決にWindowsとWSLを繋いでいるアダプタを使用しているわけです。これ自体は正しい設定ですが、問題は、なぜかそれが突然うまく動かなくなるということです。 調査をしたところ、どうやらWSLに内在する不具合のようですが、複数のissueが報告されているようで原因の特定はできませんでした。
関連するGitHub issueとしては次のものがありました。 もし、今回の手順で解決しないネットワークエラーに遭遇した場合は、これらのissueを追ってみてると良いと思います。
また、根本的な原因は1つに絞れませんでしたが、以下が関連しているのではないかと指摘されています。
- Docker
- Windows Defenderのファイアウォール設定
- VPN
おそらくそれぞれの環境で異なる原因が似たようなエラーを引き起こしていると考えられます。
最後に
WSLはWindowsから割りと安定したLinux環境を利用できるので便利ですが、ネットワーク周りは不安定になることがあるようです。しかし、エラーの理由さえ分かってしまえば /etc/resolv.conf
を変更すれば特に問題ないので、こういったエラーがあることを知っているとすぐに対処できるのではないかと思います。