VPN接続状態のWSL2内でGithubにPush/Pullをしても応答が返ってこなかった話

お疲れ様です。
株式会社アドグローブ ソリューション事業部の佐藤です。

WindowsでDockerを使用する開発を行う場合、WSL2(Ubuntu)を使用することが多いと思います。
また、セキュリティ上の観点からVPNを接続して開発することも多いのではないでしょうか。

今回の記事では、VPN接続とWSL2(Ubuntu)環境で実際に起こった問題と、解決した方法についてご紹介します。

躓いた背景

VPNを接続しIP制限しているリポジトリからPullをしてローカルに取ってこようとした際に、数分経っても終わらず、通信途中で固まってしまっているような状態が見られました。
また、VPN接続中にWSL2(Ubuntu)内でapt installなどを行ってみるとこちらも同じような状態で固まっていました。

原因を調査するため
試しにVPNを切断しIP制限のないリポジトリからPullをしてみたり、apt installなどを行ってみたりすると問題なく実行されることが確認でき、VPN周りで何か問題が起こっていることが分かりました。

詳細

原因

主な原因は、WSL2側とVPN側でMTU*1のサイズが合っておらず、通信経路で食い違っている可能性があることでした。

  • VPNのMTU値は1400バイトに設定されていました。
C:\Users\yuki.sato>netsh interface ipv4 show interfaces
Idx     Met         MTU          状態                 名前
---  ----------  ----------  ------------  ---------------------------
 63          25        1400  connected     VPN-NAME
  • WSL2(Ubuntu)側のMTU値は1500バイトでした。
$ ip addr show dev eth0 | grep mtu
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000

上記のように、接続元(WSL2)と接続先(VPNルーター)のMTU値が異なる場合、小さいほうが採用される仕組みになっています。
VPNを経由してデータを送信する時、データサイズが1500バイトだと、1400バイト以下になるように分割処理を行ってから送信するため通信が遅くなります。

今回のような固まってしまう状態に陥るのは、通信経路のどこかで分割を禁止するDFフラグ*2が立ち、送信元にICMPパケット*3を送って最適なMTU値を教えてもらえるのですが、WSL2ではなぜかICMPパケットを受信できないみたいなので固まったように見える状態になるみたいです。
そのため、予めWSL2側のMTU値を低く設定しておくと分割処理がなくなるので結果的に早くなることがあります。

WindowsのコマンドプロンプトやPowerShellなどからだと、基本的に今回のような設定をしなくてもVPNでも通信できるのですが、こちらでは問題なくIMCPパケットを受信できているからだと思われます。
(ただし、分割処理を挟むため通信速度は落ちてしまいます。)

解決方法

解決方法は、以下のコマンドをWSL2(Ubuntu)内で実行を行うことです。

$ sudo ip link set eth0 mtu 1200

数字の部分がMTU値を設定する値になります。

私の環境では、1200に設定することで正常に通信が行われました。
PCやVPNの種類によっては、MTU値をVPNと同様の値で場合問題なかったり、さらに小さい値に変更することで解決できると思います。

自動設定方法

上記の解決方法だけではWSL2起動時に設定されないため、起動時に毎回コマンドを入力する必要があります。
そのため、.bashrc/etc/bashrcなどの起動時に読み込まれるファイルに上記のコマンドを叩くよう設定してあげる必要があります。
今回は、.bashrcファイルに記述します。

まずWSL2(Ubuntu)に入り.bashrcを開きます。

$ vim ~/.bashrc

.bashrcファイル内の最後の行に解決方法で入力したコマンドを追記して保存します。

sudo ip link set eth0 mtu 1200

その後、PowerShellからWSL2を再起動を行います。

C:\Users\yuki.sato>wsl.exe --shutdown

再起動後、WSL2内でMTU値を確認します。

$ ip addr show dev eth0 | grep mtu

下記のようにMTU値が設定した値になっていることを確認できたら完了となります。

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1200 qdisc mq state UP group default qlen 1000


あとがき

今回のようなVPNなどの環境周りで問題が発生しますと、開発中は原因に気づきにくいと感じました。
原因を調査する段階では時間を使いましたが、案外単純に解決できるもので良かったです。
またWSL2内では固まってしまうので今回の設定を行いましたが、MacやLinux, Windows環境などでMTU値を確認し、VPNのMTU値と同じかそれ以下の値に設定してみると通信速度が向上する可能性があるので試してみるのもいいと思います。

今回の記事がみなさまのトラブル時の一助となれば幸いです。
最後までお読みいただきありがとうございました!

参照サイト


アドグローブでは、さまざまなポジションで一緒に働く仲間を募集しています!
詳細については下記からご確認ください。みなさまからのご応募お待ちしております。

採用情報

*1:「Maximum Transmission Unit」の略、1回の転送で送れるパケットの最大容量のこと

*2:「Don't Fragment bit」の略、経路途上でのデータグラムの分割(フラグメンテーション)を許可するか否かを記したもの

*3:「Internet Control Message Protocol」の略、データが目的の宛先にタイムリーに到達しているかどうかを判断するために使用されるネットワーク層のプロトコル