最近、仕事環境をネイティブのUbuntuからWSLに切り替えました。
しかし、WSLはVPN周りで問題があることがよく知られており、 自分の知っている範囲だと、以下の2点がよく話題になっているように見えます。
WindowsでVPNに接続するとdnsがおかしくなる WindowsでVPNに接続するとMTU値が反映されなく、通信ができなくなる そこで、最新のWSLではどうなっているのか試してみました。
MTU値の問題はまだある Windows側でVPNに接続し、WSLで通信テストをしてみました。
テキトーなサーバーにping、dig、curl等を試してみた結果、digだけ通りました。
digが通ったということはdnsが正しく引けているはずなので、上述の1.の問題は解決していそうです。
pingが通らないというのは、MTU値に問題がある可能性があるので、 -s オプションで徐々にMTU値をいじって通信テストをしてみました。
すると、自分の環境ではMTU値が1372あたりを下回ったとき、通信ができました。
Windows側でMTU値を確認したところ、VPNのインターフェースはMTU値が1400であり、WSL側のeth0のMTU値は1500のままで、パケットがロストしていたようです。
そこで、下記コマンドでWSL側のMTU値を変更したところ、pingは通りました。
sudo ip link set dev eth0 mtu 1372 TLSのMTU値はさらに低い しかし、curlでhttpsのサーバーに通信をしようとしたところ、timeoutになってしまいました。
curl -vを試してみたところ、下記部分で処理が止まっており、TLSのコネクションで問題が発生していそうでした。
* TLSv1.3 (OUT), TLS handshake, Client hello (1): そこで、MTU値を変更しながら、curlでの通信テストをしていると、1257あたりで、TLSが通るようになりました。(この値はお使いのVPNサーバーに依存すると思われます)
したがって、VPNに接続した状態でWSLからhttps通信をするためには、かなりMTU値をさげないといけないことがわかりました。
VPNに接続したときにMTU値を自動で切り替えたい とりあえずVPNに接続した状態でもWSLから通信をしたいのであれば、下記コマンドでMTU値を設定してあげればよいです。
sudo ip link set dev eth0 mtu {curlが通ったmtu値} しかし、VPNに接続していないときに低いMTU値を使ってしまうと、通信速度の低下を招いてしまう恐れがあります。
そこで、なんとかしてWindows側のVPN接続を検知して、MTU値を切り替えれないか試してみることにしてみます。
NetworkChangeイベント ネットワークが切り替わったタイミングを検知するためには、dotnetの System.Net.NetworkInformation.NetworkChangeを使えばよさそうです。
これをWSLからWindowsを経由して呼び出せれば、WSLからWindowsのVPN接続変更を検知できそうです。
powershellはdotnetのオブジェクトを呼び出せるので、下記のようなpowershellコードで、NetworkChangeイベントを受け取ることができます。
$onChangeNetwork = { Write-Host "Network Changed" } $networkChange = [System.Net.NetworkInformation.NetworkChange] Register-ObjectEvent ` -InputObject $networkChange ` -EventName NetworkAddressChanged ` -Action $onChangeNetwork | Out-Null Wait-Event WSLはexeを呼び出してWindows側のプロセスを起動できるので、あとは上記のようなpowershellをWSLで起動し、ネットワークの変更を検知したら ip link set でMTUを自動変更するsystemd unitを作ればよさそうです。
Read more...