param( [string]$ListenAddress = "0.0.0.0", [string]$ConnectAddress = "wsl", [int]$Port = 8011, [int]$ConnectPort = 8011, [string]$Distro = "" ) $ErrorActionPreference = "Stop" $principal = [Security.Principal.WindowsPrincipal]::new( [Security.Principal.WindowsIdentity]::GetCurrent() ) if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw "Run this script from an elevated PowerShell prompt." } if ($ConnectAddress -eq "wsl") { $wslArgs = @() if ($Distro) { $wslArgs += @("-d", $Distro) } $wslArgs += @("sh", "-lc", "hostname -I") $wslIps = (& wsl.exe @wslArgs) -split "\s+" $ConnectAddress = $wslIps | Where-Object { $_ -match "^\d{1,3}(\.\d{1,3}){3}$" } | Select-Object -First 1 if (-not $ConnectAddress) { throw "Could not detect the WSL IP address. Make sure your WSL distro is running." } } # Remove stale entries for this app. The old Tailscale-only entry can prevent # this service from behaving like the other WSL-published services. foreach ($entry in @( @{ Address = $ListenAddress; Port = $Port }, @{ Address = "100.103.206.4"; Port = $Port }, @{ Address = "0.0.0.0"; Port = 8001 }, @{ Address = "100.103.206.4"; Port = 8001 } )) { netsh interface portproxy delete v4tov4 listenaddress=$entry.Address listenport=$entry.Port | Out-Null } netsh interface portproxy add v4tov4 listenaddress=$ListenAddress listenport=$Port connectaddress=$ConnectAddress connectport=$ConnectPort if ($LASTEXITCODE -ne 0) { throw "Failed to add the new portproxy entry." } $ruleName = "ImpactFlow Discovery $ListenAddress`:$Port" $existingRule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue if (-not $existingRule) { $firewallArgs = @{ DisplayName = $ruleName Direction = "Inbound" Action = "Allow" Protocol = "TCP" LocalPort = $Port } if ($ListenAddress -ne "0.0.0.0") { $firewallArgs.LocalAddress = $ListenAddress } New-NetFirewallRule @firewallArgs | Out-Null } Write-Output "Forwarding http://$ListenAddress`:$Port -> http://$ConnectAddress`:$ConnectPort"