現象
WindowsでVPN接続をして、WSLからHTTPS接続しようとすると
►curl -v https://www.google.com/ 2>&1 | head -n 20
* IPv6: 2404:6800:4004:81d::2004
* IPv4: 142.250.193.196
* Trying 142.250.193.196:443...
* Connected to www.google.com (142.250.193.196) port 443
* ALPN: curl offers h2,http/1.1
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
で固まります。
VPN接続していなければ繋がります。
また、PowerShellでcurl -v https://www.google.com/は通ります。
どうやらWSLとVPNの組み合わせに何かあるようです。
原因
sudo ip link set dev eth0 mtu 1350を実行すると通るようになります。
MTUの問題のようです。
以下、私のおおざっぱな理解です。
Windows上のVPNクライアントがVPN接続しています。
WSLはVPNの存在を知りません。
WSLは1500バイトでパケットを送ります。
Windows上のVPNクライアントはカプセル化します。
1500を超えるためパケットは分割されます。
通信経路上のいずれかの機器が分割されたパケットを拒否する可能性があります。
また機器がパケット分割を回避するためICMP Frag-Neededを返しているのかもしれません。
が、WindowsのNATが中継しないためか、WSLは適切なパケットサイズで送っているつもりで理解できないためか検知できないようです。
そこで手動でMTUを設定します。
VPN カプセル化してもパケット分割が起きなくなります。
対処
永続化するにはWSLの /etc/wsl.conf に設定します。
[network]
mtu=1350
確認するには、
Windows側でwsl --shutdownしてWSLを再起動します。
MTU探訪
実際は何が障害なのでしょうか?
ます、WindowsからMTUを計測してみます。
ping google.com -f -l 1432コマンドを使います。
PS C:\Windows\System32> ping google.com -f -l 1432
google.com [172.217.31.174]に ping を送信しています 1432 バイトのデータ:
172.217.31.174 からの応答: バイト数 =1432 時間 =6ms TTL=116
172.217.31.174 からの応答: バイト数 =1432 時間 =8ms TTL=116
172.217.31.174 の ping 統計:
パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
最小 = 6ms、最大 = 8ms、平均 = 7ms
Ctrl+C
PS C:\Windows\System32> ping google.com -f -l 1433
google.com [172.217.31.174]に ping を送信しています 1433 バイトのデータ:
192.168.1.1 からの応答: パケットの断片化が必要ですが、DF が設定されています。
1432バイトが限界です。これはIPヘッダー20バイトとICMPヘッダ8バイトを足した1460バイトです。
これがVPNを使っていない状態のMTU最適値です。
次に、VPNに接続すると
PS C:\Windows\System32> ping google.com -f -l 1323
google.com [142.250.196.142]に ping を送信しています 1323 バイトのデータ:
パケットの断片化が必要ですが、DF が設定されています。
パケットの断片化が必要ですが、DF が設定されています。
142.250.196.142 の ping 統計:
パケット数: 送信 = 2、受信 = 0、損失 = 2 (100% の損失)、
Ctrl+C
PS C:\Windows\System32> ping google.com -f -l 1322
google.com [142.250.196.142]に ping を送信しています 1322 バイトのデータ:
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
142.250.196.142 の ping 統計:
パケット数: 送信 = 4、受信 = 0、損失 = 4 (100% の損失)、
1322バイトが限界です。
IPヘッダとICMPヘッダを足して1350バイトです。
1350がVPN接続時のMTU最適値と見て良さそうです。
まあ、でもタイムアウト気になりますよね。
PS C:\Windows\System32> ping google.com -f -l 1000
google.com [172.217.31.174]に ping を送信しています 1000 バイトのデータ:
172.217.31.174 からの応答: バイト数 =1000 時間 =51ms TTL=116
172.217.31.174 からの応答: バイト数 =1000 時間 =20ms TTL=116
172.217.31.174 の ping 統計:
パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
最小 = 20ms、最大 = 51ms、平均 = 35ms
Ctrl+C
PS C:\Windows\System32> ping google.com -f -l 1001
google.com [172.217.31.174]に ping を送信しています 1001 バイトのデータ:
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
172.217.31.174 の ping 統計:
パケット数: 送信 = 4、受信 = 0、損失 = 4 (100% の損失)、
1000バイト境界で何かいます。
謎の挙動です。
sudo ip link set dev eth0 mtu 1500を実行して、MTUを1500に戻しておきます。
Linuxでは、ping -M do -s 1432 google.comコマンドを使います。
ledsun@xps24nov:/m/c/U/led_l►ping -M do -s 1432 google.com
PING google.com (142.250.193.206) 1432(1460) bytes of data.
1440 bytes from del11s17-in-f14.1e100.net (142.250.193.206): icmp_seq=1 ttl=115 time=7.75 ms
1440 bytes from del11s17-in-f14.1e100.net (142.250.193.206): icmp_seq=2 ttl=115 time=10.6 ms
^C
--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1004ms
rtt min/avg/max/mdev = 7.747/9.154/10.561/1.407 ms
ledsun@xps24nov:/m/c/U/led_l►ping -M do -s 1433 google.com
PING google.com (142.250.194.174) 1433(1461) bytes of data.
From ntt.setup (192.168.1.1) icmp_seq=1 Frag needed and DF set (mtu = 1460)
ping: local error: message too long, mtu=1460
^C
--- google.com ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1000ms
1432境界です。
1322境界があると思うじゃないですか?
ledsun@xps24nov:/m/c/U/led_l[1]►ping -M do -s 1323 google.com
PING google.com (172.217.31.174) 1333(1361) bytes of data.
で固まります。
つまりICMP Frag-Neededは受け取れません。
1000の境界を試すと
ledsun@xps24nov:/m/c/U/led_l[1]►ping -M do -s 1000 google.com
PING google.com (142.250.194.174) 1000(1028) bytes of data.
1008 bytes from del12s06-in-f14.1e100.net (142.250.194.174): icmp_seq=1 ttl=115 time=21.5 ms
1008 bytes from del12s06-in-f14.1e100.net (142.250.194.174): icmp_seq=2 ttl=115 time=21.5 ms
1008 bytes from del12s06-in-f14.1e100.net (142.250.194.174): icmp_seq=3 ttl=115 time=22.9 ms
1008 bytes from del12s06-in-f14.1e100.net (142.250.194.174): icmp_seq=4 ttl=115 time=26.1 ms
1008 bytes from del12s06-in-f14.1e100.net (142.250.194.174): icmp_seq=5 ttl=115 time=24.5 ms
^C
--- google.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4005ms
rtt min/avg/max/mdev = 21.459/23.273/26.108/1.797 ms
ledsun@xps24nov:/m/c/U/led_l►ping -M do -s 1001 google.com
PING google.com (142.250.194.174) 1001(1029) bytes of data.
これはWindowsと一致しています。
ICMP Frag-Neededが受け取れないのはWindowsと一致していません。
WSL固有の現象のようです。
どうやらWindowsのNATがそういう性質らしいです。よくわかりません。
また、いまのところMTUは1350が良さそうです。
ですが1000バイト境界の謎挙動も気になる所です。