Tailscale 経由で WSL2 に SSH すると鍵交換で固まる問題
環境 #
- 自宅PC: Windows + WSL2 (Ubuntu)、有線接続。Windows と WSL2 にそれぞれ Tailscale を導入(別ノード扱い)。
- ノートPC: Tailscale 導入済み。自宅の別 WiFi に接続。
症状 #
- ノートPC の PowerShell から WSL2 ノードへ ssh すると無反応で固まる。
- Tailscale IP への ping は返ってくる。
原因 #
- Windows と WSL2 は Tailscale 上では別ノードで、それぞれ別の
100.x.x.xを持つ。最初は Windows ノードの IP に ssh していたため届いていなかった(tailscale statusで WSL2 ノードの IP を確認して解決)。 - 本質的な原因は MTU の逆転。WSL2 の
tailscale0が 1280、その下のeth0が 1200 になっていた。- sshd は
tailscale0(1280) 基準でパケットを作る。 - Tailscale が WireGuard で暗号化すると約 60 バイト増えて合計およそ 1340 バイトになる。
- これが
eth0(1200) を超えるため、大きいパケットが送り出せずドロップされる。 - 小さいパケット(バナー)は通り、大きいパケット(鍵交換)は落ちるので KEX 段階で固まる。
- sshd は
切り分け手順 #
ssh -vvv user@<WSL2のTailscale IP>を実行 →SSH2_MSG_KEXINIT sentの直後で停止。バナー受信後・鍵交換で固まる場合は MTU / MSS を疑う。- DF ビット付き ping をサイズ別に実行(PowerShell)。
ping -f -l 1300 <WSL2のTailscale IP>小さいサイズは通るのに一定サイズ以上で「パケットの断片化が必要ですが、DF が設定されています」と出れば経路 MTU が小さいと判明。
- WSL2 内で MTU を確認。
ip link show→ tailscale0 = 1280、eth0 = 1200 の逆転を確認。
対処 #
WSL2 で eth0 の MTU を tailscale0 + オーバーヘッドが収まる値(通常値 1500)に戻す。
sudo ip link set dev eth0 mtu 1500→ ssh を再試行して接続成功。
永続化 #
ip link set は WSL2 再起動で元に戻るため /etc/wsl.conf に設定する。
[boot]
command = ip link set dev eth0 mtu 1500既に [boot] セクションがある場合(例: systemd=true)は分割せず同じセクションにまとめる。
[boot]
systemd=true
command = ip link set dev eth0 mtu 1500反映と確認。
wsl --shutdown入り直したあと ip link show eth0 が 1500 になっていれば完了。
メモ #
- Tailscale が tunnel MTU を 1280 にするのは「1280 + オーバーヘッド ≒ 1340 が通常の 1500 経路に収まる」前提のため。経路上に 1500 を下回る MTU があると破綻する。
eth0が 1200 になっていた根本原因は未調査(手動設定、何らかのソフト、ホスト側 MTU の継承などの可能性)。再起動のたびに 1200 へ戻る場合は別途調査が必要。