SSH and Remote Access in WSL
If you just want to open a WSL terminal locally on Windows, you don't actually need SSH. But SSH becomes very useful when you want to do the following:
- Connect to WSL uniformly from Windows Terminal, VS Code, or other terminal tools
- Log in to your WSL environment from another machine on the LAN
- Run development services long-term in WSL, with SSH forwarding or remote development
This document splits the entire pipeline into two layers:
- First get the SSH service inside WSL working properly
- Then decide whether to allow only Windows local access or access from other LAN machines
1. Installing OpenSSH in WSL
The following examples use Ubuntu / Debian:
sudo apt update
sudo apt install -y openssh-server
After installation, first confirm the service file exists:
sshd -T | head
If the system says sshd is not found, it usually means openssh-server has not been installed successfully.
2. Configure the Minimum SSH Security Baseline
Edit the configuration file:
sudo nano /etc/ssh/sshd_config
It is recommended to at least confirm these settings:
Port 22
ListenAddress 0.0.0.0
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin no
AuthorizedKeysFile .ssh/authorized_keys
The default approach here is:
- Prefer public key authentication
- Don't allow root login by default
- Don't keep password login by default
If you are just testing temporarily, you can also change PasswordAuthentication to yes, and turn it back off after confirming public key login works.
3. Generate and Import the Public Key
If you don't have an SSH key yet, generate one on the client machine first. Using Windows PowerShell as an example:
ssh-keygen -t ed25519 -C "your_email@example.com"
After generation, view the public key content:
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub
Then append the public key to the WSL user's authorized_keys:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
If permissions are wrong, SSH will often simply ignore this file, so don't skip this step.
4. Start the SSH Service
First determine whether your WSL has systemd enabled.
Method A: systemd Enabled
If you have already enabled systemd in your /etc/wsl.conf:
[boot]
systemd=true
Then you can directly use:
sudo systemctl enable --now ssh
sudo systemctl status ssh
After modifying wsl.conf, remember to execute once in Windows:
wsl --shutdown
Then re-enter the distribution.
Method B: systemd Not Enabled
If you haven't enabled systemd, you can start manually first:
sudo service ssh start
sudo service ssh status
This approach also works, but note: after the WSL distribution exits, the service usually won't persist like a traditional Linux server.
5. Verify Windows Local Access First
Do a local test in Windows PowerShell first:
ssh <your_user>@localhost
As long as this step doesn't work, don't proceed with LAN port forwarding. The portproxy only forwards requests to WSL -- it cannot solve SSH issues inside WSL itself.
If you are using a non-standard port:
ssh <your_user>@localhost -p <port>
6. Allow Other LAN Machines to Access WSL
By default, other LAN devices cannot stably access WSL directly. The more reliable approach is:
- Open a listening port on Windows
- Forward that port to the SSH port of the current WSL instance
6.1 Get the Current WSL IP
Execute in an elevated PowerShell:
$distro = "Ubuntu"
$wslIp = wsl -d $distro -- bash -lc "hostname -I | awk '{print \$1}'"
$wslIp
Change $distro to your distribution name.
6.2 Add Windows Firewall Rule
Still in an elevated PowerShell:
New-NetFirewallRule `
-DisplayName "WSL SSH 22" `
-Direction Inbound `
-Action Allow `
-Protocol TCP `
-LocalPort 22
If you plan to forward to a different port, replace 22 with your listening port.
6.3 Configure portproxy
Clear old rules first, then re-add:
netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=22
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=22 connectaddress=$wslIp connectport=22
View current rules:
netsh interface portproxy show all
The meaning here is:
- Windows listens on
0.0.0.0:22 - When a connection is received, it forwards to port
22of the current WSL IP
6.4 Connect from Another Machine
First find the Windows host's IP on the LAN:
ipconfig
Then on another machine:
ssh <your_user>@<windows_lan_ip>
If the Windows listening port is not 22, don't forget to add -p.
7. What to Do When the WSL IP Changes
This is the most common pitfall of portproxy. After WSL restart, Windows restart, or network environment changes, the WSL IP may change.
So once you find:
ssh user@localhoststill works- But
ssh user@<windows_lan_ip>suddenly doesn't work
First suspect that portproxy is still pointing to the old WSL IP. The most direct fix is to re-execute the steps from the previous section to get the IP and add portproxy rules.
Minimal Troubleshooting Order
It is recommended to troubleshoot in this order, rather than starting by modifying the firewall:
- In WSL:
sudo service ssh statusorsudo systemctl status ssh - In WSL:
ss -lntp | grep :22 - On Windows:
ssh <your_user>@localhost - On Windows:
Test-NetConnection -ComputerName localhost -Port 22 - Check
netsh interface portproxy show all - Then check Windows firewall and LAN IP
Frequently Asked Questions
1. Why Not Enable Root Login by Default
Although WSL is often used as a local development environment, as soon as you open LAN access, it becomes a truly exposed SSH service on the network. The habit of using a normal user with sudo is much safer.
2. service ssh start Succeeded, But It's Gone After Reopening WSL
This is usually not SSH being broken, but the service not persisting after the WSL instance exits. Either accept "start manually when needed," or switch to enabling systemd.
3. Why chmod 600 /etc/ssh/sshd_config Is Not the Focus of Troubleshooting
Many tutorials will have you change this permission right away, but the actually more common problems are:
- Service not started
authorized_keyspermissions are wrongportproxypointing to an old IP- Windows firewall not allowing the connection