WSL2 Network Forwarding

Share on:
700 Words | Read in about 3 Min | View times

Overview

With the WSL2 Released, Microsoft has made a big change on the system architecture, including changing from the default bridged network adapter to a hyper-v virtual network adapter.

The new version of WSL is built on Hyper-V, which provides independent virtual network adapter for the virtual matchine. Therefore, WSL2 cannot share the network with host directly. The work around is to forward the TCP ports of WSL2 to the host OS.

In addition, the virtual adapter on WSL2 changes it’s ip address during reboot, which makes it tough to implement a run once solution. So we need a solution to auto update the forwarding TCP ports during host OS reboot.

TCP ports forwarding

If we had installed multiple version of WSL on Windows 10, we need to set the WSL2 as the default distribution:

1// Query versions of different WSL distribution
2> wsl -l -v
3  NAME            STATE           VERSION
4* Ubuntu-20.04    Running         2
5  Ubuntu-16.04    Stopped         1
6
7// set your own default distribution
8> wsl --set-default Ubuntu-20.04 2

We will open the right version of WSL, Ubuntu20.04 for example, when executing wsl.exe in powershell or command line only if we had set the Ubuntu20.04 as the default distribution.

Now we create a powershell script wslbridge.ps1 to implement TCP ports forwarding:

 1# Run as administrator
 2if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
 3    Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
 4    exit;
 5}
 6
 7# Read ip address of WSL2
 8$remoteport = wsl ifconfig eth0 | wsl grep 'inet '
 9$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
10
11if( $found ){
12  $remoteport = $matches[0];
13} else{
14  echo "The Script Exited, the ip address of WSL 2 cannot be found";
15  exit;
16}
17
18#[Ports]
19# Modify the forwarding ports here, seperated with comma mark
20$ports=@(80,443,3633,4101,4102,10501);
21
22#[Static ip]
23$addr='0.0.0.0';
24$ports_a = $ports -join ",";
25
26# Remove old Windows firewall rule
27iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";
28
29# Add new Windows firewall rule for inbound and outbound
30iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";
31iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";
32
33for( $i = 0; $i -lt $ports.length; $i++ ){
34  $port = $ports[$i];
35  iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$addr";
36  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$remoteport";
37}

After executing the wslbridge.ps1 script, we can check whether the TCP ports forwarding takes effect. Execute the following command in powershell:

 1> netsh interface portproxy show all
 2Listen on ipv4:                 Connect to ipv4:
 3
 4Address         Port        Address         Port
 5--------------- ----------  --------------- ----------
 60.0.0.0         80          172.18.48.151   80
 70.0.0.0         443         172.18.48.151   443
 80.0.0.0         3633        172.18.48.151   3633
 90.0.0.0         4101        172.18.48.151   4101
100.0.0.0         4102        172.18.48.151   4102
110.0.0.0         10501       172.18.48.151   10501

Update forwarding ports during reboot

Press Win + R and input shell:startup, open the Windows startup directory C:\Users\[Your-User-Name]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup.

We can place some vbs scripts here and Windows will auto execute these them during reboot.

Now we can write a vbs script, wsl2autostart.vbs for example, to auto update the forwarding ports on the initialization for WSL2 startup, and update the Windows firewall rules in the meanwhile.

WSL2 will not run the init services on Windows reboot, so manually execution is required. We can put it into the vbs script.

1' run the Linux custom init script as root
2Set ws = WScript.CreateObject("WScript.Shell")
3ws.run "wsl -d Ubuntu-20.04 -u root /etc/init.wsl"
4
5' start the Windows firewall forwarding rules
6Set app = CreateObject("Wscript.Shell")
7app.run "powershell -ExecutionPolicy Unrestricted -file wslbridge.ps1"

The content of /etc/init.wsl depends on your own requirements. For example,

1#! /bin/bash
2
3cd /home/zhxilin/dev/script
4
5./runrendis.sh
6./runmysql.sh
7./runnginx.sh
8./rundistccd.sh
Prev Post: 『What's std::ios::sync_with_stdio(false) and std::cin.tie(nullptr)?』
Next Post: 『Update multiple versions of dev tools under Ubuntu』