「DNS issues in WSL2」の回避 — WSL起動時に/etc/resolv.confを書き換える
はじめに
追記(2024年07月16日)対策は不要に!?
この追記を執筆時点(2024-07-16)での WSL2 の最新リリースバージョンは、2.2.4.0 です。このバージョンでは、dnsTunneling がデフォルトで有効になるようで、DNSが索けなくなる現象は起きなくなったようです。少くとも、筆者の環境では起きなくなりました。
ここでは、以前の記事にしたがった設定の無効にし、WSLを更新する方法を示しておきます。なお、設置したファイルなどは残ります。それも不要な場合は、個別に削除してください。
- WSL:UBuntu側の設定無効化
sudo chmod -x /usr/local/bin/set-resolv-conf
sudo systemctl disable set-resolv-conf
- Windows側からWSLの更新(管理者権限でターミナルを起動)
wsl --shutdown
wsl --update
その後 Windows 11 の再起動
"DNS issues in WSL2"
問題となる現象としては、WSL2でUbuntuを利用しているとき[1]、インターネットアクセスができなくなるというものです。WSL2起動時に自動生成された/etc/resolv.conf
で指定されているWSL2の仮想ネットワーク上のネームサーバーの不調が原因のようです。
"DNS issues in WSL2"を見ると、1年以上前から報告されている問題で、2023-11-04の時点でイシューが閉じられていないので、解決にはいたってないようです。
回避する方法
概要
基本的には、/etc/resolv.conf
の nameserver
のIPアドレスを
- アクセス可能な
- 正しく動作しているDNSの
- IPv4のアドレス
に修正することで、この問題を回避します[2]。
resolv.conf
で nameserver を指定する IP アドレス
候補としては、
- Googleなどの公開DNSサーバーのアドレス:例:
8.8.8.8
- ホストのWindows 11が利用しているDNSサーバーのアドレス:例:
192.168.1.1
があります。ただ、筆者がPCを接続するLANでは外部の公開DNSサーバーへクエリが許可されていないこともあって、この記事では 2. の「ホストが利用しているDNSサーバーのアドレス」を指定することにします。
具体的な作業手順
-
WSLのアップデート(管理者権限で起動したWindows PowerShellで行う)
wsl --shutdown wsl --update
-
Windowsが使うDNSサーバーのアドレスを確認(Windows PowerShellで行う)
Get-DnsClientServerAddress
以下のような出力になります。
InterfaceAlias Interface Address ServerAddresses Index Family -------------- --------- ------- --------------- ローカル エリア接続* 1 13 IPv4 {} ローカル エリア接続* 1 13 IPv6 {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3} ローカル エリア接続* 2 16 IPv4 {} ローカル エリア接続* 2 16 IPv6 {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3} Wi-Fi 6 IPv4 {192.168.3.1} Wi-Fi 6 IPv6 {2400:2411:8f63:a500:1111:1111:1111:1111} Bluetooth ネットワーク接続 12 IPv4 {} Bluetooth ネットワーク接続 12 IPv6 {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3} Loopback Pseudo-Interface 1 1 IPv4 {} Loopback Pseudo-Interface 1 1 IPv6 {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3} vEthernet (WSL) 35 IPv4 {} vEthernet (WSL) 35 IPv6 {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3}
この場合は、192.168.3.1 が Hostが使用しているDNSのIPアドレスです。
-
wsl.conf
を設置(以降は、WSL:Ubuntuのbashで行う)[boot] systemd=true
-
一時的に
resolv.conf
を設定
2.
で確認したHostが使用するDNSのアドレスをresolv.conf
に設定します。echo "nameserver 192.168.3.1" | sudo tee /etc/resolv.conf
-
Ubuntuに
nkf
をインストールsudo apt update; sudo apt upgrade -y; sudo apt install nkf -y
-
WSL起動時に実行するスクリプトの設置
#!/bin/bash ifname=`/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0//powershell.exe -Command "Get-NetAdapter | Where-Object Status -eq Up | Select-Object -ExpandProperty Name" | nkf -w -Lu` /mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0//powershell.exe -Command "Get-DnsClientServerAddress -InterfaceAlias '${ifname}' -AddressFamily IPv4 | Select-Object -ExpandProperty ServerAddresses" | nkf -w -Lu | sed -e 's/^/nameserver /' > /etc/resolv.conf
上のスクリプトを保存した
set-resolv-conf
というファイルを、/usr/local/bin/
にコピーし、実行可能にしておく。sudo cp set-resolv-conf /usr/local/bin/ sudo chmod +x /usr/local/bin/set-resolv-conf
-
スクリプトの動作確認
sudo /usr/local/bin/set-resolv-conf
これがエラーなく実行されたら、
/etc/resolv.conf
を確認します。cat /etc/resolv.conf
の結果が、
nameserver 192.168.3.1
となって、2.で確認したホストが使用するDNSサーバーのIPv4アドレスと一致していれば OKです。 -
6.
のスクリプトを起動するためのsystemd用サービス記述ファイルの設置[Unit] Description=set resolv.conf After=network.target [Service] ExecStart=/usr/local/bin/set-resolv-conf [Install] WantedBy=multi-user.target
上の内容を保存した
set-resolv-conf.service
というファイルを/etc/systemd/system/
にコピーします。sudo cp set-resolv-conf.service /etc/systemd/system/
-
8.
のサービス記述ファイルの有効化sudo systemctl enable set-resolv-conf
Discussion