WSL2 の Git が VPN で止まる:インターフェースの MTU か経路か?
Git が認証した後に WSL2 内で固まる?Linux のインターフェースと Windows の VPN アダプターを比較し、小さい値を一つ試して、その寿命を計画しましょう。
クローンは認証を終え、オブジェクト数が表示され、そのあと数分間まったく動きません。Windows は VPN が接続済みと報告し、ホスト名は解決し、同じマシンのブラウザーは同じリポジトリのページを問題なく取得します。この組み合わせは資格情報ではなくパケットサイズを示しており、サイズの問いは、WSL2 には独自の MTU を持つ独自の Linux インターフェースがあるため、二か所で立てる必要があります。一方の数値は経路の Windows 側に、もう一方はディストリビューション側に属し、VPN アダプターだけを見ると経路の半分が未調査のままになります。
三つの兆候がサイズの問題を他の原因から切り分ける
第一の兆候は形で、接続の確立と小さなやり取りは成功した後に大量転送が進まなくなります。第二は対称性で、同じリポジトリと同じ転送方式が失敗する一方で同じ経路上の別のホストは動作する、あるいは失敗が時間帯ではなくペイロードの大きさで変わります。第三は沈黙で、認証エラーもプロキシの拒否も名前解決の失敗もなく、ただ転送が完了しないだけです。
この三つがそろえばパケットサイズの仮説が正当化されます。DNS の失敗、期限切れのトークン、拒否された SSH 鍵、CONNECT を拒否するプロキシはそれぞれ独自のエラーを出し、どれも成功後の停止のようには見えません。テスト中に同じリポジトリ、転送方式、時間帯を保つことが、比較を誠実にします。
決める前に両方のインターフェースを比較する
同じセッションで Windows 側の見え方と Linux 側の見え方を集め、どのインターフェースが運んでいるかを推測するのではなくリポジトリのアドレスを保ちます。下のコマンドは最初に宛先を解決するので、経路の検索結果はクローンが実際に接続するサーバーを表し、これはブラウザーが表示した名前と異なる場合があります。VPN は試行の間にインターフェースのメトリックを変えうるので、両方の半分を近い時刻に実行します。
netsh interface ipv4 show subinterfaces
wsl -d Ubuntu -- bash -lc 'dest=$(getent ahostsv4 github.com | awk \'NR==1{print $1}\'); ip -br link show; ip route get "$dest"'
Linux 側の半分は、インターフェース名と経路選択がそこでしか意味を持たないため、Windows シェルに出力を貼り付けるのではなくディストリビューションの中で実行します。Windows シェルからの貼り付けは、間違った数値を自信たっぷりに報告します。何かを変える前に、両側のデバイス、選択された経路、MTU を記録します。
その数値を小さくすべきか決める
経路 MTU 探索がまさにそのために存在するため、経路が運べる量より大きいインターフェース MTU は自動的に障害ではありません。障害の形は探索が抑制されたときに現れ、ICMP メッセージが途中でフィルタリングされて送信側は上限を学べず、大きなパケットは消えて小さなものだけが通ります。これは経路の性質であり、Git の性質ではありません。小さなファイルが成功し、大きなファイルが決して終わらない接続がある理由もここにあります。
証拠がそれを支持するなら、Linux インターフェースでの一時的な変更が最も安価なテストです。利用可能な経路サイズを下回る値を選び、以前の値を記録し、比較が意味を持つように他はすべて一定に保ちます。小さい値で転送が完了すれば、それは偶然ではなく診断です。
ip -br link show dev eth0
sudo ip link set dev eth0 mtu 1380
ip -br link show dev eth0
設定をどこに置くべきか決める
テストから三つの選択肢が導かれ、通常はそのうち一つだけが適切です。小さい値で転送が直り、その値がこのネットワークに本当に必要な場合、設定には、ディストリビューションの起動フック、プラットフォームが管理するネットワーク構成、または文書化された手順というライフサイクルの所有者が必要です。値が何も直さないなら元に戻し、転送、プロキシ、認証の問いに戻ります。
起動フックがあるかどうかは、使用中の Windows と WSL のバージョン、および構成されたネットワークモードによります。Windows のネットワークをミラーリングすると、VPN とディストリビューションの関わり方が変わり、MTU の調整より重要な場合があるため、回避策を設計する前にモードを特定してください。一つの通信事業者や一つの VPN プロファイルに合う値は、次のための既定値ではありません。
避けるべきは魅力的な配置で、すべての対話シェルの起動ファイルに特権ネットワークコマンドを置くこと、あるいはスクリプトが一行実行できるように ip バイナリ全体にパスワードなしの sudo を与えることです。どちらも診断を恒久的な露出に変え、元の問題を後から見えにくくします。
きれいな起動の後に検証し、それから元に戻す
ディストリビューションを再起動するまでしか持たない変更は修正ではありません。ディストリビューションを再起動し、VPN に再接続し、ping や小さな HTTP 要求のような代用ではなく元の Git 操作を繰り返します。そのうえで新しいセッションでインターフェースが意図した値を持つことを確認します。
ip -br link show dev eth0
ip route get "$(getent ahostsv4 github.com | awk 'NR==1{print $1}')"
IPv4 の結果は同じホストの IPv6 接続について何も語らないため、記録した元の値は変更のそばに置いて実験をきれいに取り消せるようにし、どのアドレスファミリーを試したかを書き留めます。WSL のネットワークに関するドキュメントは、修正がどうあるべきかを決めるモードを説明しており、MTU の数値そのものはローカルの測定であって推奨値ではありません。