WSL2 の Ubuntu 22.04 でホスト名解決を普通っぽくする
WSL2 のホスト名解決は鬼門?
今まで WSL2 でのホスト名解決はしばしばトラブっていたと思うが、最近(Windows version 22H2 以降)は dnsTunneling
なる機能がサポートされたためだいぶマシになった。
そこで、Ubuntu 22.04 でホスト名解決が一般的な環境に近くなるような設定を紹介する。
systemd が有効になっていることを確認する
最近は初めから systemd
が有効になっているハズだが、念のため確認しておく。
Ubuntu 側で以下のコマンドを実行する。
cat /etc/wsl.conf
表示された中に下記の内容が書かれていれば OK。
[boot]
systemd=true
もし書かれていなかったら以下のコマンドを実行する。
sudo tee -a /etc/wsl.conf <<EOF
[boot]
systemd = true
EOF
dns tunneling を有効にする
Windows 側で %USERPROFILE%\.wslconfig
に以下の設定を追加する。
[wsl2]
dnsTunneling = true
これがキモで、ぶっちゃけこれだけやっておけばまぁマトモにはなる。
WSL をシャットダウンする
Windows 側で以下のコマンドを実行して WSL をシャットダウンする。
wsl --shutdown
DNS 直での名前解決も systemd-resolved 経由にする
/etc/resolv.conf
を直接読みやがるヤツら(dig
とか)のために、Ubuntu 側で以下のコマンドを実行する。
追記:/etc/resolv.conf
を直接読まなくても gethostbyname(3)
とか getaddrinfo(3)
とかの glibc ライブラリは /etc/nsswitch.conf
経由で /etc/resolv.conf
の影響を受けるし、Golang も glibc と同じような動きをするようなので、/etc/resolv.conf
の影響範囲は結構広いのかもしれない…
さらに追記:glibc ライブラリは libnss-resolve
パッケージをインストールしていれば Unix Domain Socket 経由で systemd-resolved
に直接問い合わせるので /etc/resolv.conf
の影響は受けないようだ。一方で Golang は Cgo が使えれば getaddrinfo(3)
にフォールバックするので glibc ライブラリと同じ挙動になるが、Cgo が使えないと自前で解決しようとするので /etc/resolv.conf
の影響をうけるようだ。
resolv.conf の自動生成を無効にする
sudo tee -a /etc/wsl.conf <<EOF
[network]
generateResolvConf = false
EOF
resolv.conf を stub モードにする
sudo rm /etc/resolv.conf
sudo ln -s ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
systemd-resolved に dnsTunneling のアドレスを教える
sudo mkdir -p /etc/systemd/resolved.conf.d
sudo tee /etc/systemd/resolved.conf.d/dns.conf <<EOF
[Resolve]
DNS=127.0.0.42
EOF
systemd-resolved を再起動する
sudo systemctl restart systemd-resolved
注意
systemd-resolved
では 127.0.0.53:53
で DNS スタブリスナが待ち受けているのだが、WSL2 で複数の環境を実行しているとこれがかち合ってしまう。
かち合うとどうなるかと言うと、後から実行した方の systemd-resolved
が DNS スタブリスナの待ち受けを諦める。(systemctl status systemd-resolved
で見てみるとそれっぽいログが出ているので分かると思う)
そして、その環境からの 127.0.0.53:53
への接続は先に起動していた環境の systemd-resolved
に繋がってしまうため、妙なトラブルに遭遇することになる。(先に起動していた環境を停止するとホスト名解決できなくなったり、先に起動していた環境の /etc/hosts
から結果を返したり…)
なので、複数環境を実行していて安定した動作を望む場合には「DNS 直での名前解決も systemd-resolved 経由にする」はやらないほうが良いだろう。
Discussion