どういう問題?
WSL2でgit pullコマンドを実行したときに下記のようなエラーが出た。
$ git pull
fatal: unable to access 'https://github.com/hoge/fuga/': gnutls_handshake() failed: Error in the pull function.
環境
WSL2 Distribution: Ubuntu-20.04
git version: 2.38.1
原因
「gnutls_handshake() failed: Error in the pull function.」でググるとgit config
の問題やらproxy
やら出てきますが、configはすべて設定済みで不備もないし、proxyは特にプロキシサーバーを経由させるようなこともやってないしなんだろうなと途方に暮れていました。
根気強く調べていると、WSLのissueで下記のようなやり取りがありました。
そこに書いてあった内容でベストプラクティスを見つけました。 要約すると下記のような感じです。
問題はVPNのMTU値とLinux側のMTU値の不一致にあります。
まず、Windows PowerShell (管理者として実行)でnetsh interface ipv4 show subinterfaces
を実行し、最初の行に注目してください。これは、VPN で許可される MTU の大きさを示しています。
次に、Linux (WSL2内部) のコンソールでip adrr
を実行し、eth0'で始まる行に注目してください。そのMTUは、上記のものと一致するか、より低いものでなければなりません。
私の場合、LinuxのMTUの方が高かったです。
なるほど、実際に確認してみると
PS > netsh interface ipv4 show subinterfaces
MTU MediaSenseState 受信バイト 送信バイト インターフェイス
------ --------------- ----------- ---------- -----------------
4294967295 1 0 367360 Loopback Pseudo-Interface 1
1500 1 24369484190 752500695 イーサネット 2
1404 1 1008731 46221951 vEthernet (WSL)
$ ip addr
...
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
...
...
あー、なんとなく分かった。
VPN側だとMTU値がWSL用に1404で割り当てられているけど、WSLでは1500になっていてVPN < WSL
でダメって感じかな?
対処法
対処法もissueに書いてありました。
以下のコマンドで即座に解決しました。
sudo ip link set dev eth0 mtu 1400
(MTU値をVPNに合わせて更新してください)
私はこれを ~/.bashrc の中に入れて、自分のアカウントの sudoers NOPASSWD の中に /usr/sbin/ip を入れています。
とりあえずWSL2で叩いてgit pullできるかやってみましょうか。
$ sudo ip link set dev eth0 mtu 1404
$ git pull
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 4 (delta 3), reused 4 (delta 3), pack-reused 0
Unpacking objects: 100% (4/4), 391 bytes | 391.00 KiB/s, done.
From https://github.com/hoge/fuga
b91f4ab..507018d main -> origin/main
Updating b91f4ab..507018d
Fast-forward
"books/\343\200\220Python\343\200\221pytest\343\201\247\347\237\245\343\201\243\343\201\246\343\201\212\343\201\215\343\201\237\343\201\204\343\201\223\343\201\250.md" | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
出来ましたね!
あとは起動時にこのコマンドが走れば良いので、私は下記のような処理をfish_greeting.fish
に追記しています。
(bashやzshの方は.bashrcや.zshrcに追記すれば良いと思います)
echo {sudo password} | sudo -S ip link set dev eth0 mtu 1404 > /dev/null 2>&1
おまけ(MTUとは?)
下記の記事が参考になりました。
抜粋すると
MTU (Maximum Transmission Unit)とは、 ノードが隣接したネットワークへ、1回の通信で転送可能な最大のデータグラムサイズです。
TCP/IPの階層モデルにおいては、 リンク層の通信メディア(Ethernetなど)の違いによってMTUのサイズが異なるため、 その上位のインターネット層におけるIPデータグラム(IPパケット)のサイズもこのMTUに合わせて決められます。 さらにトンネリングなどの追加ヘッダを利用する通信方式を利用する場合には、 増えたヘッダの分だけペイロードを減らす必要があるので、 MTUがネットワーク層において、より小さな値となります。
なるほどね、なんか昔に勉強したような…。「マスタリングTCP/IP―入門編―」もう一度読み直しましょうか…。