How to Configure WSL 2 Port Forwarding to Local Area Network in Windows 11 Using PowerShell

The Windows Subsystem for Linux (WSL 2) isolates Linux distributions behind a virtual Network Address Translation (NAT) switch. While services hosted inside WSL 2 (such as Node.js development servers, Django apps, or Docker containers) are directly accessible from the local Windows host via localhost, they remain completely invisible to external devices on your physical Local Area Network (LAN). Using PowerShell and Windows netsh portproxy rules, developers can route incoming LAN traffic directly into WSL 2 virtual instances.

Understanding Windows NAT and PortProxy Mechanics

Exposing WSL 2 services across your physical local network requires coordinating three distinct networking components:

  • PortProxy (netsh interface portproxy): A native Windows networking service that listens for incoming TCP traffic on the host’s physical network adapter and forwards packets to the internal WSL 2 virtual IP.
  • Windows Defender Firewall Rules: External devices attempting to connect to your Windows host IP will be dropped by default unless explicit inbound firewall rules permit traffic on designated ports.
  • Dynamic IP Resolution: Because WSL 2 regenerates its internal IP address upon reboot, portproxy bindings must be updated dynamically via automated PowerShell scripts.

Creating the Automated Port Forwarding PowerShell Script

Create a dedicated PowerShell script to query the live WSL 2 IP address and configure both portproxy and firewall rules:

# Define script location
$scriptPath = "$env:USERPROFILE\Documents\Set-WSLPortForward.ps1"

$scriptBody = @'
# Define ports to expose to your local network (e.g., 3000 for React, 8080 for web server)
$Ports = @(3000, 8080)

# Retrieve active WSL 2 internal IP address
try {
    $wslIP = (wsl -e hostname -I).Trim().Split(' ')[0]
    Write-Output "Detected WSL 2 IP: $wslIP"

    if (-not $wslIP) {
        throw "WSL IP address could not be resolved. Ensure WSL is running."
    }

    foreach ($Port in $Ports) {
        # Configure Windows netsh portproxy forwarding
        netsh interface portproxy delete v4tov4 listenport=$Port listenaddress=0.0.0.0 | Out-Null
        netsh interface portproxy add v4tov4 listenport=$Port listenaddress=0.0.0.0 connectport=$Port connectaddress=$wslIP

        # Ensure Windows Defender Firewall allows incoming traffic on the port
        $ruleName = "WSL2_Inbound_Port_$Port"
        Remove-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
        New-NetFirewallRule -DisplayName $ruleName -Direction Inbound -LocalPort $Port -Protocol TCP -Action Allow | Out-Null

        Write-Output "Successfully forwarded port $Port -> $wslIP:$Port"
    }
} catch {
    Write-Error "Error configuring WSL port forwarding: $_"
}
'@

$scriptBody | Out-File -FilePath $scriptPath -Encoding utf8

Executing and Testing the Port Forwarding Configuration

Execute the script from an elevated administrative terminal:

  1. Right-click the Start menu and select Terminal (Admin).
  2. Run the configuration script:
    & "$env:USERPROFILE\Documents\Set-WSLPortForward.ps1"
  3. Verify that the portproxy bindings have registered:
    netsh interface portproxy show v4tov4
  4. Identify your physical Windows host LAN IP:
    (Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias "Wi-Fi*", "Ethernet*").IPAddress
  5. From a secondary device on the same local network (such as a smartphone or tablet), navigate to http://<windows-host-ip>:3000 to verify live connection to your WSL 2 development server.

Automating Forwarding on Windows Startup

To avoid manual re-execution following system restarts, create a Windows Scheduled Task with administrative credentials:

$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-WindowStyle Hidden -ExecutionPolicy Bypass -File `"$env:USERPROFILE\Documents\Set-WSLPortForward.ps1`""
$trigger = New-ScheduledTaskTrigger -AtLogOn
$principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest

Register-ScheduledTask -TaskName "WSL_PortForward_Init" -Action $action -Trigger $trigger -Principal $principal -Description "Automates WSL 2 LAN port forwarding on startup."

Removing Port Forwarding Rules

When testing is complete and you wish to close external network access:

# Clear specific port forwarding entry
netsh interface portproxy delete v4tov4 listenport=3000 listenaddress=0.0.0.0

# Remove corresponding firewall rule
Remove-NetFirewallRule -DisplayName "WSL2_Inbound_Port_3000"

This automated approach guarantees secure, repeatable access to WSL 2 services across physical networks without manual host editing.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.