August 10, 2020

Remote access to Windows WSL

Now that I have WSL 2 installed and running on my Windows 10 machine, I would like to access it via ssh. WSL runs a virtual network, so this requires some kind of forwarding or proxy. A side note. Remmina is a client for the Windows remote desktop protocol and would be a way to remote contact my Windows machine from linux (it is available as a Fedora package).

install NetSH

I thought for some reason I had to somehow install netsh on my windows machine, but I don't. It is already there.

An ssh server on WSL-Debian

apt-get install ssh
This fetches openssh-server and a bunch of other stuff. When it is done I have an ssh command (client) available as well as openssh-server installed.

I edit /etc/ssh/sshd_config and tell it to listen to port 2222 rather than the default (22). I leave PasswordAuthentication alone.

service ssh start
This appears to start the ssh server (apparently WSL2 does not use systemd). And indeed if I "telnet x.y.z 2222" from the windows shell, it is responding.

I try this:

chkconfig --level 35 ssh on
But there is no chkconfig command.

net-tools and ifconfig

apt-get install net-tools
This gives me ifconfig, which is how I am used to finding out the ip assigned to WSL2 on the virtual network. It is 172.23.25.42, at least for now.

Forward port 2222

First, let's open up port 2222 on the Windows Firewall.

Settings, Update and Security, Windows Security, Firewall and network protection.
Select "advanced settings" and give admin password.
Select "inbound rules", then "new rule" on the right.
Select rule type "Port", hit "Next"
Select "specific local port" and enter 2222, hit "Next"
Select "allow connection" and hit "Next"
Leave Public, Domain and Private all checked, hit "Next"
Enter a name and description, hit "Finish"

I called my rule "WSL2 ssh".

Now type in this huge mess (this needs to go in a script).

netsh interface portproxy add v4tov4 listenport=2222 listenaddress=0.0.0.0 connectport=2222 connectaddress=172.23.25.42
I put this into a BAT file, but of course this requires elevated privilege to run. So I fire up an admin power shell and type ./myssh.bat and it seems to take the command.

Poking around with netsh, I see deprecation warnings from Microsoft. They want you to transition to doing these sorts of things from the powershell and warn that they may remove netsh in the future.

Public network

The first time I tried this, it did not work. I played around (trial and error) and found that if I disabled the Public network firewall, it would work. So the instructions I had were in error about that, so I need to go back and change the rule, then turn the firewall on for Public, Private, and Domain.

Automate the forwarding

I set up a script "wsl.ps1" in c:\Users\Tom. Then to test it, I start a Powershell as administrator. I am told "running scripts is disabled on this system". I type this:
Set-ExecutionPolicy RemoteSigned
./wsl.ps1
I have no idea if this setting will persist or is only for this session.
I get his message:
The Script Exited, the ip address of WSL 2 cannot be found
There is a lot of discussion here on starting sshd automatically in WSL:
https://gist.github.com/dentechy/de2be62b55cfd234681921d5a8b6be11
Apparently the usual business of linux runlevels, chkconfig, init.d, systemd and all of that does not work as you might expect in WSL, so you have to monkey around with the "task scheduler" on the windows side of things.

Also, quite to my surprise, WSL starts up anew each time the user that installed it logs in. So "booting" from the point of view of WSL happens at each user login. Once we get ssh running, then it is just a matter of discovering our virtual IP number, splicing it into the following and issuing this command:

netsh interface portproxy add v4tov4 listenport=2222 listenaddress=0.0.0.0 connectport=2222 connectaddress=172.23.25.42

What works right now

I have the following at the end of .bashrc for wsl/debian user tom:
# Be sure ssh is running
SERVICE='ssh'
if ps ax | grep -v grep | grep $SERVICE >/dev/null
then
    echo "$SERVICE service is running"
else
    sudo /etc/init.d/ssh start
    echo "$SERVICE service started"
fi
This gets the job done as far as starting sshd (though I do have to give my password each time). While I am at it, I run /sbin/ifconfig -a to get the IP address for eth0 and write it down.

Then, on the windows side, what I do is to start a command prompt window (as user tom) and edit the file nsh.ps1 which looks like this:

iex "netsh interface portproxy add v4tov4 listenport=2222 listenaddress=0.0.0.0 connectport=2222 connectaddress=172.23.25.42";
I edit in my correct IP number and save it. Then I launch an administrator powershell (need to give a password again). Then:
cd \Users\Tom
./nsh.ps1
And this seems to get it done.


Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org