VPNを使うとWSLからTLS接続ができなくなる
問題について
タイトルの通りです。
リモートワーク等でWindows標準のVPN機能を利用すると、何故かWSL内からTLS接続ができなくなるという現象が発生していました。
完全にインターネット通信が出来なくなる訳ではなく、例えばpingや平文HTTPなどは問題なく通信できます。
> ping google.com PING google.com (172.217.174.110) 56(84) bytes of data. 64 bytes from nrt12s28-in-f14.1e100.net (172.217.174.110): icmp_seq=1 ttl=117 time=51.8 ms 64 bytes from nrt12s28-in-f14.1e100.net (172.217.174.110): icmp_seq=2 ttl=117 time=69.8 ms 64 bytes from nrt12s28-in-f14.1e100.net (172.217.174.110): icmp_seq=3 ttl=117 time=40.1 ms 64 bytes from nrt12s28-in-f14.1e100.net (172.217.174.110): icmp_seq=4 ttl=117 time=66.1 ms ^C --- google.com ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3005ms rtt min/avg/max/mdev = 40.121/56.953/69.763/11.801 ms
> curl http://google.com <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>301 Moved</TITLE></HEAD><BODY> <H1>301 Moved</H1> The document has moved <A HREF="http://www.google.com/">here</A>. </BODY></HTML>
> curl -vvv https://google.com * Trying 172.217.174.110:443... * TCP_NODELAY set * Connected to google.com (172.217.174.110) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: /etc/ssl/certs * TLSv1.3 (OUT), TLS handshake, Client hello (1): * OpenSSL SSL_connect: Connection reset by peer in connection to google.com:443 * Closing connection 0 curl: (35) OpenSSL SSL_connect: Connection reset by peer in connection to google.com:443
このように途中でコネクションがリセットされてしまいます。
TLS接続だけかと思いきや、 apt install
のような一部のHTTP通信でも通信できなくなる場合があります。
解決策
とりあえずWSLとVPNに関する通信関連のトラブルについて探してみると下のドキュメントがヒットします。
VPN に接続されると、bash のネットワーク接続が切断される
Windows で VPN に接続した後、bash のネットワーク接続が切断される場合は、bash 内からこの回避策を試してください。 この回避策により、/etc/resolv.conf を使用して DNS 解決を手動で上書きできます。
Windows Subsystem for Linux のトラブルシューティング | Microsoft Docs
症状的には似ていますが、どうやらDNSサーバを手動で設定する方法のようです。
今回の症状は、先に述べたようにpingやHTTPが通っているためドメイン名の名前解決自体は何の問題もなく行えています。
そのため、この対処法は今回のトラブルとは無関係でしょう。
さらに探しているとmicrosoft/WSLリポジトリのissueで次のようなコメントを見つけます。
May this could be a fix for you:
Set MTU to the value of the VPN interface:
sudo ifconfig eth0 mtu 1350
While connected to VPN the curl command hangs up · Issue #4517 · microsoft/WSL · GitHub
あー、なるほど。MTU値が原因ね。
というわけでMTU値を調べてみます。
まずはWindows側から
> netsh interface ipv4 show subinterfaces MTU MediaSenseState 受信バイト 送信バイト インターフェイス ------ --------------- ----------- ---------- ----------------- 1376 1 1484402 847609 VPN //...
ふむふむ。次はWSL側
# ip link show //... 4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff //...
はい、ビンゴです。
VPNによってMTU値が減少していたのが正しくWSL側に伝わっておらず、1376バイトを超えるパケットが経路上で破棄されていたため上手く通信できていなかったのでしょう。
pingやHTTPが通ったのはパケットのサイズが1376バイト以内に収まっていたからだと考えられます。
一方で、HTTP通信であるのも関わらず apt install
が通らなかったのは、パケットのサイズが1376バイトを超えていたからでしょう。
対処法は上のコメントの通り、WSL側のインタフェースにも適切なMTU値を設定することです。
そうすることで、次のようにVPN経由でも問題なくインターネット通信が行えるようになりました。
# ip link set eth0 mtu 1376 # curl https://google.com <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>301 Moved</TITLE></HEAD><BODY> <H1>301 Moved</H1> The document has moved <A HREF="https://www.google.com/">here</A>. </BODY></HTML>
めでたしめでたし。