14

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?

3
  • 1
    Why can't you use the built-in OpenSSH client?
    – Ramhound
    Commented Feb 1, 2021 at 18:08
  • You mean installing OpenSSH for all nodes and calling and accessing them from the controller node? Does it work for LAN machines?
    – Marjan
    Commented Feb 1, 2021 at 18:23
  • Does what work for lAN machines?
    – Ramhound
    Commented Feb 1, 2021 at 18:55

3 Answers 3

14

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:

Note that this requires either a very old version of WSL or the (at this time) absolute latest version 2.0.0 pre-release.

  • 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:

    • (Older WSL releases): ssh -t <windowshost> "wsl ~"

    • 2.0.0 and later: `ssh -t '"C:\Program Files\WSL\wsl.exe" ~'

      While the WSL development team has mentioned that they want to get back to being able to use just wsl, that's not working just yet. For that reason, the double-quotes are required. The outer single-quote is for the Bash shell from which I'm calling ssh, and the inner double-quotes are for the CMD interpreter which is being called by the Windows OpenSSH.

    If by some outrageous coincidence you are using my answer here to launch OpenSSH with PowerShell with no logo, then the invocation becomes:

    ssh -t <windowshost> 'C:\Program` Files\WSL\wsl.exe'
    

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. See the path and quoting rules above if using WSL 2.0.0.

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.

4
  • Thank you so much for this comprehensive answer @NotTheDr01ds. You truly helped me out.
    – Marjan
    Commented Feb 2, 2021 at 21:08
  • If you are using OpenSSH and your account is part of local administrators, you'll need to setup public key in a special way see: docs.microsoft.com/en-us/windows-server/administration/openssh/…
    – Altair7852
    Commented Jul 25, 2022 at 0:30
  • This (Full remote WSL2 ssh support) works just great, thank you! Probably even a bit easier is the use of -J windowshost.local (or ProxyJump windowshost.local in the configuration), which at least also works in my scenario. ;-)
    – CodeFox
    Commented Sep 11, 2023 at 6:45
  • is this still so complicated to ssh into WSL2 from the Windows Host in 2024? Commented Jan 27 at 11:02
7

In Windows, forward your port from the public IP port to the WSL port in powershell as admin using:

netsh interface portproxy add v4tov4 listenport=$EXT_PORT listenaddress=0.0.0.0 connectport=$WSL_PORT connectaddress=127.0.0.1

To forward SSH access to WSL, $EXT_PORT=2222, $WSL_PORT=22 After above set up, from another computer in same LAN or VPN, do

ssh user@wslhostip -p 2222

Advantage of this approach is that no extra set up in WSL other than setting up SSH service as in any Linux distribution. It's also a generic way for setting up other networking service by just changing the forwarding ports.

1
  • Thank you for providing this solution, using VSCode Remote Server don't allow to jump or any specific command Commented Sep 15, 2023 at 14:53
-1

I know it's been a while since the post, but here is a useful answer that uses Remote -- Tunnels extension. https://stackoverflow.com/a/75389647

It appears that, for now, you need to manually install the CLI in WSL in order for it to work. The downloads can be found here. Since you are on Windows, I would recommend the x64 CLI download. When you extract the tar.gz file, you will get a file named code. I would recommend moving it to your home directory for ease. To open the tunnel, run ./code tunnel (from wherever you put the code file) to force the new CLI. If you use code tunnel it will still use the Windows version.

Source: https://github.com/microsoft/vscode/issues/171196

1
  • 1
    That seems to be a really different issue than what is being asked in this question. VSCode tunnels are for running VSCode on a remote system, not a generic SSH feature. Commented Feb 16, 2023 at 1:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .