WSL2 で立ち上げたサーバに LAN 内の別 PC からアクセスする

  1. Windows GitBash (WSL 環境ではない) で $ node server.js とかやって、http://localhost:8080/ という開発サーバを立ち上げたとする。
  2. 次に、Windows マシンの Private IP を ipconfig などで確認する。
  3. そうすると、同じ LAN に接続している別の PC やスマホなどで、確認した Private IP を指定して http://192.168.1.10:8080/ などとして開発サーバにアクセスできる。

コレは通常どおりの動作だ。

一方、開発サーバを立ち上げるのが WSL2 環境だと、

  1. WSL2 で $ node server.js などとやって http://localhost:8080/ という開発サーバを立ち上げたとする。
    • Windows ホスト側では、http://localhost:8080/ で WSL2 上の開発サーバにアクセスできる。
    • http://192.168.1.10:8080/ ではアクセスできない。
  2. ipconfig で、WSL2 (「イーサネット アダプター vEthernet (WSL)」) の Private IP を確認する。
  3. Windows ホスト側から、WSL2 の Private IP を指定して http://172.26.64.1:8080/ などとして開発サーバにアクセスできる。
  4. 同じ LAN に接続している別の PC やスマホなどからは、http://192.168.1.10:8080/ でも http://172.26.64.1:8080/ でもアクセスできない。
    • http://172.26.64.1:8080/ (WSL2 の Private IP) が別のマシンから見えないのは妥当

…という状態になる。要するに、WSL2 のポートは、Windows ホスト側には localhost でのみ透過されているが、Windows ホストの Private IP や WSL2 自体の Private IP には接続されていないというワケだ。

WSL2 上で起動した開発サーバに、スマホからアクセスして UI を確認したいと思っていたので、なんとか WSL2 のポートを Windows ホスト側にまで開放できないかやり方を調べた。

上のブログに素晴らしい PowerShell スクリプトが載っていた。以下に転載。

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole("Administrators")) { Start-Process powershell.exe "-File `"$PSCommandPath`"" -Verb RunAs; exit }

$ip = bash.exe -c "ip r |tail -n1|cut -d ' ' -f9"
if( ! $ip ){
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

# All the ports you want to forward separated by comma
$ports=@(22,3000,8080);
$ports_a = $ports -join ",";

# Remove Firewall Exception Rules
iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";

# Adding Exception Rules for inbound and outbound Rules
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";

for( $i = 0; $i -lt $ports.length; $i++ ){
  $port = $ports[$i];
  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=* connectport=$port connectaddress=$ip";
}

# Show proxies
iex "netsh interface portproxy show v4tov4";

ポイントは $ports=@(22,3000,8080); の行。ココで、Windows ホスト側に透過させたい WSL2 のポート番号を列挙しておく。

コイツを適当な .ps1 ファイルとして保存し、管理者権限で実行してやることで、Windows ホストの Private IP http://192.168.1.10:8080/ でアクセスできるようになる。