YDiary

メモ的な

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>

ところがTLSHTTPS)接続を試してみると…。

> 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 のネットワーク接続が切断される
WindowsVPN に接続した後、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>

めでたしめでたし。