SSH into WSL from another machine on the network

I'm trying to deploy a distributed systems using Windows machines. However, the code I want to compile and run on this system should get complied in a Linux-based environment. Thus, I downloaded and installed WSL and Ubuntu on all nodes. Now, I need to SSH into the worker nodes from the controller node. Is there any way to do so?


Solution 1:

SSH into WSL1

If the WSL instances are WSL1, then you can install SSH on those instances and access them directly. It sounds like you may have multiple WSL "node" instances on one Windows host, and if that's the case, then you should, of course, have a different port number for each SSH server in its /etc/ssh/sshd_config. Note that you'll still need a reliable way to start the SSH services on those instances (see below).

SSH into WSL2

If you must run WSL2 on the node instances, then you'll need to go a slightly different route, since as you seem to be aware (from your comment on the question), accessing them from the LAN is not straightforward, but there are multiple options to make it work.

To start with, check out this answer that I've provided on another similar question, just to understand the issue better.

Simplified option for those just needing remote command-line access to WSL

This doesn't sound like it's an option for your original question, but I'm including it here for others that may not need a full-blown ssh solution:

  • First set up OpenSSH server on the Windows' host.

  • As long as you can directly access the Windows host, you can ssh directly into PowerShell on the Windows host.

  • Then, from the CMD ssh command-line, you can just run wsl ~ to get access to your WSL instance remotely.

  • This can even be simplified into a one-liner with ssh -t <windowshost> "wsl ~"

Full remote WSL2 ssh support

In your case, it sounds like your controller will need automatic ssh access to the remote WSL2 instances. That can still be done, but requires a little more effort. The way that I handle this on my network (for Ansible configuration of those nodes) is to:

  • As with the simplified option, set up OpenSSH server on the Windows' host. I use the default port 22 for the "host" ssh, but you don't necessarily have to.

  • Next, set up SSH for each WSL instance. Here, I use a different port number for each instance.

  • Optional, but recommended, set up both the Windows OpenSSH and the WSL instances with your public key in ../ssh/authorized_keys (on Windows OpenSSH, this is under your %userprofile%/.ssh directory. In Linux/WSL, of course, it's in ~/.ssh.

Now, since each Windows host can access the WSL2 instances on localhost, you can use the Windows SSH as a jumphost to the WSL2 SSH sessions.

For instance:

ssh -o "ProxyCommand ssh -W %h:%p windowshost.local" -o "StrictHostKeyChecking=no" -p 2224 localhost

This uses the port 22 OpenSSH server running on Windows at "windowshost.local" (insert your name or IP here) to access the WSL instance running on its port 2224. Note that localhost is always going to be localhost here, since port 2224 is local to "windowsthost.local".

StrictHostKeyChecking needs to be off in this case, since you are going to have a lot of "localhosts" in your known_hosts, and ssh doesn't take into account jumphosts when looking up keys.

Of course, this can be greatly simplified with a ~/.ssh/config:

Host wsl-ubuntu.windowshost.local
HostName localhost
ProxyCommand ssh -W %h:%p windowshost.local
StrictHostKeyChecking no
Port 2224

You can then access the WSL session directly via ssh wsl-ubuntu.windowshost.local. Make the hostname whatever you want in the config.

Note that this jumphost technique is only needed for automation which requires "real" SSH into the WSL instance. If you just need to "access" the WSL instance's terminal remotely, you can shortcut it with:

ssh -t windowshost.local wsl or ssh -t windowshost.local wsl -d Ubuntu20.04

The first one just launches into the default WSL instance. The second allows you to select a specific instance/distribution by name.

Starting SSH in WSL

You could get fancy and try to bring up your WSL nodes and their SSH servers when Windows boots via Windows Task Scheduler or another means. But if you use the Windows SSH server technique mentioned above (including for your WSL1 hosts), then you can bring them up on demand via:

ssh -o "RemoteCommand=wsl -d Ubuntu-20.04 sudo service ssh status ^|^| sudo service ssh start" windowshost_ip_or_name

This logs into the Windows host and uses the wsl command to access the WSL instance by name, running the command to check whether SSH is running and start the service if it isn't. Note that the ^|^| is escaping the || for CMD, since CMD is the default shell when you SSH into a Windows OpenSSH server (although this can be changed).

Other options

You can also change your Windows ssh default shell to be WSL, so that when you connect to OpenSSH on Windows, it drops you directly into WSL. I won't repeat the steps here, but see these Microsoft instructions and my related question/answer on how to extend this to WSL.

Personally, I don't recommend this approach if you ever think you may use more than one WSL instance. I change my default shell to PowerShell Core, which still allows me easy access to WSL as documented above.