はじめに
WSL2のDev Container環境でVPNに接続中 mvn install を実行したら、プライベートMavenリポジトリへの接続がタイムアウト。
結論から言うと、MTU(Maximum Transmission Unit)の問題でした。
同じ沼にハマっている人の助けになればと思い、原因の切り分けから解決までの流れを残しておきます。
環境
- ホストOS:Windows(VPNはWindows側で接続)
- WSL2:Ubuntu 22.04
- Docker:28.x(WSL2内で稼働)
- IDE:Cursor(Dev Containers拡張でコンテナ起動)
症状
Dev Container内でMaven Installを実行すると、プライベートリポジトリへの接続でタイムアウトが発生。
[FATAL] Non-resolvable parent POM:
Could not transfer artifact from/to private-maven-repo
(https://private-gitlab.example.com/...):
Connect to private-gitlab.example.com:443 failed: Read timed out
原因の切り分け
ここからが本題です。VPNなしでコンテナを起動し、後からWindows側でVPN接続した状態で確認していきます。
Step 1:コンテナ内から疎通確認
$ curl -v --connect-timeout 5 https://private-gitlab.example.com
* Trying 203.0.113.10:443...
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* Connection timed out after 5000 milliseconds
TLS Client Helloを送った後にタイムアウト。接続自体はできていない。
Step 2:WSL側(コンテナの外)から確認
$ curl -v --connect-timeout 5 https://private-gitlab.example.com
* Connected to private-gitlab.example.com (203.0.113.10) port 443 (#0)
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL connection timeout
TCP接続は成功しているのに、TLSハンドシェイクでタイムアウト。これがヒントでした。
Step 3:MTUの確認
# WSL側
$ ip link show eth0
2: eth0: ... mtu 1400 ...
# コンテナ側
$ docker exec <container> cat /sys/class/net/eth0/mtu
1500
VPNはパケットを暗号化のために追加ヘッダーで包むので、実際に流れるパケットサイズが元より大きくなります。MTUが大きいままだとこのオーバーヘッド分だけサイズ超過してパケットがドロップされる、というのが原因でした。
解決手順
WSL2・Docker・コンテナのMTUをすべて1200に下げることで解決しました。
VPNなしでDev Containerを起動した後、Windows側でVPN接続してから以下を実行します。すべてWSL側(コンテナの外)で実行します。
1. WSL2のMTUを下げる
sudo ip link set eth0 mtu 1200
この時点でWSLからの疎通を確認:
curl -v --connect-timeout 10 https://private-gitlab.example.com
# → TLSハンドシェイクが通るようになる!
2. DockerブリッジのMTUを下げる
sudo ip link set docker0 mtu 1200
3. コンテナを再起動する
docker restart <container-name>
4. コンテナ内のMTUを下げる
コンテナ内に ip コマンドがない場合は、nsenter でホスト側から変更できます。
PID=$(docker inspect -f '{{.State.Pid}}' <container-name>)
sudo nsenter -t $PID -n ip link set eth0 mtu 1200
5. 疎通確認
docker exec <container> curl -vk --connect-timeout 10 https://private-gitlab.example.com
# → HTTP 302が返ってくれば成功!
6. ビルド実行
docker exec -it <container> bash
cd /workspace
./mvnw install -s ./settings.xml -Dmaven.test.skip=true
# → 成功!
注意点
MTU設定は永続化されない
ip link set によるMTU変更は一時的なもののようで、以下のタイミングでリセットされるみたいです:
- WSLの再起動(
wsl --shutdown) - コンテナの再作成(Rebuild Container)
VPN経由のビルドが必要になるたびに、手順1〜4を再実行してください。
(毎回打つのは面倒なので、スクリプト化しておくと便利です。)
おしまい!