Short answer (TL;DR)
My preferred method, detailed below, is to install the Windows OpenSSH server and use it as a jump host to access Ubuntu in WSL2. Don't let the length of this answer scare you. I just tend to explain in (perhaps too much) detail ... ;-)
Explanation
The core issue here is that WSL2 is on a separate, NAT'd, virtual network inside a Hyper-V virtual machine on the Windows system. That means that we have to provide a route via tunnel, proxy, or forwarding from the "real" network to this virtual network where Ubuntu resides.
There have been several solutions to this over the years, but the best ones (IMHO) no longer (at least currently) work with the latest version of WSL installed from the Microsoft Store.
Most solutions rely on port forwarding, as with the tutorial you mentioned in the comments. Historically, that has been complicated by WSL2 using a different IP address each time it starts (also mentioned in that tutorial). However, there's some good news on that front -- The latest WSL release (starting with 1.1.0) in the Microsoft Store now attempts to use the same IP address on each restart. So if you want to use the netsh interface portproxy
method mentioned in that tutorial (and also the WSL docs), you can in theory do it once without needing to worry about "per reboot" mechanics.
The Process
That said, for SSH into WSL2, I still prefer using a simple SSH jump host. I'll cover a version of this setup here in this answer, but if you want to configure SSH keys, also see my original Super User answer on the topic.
For password based (non-key)
One time installation/configuration of the Windows OpenSSH server. Full instructions in the link, but essentially, in an Admin PowerShell:
# Install the feature:
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# Start the sshd service
Start-Service sshd
# OPTIONAL but recommended:
Set-Service -Name sshd -StartupType 'Automatic'
# Confirm the Firewall rule is configured. It should be created automatically by setup. Run the following to verify
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
} else {
Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
}
One-time configuration of the Ubuntu OpenSSH server -- Essentially edit /etc/ssh/sshd_config
to modify the port number. I'll use 2222 for example below. Restart the service, of course (sudo systemctl restart ssh
if using Systemd; sudo service ssh restart
if not).
For the examples below, I'm going to assume that:
- Your Windows host with the Ubuntu that you want to access is named
Bubblegum
and it is accessed on the network as bubblegum.local
(an mDNS name), but you can also substitute IP address here.
- Your username on the Windows host is
helga
- Your Ubuntu username is
hc
- Your Ubuntu SSH port set up above is 2222.
Then you can access Ubuntu through SSH from another system on the network via something like:
ssh -J helga@bubblegum.local -p 2222 hc@localhost
This tells SSH to first login to the jump host (the Windows SSH server), then connect from that host to localhost:2222
, which is the Ubuntu SSH server. If your usernames are all the same, you can omit them entirely. So it can be as clean as:
ssh -J bubblegum.local -p 2222 localhost
You can simplify it even further with a ~/.ssh/config
file for the clients.
Host bubblegum_ubuntu # Can be whatever you want
Hostname localhost
User hc # If needed
Port 2222
ProxyJump helga@bubblegum.local
# Optional, but useful if you access more than one
# WSL distribution on the system to avoid unnecessary
# man-in-the-middle warnings due to different host keys.
UserKnownHostsFile ~/.ssh/known_hosts_bubblegum_ubuntu
With that in place, you can just:
ssh bubblegum_ubuntu