他のPCから自分のPCのWSLに接続したい
WSL2上で動かしているROSに,同じネットワーク上の別のPCから接続したかった.
WSL2はWindowsホストとは別のIPアドレスを持つ仮想マシンとしてNAT越しに動いているため,外部のPCからWSL2に直接アクセスすることはできない.そこで,Windowsホストの特定のポートに来た通信をWSL2に転送する形で対応する.
1. Windowsホストに疎通できるようにする
まずは,そもそもWindowsホストにPingが通るようにする.Windows Defender ファイアウォールの受信規則を追加する.
- コントロールパネルからWindows Defender ファイアウォールを開く
- 左側の「詳細設定」を選択
- 「受信の規則」を右クリックし,「新しい規則…」を選択
- 「カスタム」を選択して「次へ」
- 「すべてのプログラム」を選択して「次へ」
- プロトコルの種類で「ICMPv4」を選択し,「カスタマイズ…」をクリック
- 「特定のICMPの種類」を選択して「エコー要求」にチェックを入れ,「OK」→「次へ」
- ローカルIPアドレスとリモートIPアドレスに「任意のIPアドレス」(もしくは必要な範囲)を指定して「次へ」
- 「接続を許可する」を選択して「次へ」
- 「ドメイン」「プライベート」「パブリック」すべてにチェックを入れて「次へ」
- 分かりやすい名前を付けて「完了」
参考:Windows WSL 2 can’t ping host machine
この設定で,とりあえず他のPCからWindowsホストにPingが通るようになる.なお,この設定はコマンドでも可能で,後述の netsh advfirewall を使う.
2. WSL2へのポートフォワーディング設定(PowerShell・管理者権限)
netsh コマンドでポートフォワーディングを設定すると,Windowsホストのポートに来た通信がWSL2に転送され,他のPCからWSL2上のプロセスに接続できるようになる.
以下は,ROS Bridge(WebSocketの9090番)を対象にした場合の設定.
# ポートフォワーディング(172.19.35.202 は WSL2 のIPアドレス)
netsh interface portproxy add v4tov4 listenport=9090 connectport=9090 connectaddress=172.19.35.202
# ファイアウォール
netsh advfirewall firewall add rule name="WSL2 Firewall Unlock for ROS" dir=in action=allow protocol=TCP localport=9090
netsh advfirewall firewall add rule name="WSL2 Firewall Unlock for ROS" dir=out action=allow protocol=TCP localport=9090
確認.
netsh interface portproxy show all
netsh advfirewall firewall show rule name="WSL2 Firewall Unlock for ROS"
消すとき.
netsh interface portproxy delete v4tov4 listenport=9090 listenaddress=*
netsh advfirewall firewall delete rule name="WSL2 Firewall Unlock for ROS"
WSL2のIPアドレスはWSLを再起動するたびに変わる.そのため,起動のたびに wsl hostname -I でアドレスを確認して portproxy を貼り直す必要がある.
wsl hostname -IROSの場合の注意
上記のポートフォワーディングは,接続先のポート番号が固定されている通信であればうまくいく.
一方でROS1のノード間通信は,マスター(11311番)以外のポートが起動のたびに動的に割り当てられるため,ポートを1つ開けるだけでは通信できない.そのため,ポート番号が固定されているROS Bridge(9090番)を経由させる方法をとった.このあたりは以下の記事が分かりやすい.
【ROS/WSL2】WSL2上のROSと外部PCで通信してみたかった - Qiita
【ROS/WSL2】ROS Bridgeを使用した複数マシン(複数ROS master)間の通信 - Qiita
Windows 11(22H2以降)とWSL 2.0.0以降の環境であれば,.wslconfig でネットワークをミラーモード(networkingMode=mirrored)にすることで,WSL2がホストと同じネットワークインターフェースを共有するようになり,こうしたポートフォワーディングの設定自体が不要になる.