WSL2 の localhostForwarding 機能がうまくうごかない

WSL2 の localhostForwarding 機能を使うと、WSL2側で listen したポートを自動的にWindows側で port forwarding してくれるので、Windows側からは localhost でWSL2側で listen しているポートにアクセスすることができる。

しかし、自分の環境ではアクセスはできるが、頻繁にハングすることがあり困っていた。

そのため、WSL2の localhostForwarding 機能を無効にして、かわりに netsh interface portproxy add v4tov4 コマンドを使って手動で port forwarding することにした。

まず、WSL2側のIPアドレス(WSL2が使用しているHyper-V仮想スイッチに接続しているアダプタのIPアドレス)を調べる。これは通常はeth0であるので、ip route |grep 'eth0 proto'|cut -d ' ' -f9 で取得することができる。ここで、Windows側からは bash.exe 経由で実行できるので、bash -c "ip route |grep 'eth0 proto'|cut -d ' ' -f9" で取得できる。

次に netsh interface portproxy add v4tov4 listenaddress=<host ip> listenport=<port> connectaddress=<wsl ip> connectport=<port> コマンドを使うことにより port forwarding することができるので、さきほど取得した WSL2 の IP を使って port forwarding する。 PowerShell スクリプトにまとめると以下の通りとなる。

wsl-proxy.ps1:

$WSL2_IPV4=bash -c "ip route |grep 'eth0 proto'|cut -d ' ' -f9"
$HOST_IPV4="0.0.0.0"
$PORT=$Args[0]
netsh interface portproxy delete v4tov4 listenaddress=$HOST_IPV4 listenport=$PORT
netsh interface portproxy add v4tov4 listenaddress=$HOST_IPV4 listenport=$PORT connectaddress=$WSL2_IPV4 connectport=$PORT
netsh interface portproxy show v4tov4

このスクリプトを管理者権限で起動したターミナルから実行する。

> wsl-proxy.ps1 3000

これで、ブラウザ等から localhost:3000 にアクセスすると、WSL2の 3000 ポートに転送されてアクセスできるようになる。

なお、このときの環境は以下のとおりである。

参考