Port Forwarding (NAT Mode)¶
Only needed if using NAT networking (the default). If using mirrored mode, skip this -- see networking.md.
The Problem¶
WSL2 in NAT mode gets a private IP (172.x.x.x) that is not reachable from
outside the host. The IP also changes on every WSL restart. You need
netsh interface portproxy to forward traffic from the host's IPs to WSL2.
Manual Setup¶
# Get current WSL2 IP
$wslIP = (wsl hostname -I).Trim()
# Forward port 22 on all host interfaces to WSL2's SSH
netsh interface portproxy add v4tov4 `
listenport=22 listenaddress=0.0.0.0 `
connectport=22 connectaddress=$wslIP
# Verify
netsh interface portproxy show all
listenaddress=0.0.0.0 makes it accessible on all host IPs including the Tailscale IP. For tighter security, use the specific Tailscale IP:
$tsIP = (tailscale ip -4)
netsh interface portproxy add v4tov4 `
listenport=22 listenaddress=$tsIP `
connectport=22 connectaddress=$wslIP
Automated via Startup Script¶
Since the WSL2 IP changes on reboot, automate portproxy in a PowerShell script triggered by Task Scheduler:
C:\Scripts\wsl-ssh-setup.ps1¶
# Start WSL and sshd
wsl -d Ubuntu -u root -- service ssh start
# Wait for WSL to be ready
Start-Sleep -Seconds 3
# Get WSL2 IP
$wslIP = (wsl hostname -I).Trim().Split(' ')[0]
# Remove old portproxy rule
netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=22
# Add new portproxy rule
netsh interface portproxy add v4tov4 `
listenport=22 listenaddress=0.0.0.0 `
connectport=22 connectaddress=$wslIP
# Log for debugging
"$(Get-Date) - WSL IP: $wslIP - portproxy updated" | Out-File -Append C:\Scripts\wsl-ssh.log
Add this script to Task Scheduler (see boot-automation.md):
- Program: powershell.exe
- Arguments: -ExecutionPolicy Bypass -File C:\Scripts\wsl-ssh-setup.ps1
Cleanup¶
To remove all portproxy rules:
Verify from Remote¶
From your home machine:
The -v flag shows connection details for debugging.