WSL 2 SSH server setup - chhwang/devel-note GitHub Wiki

Preliminaries

  1. Install WSL 2 (available since Windows 10 version 2004) and enable Hyper-V.

  2. Install any Linux distro (e.g. Ubuntu) from Microsoft Store. Run the distro to create your account and complete the installation.

Linux-side Setup

  1. Run the Linux distro.

  2. Re-install OpenSSH server as follows.

    sudo apt remove --purge openssh-server
    sudo apt install openssh-server
    
  3. Edit /etc/ssh/sshd_config.

    • Open /etc/ssh/sshd_config (e.g. sudo vi /etc/ssh/sshd_config).
    • Write PasswordAuthentication yes
    • Write AllowUsers YOUR_ACCOUNT_NAME (where YOUR_ACCOUNT_NAME should be replaced by your Linux account name).
    • Save the file and exit.
  4. (Optional) For security, allow only specific IP addresses to login. E.g. to allow 192.30.118.x and 194.57.240.32 only, do as follows. edit as follows.

    • Open /etc/hosts.deny (e.g. sudo vi /etc/hosts.deny).
    • Write ALL EXCEPT sshd: 192.30.118.0/24 194.57.240.32.
    • Save the file and exit.
  5. Full restart the SSH server.

    sudo service ssh --full-restart

  6. Allow SSH server to start without password.

    • Run sudo visudo.
    • Add %sudo ALL=NOPASSWD: /etc/init.d/ssh after %sudo ALL=(ALL:ALL) ALL.

Windows-side Setup

  1. Copy and save the following PowerShell script under a permanent directory. (File is uploaded here.) Note that this script is needed because the IP address of WSL 2 changes whenever we reboot the system, so this script automatically change the port forwarding rule at every startup. Suggested here: link.

    $remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
    $found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
    
    if( $found ){
        $remoteport = $matches[0];
    } else{
        echo "The Script Exited, the ip address of WSL 2 cannot be found";
        exit;
    }
    
    #[Ports]
    
    #All the ports you want to forward separated by coma
    $ports=@(22);
    
    #[Static ip]
    #You can change the addr to your ip config to listen to a specific address
    $addr='0.0.0.0';
    $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 delete v4tov4 listenport=$port listenaddress=$addr";
        iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$remoteport";
    }
    
  2. Open Windows Task Scheduler (search for 'task' from the search bar).

  3. Select "Create Task..." at the right-side pane and configure the task as follows.

    • In General tab,
      • Name: WSL 2 SSH Server
      • Select "Run with highest privileges"
    • In Triggers tab, click the "New" button and create a trigger:
      • Begin the task: At startup
      • Delay task for up to: 10 seconds
    • In Actions tab, click the "New" button and create an action that starts the SSH server:
      • Action: Start a program
      • Program/script: %windir%\System32\bash.exe
      • Add arguments: -c "sudo /etc/init.d/ssh start"
    • In Actions tab, click the "New" button and create an action that runs the aforementioned PowerShell script:
      • Action: Start a program
      • Program/script: powershell.exe
      • Add arguments: the path you stored the script in 1.
    • Click "OK" to save the task.
  4. Select the task created in 3. (the name is "WSL 2 SSH Server"), and click "Run" at the right-side pane.

Verification

  1. To check whether the port forwarding script ran correctly, open up PowerShell and run the following.

    netsh interface portproxy dump

    It should print

    add v4tov4 listenport=22 connectaddress=WSL_IP_ADDRESS connectport=22

    where WSL_IP_ADDRESS is the IP address you see at the Linux-side.