<# .SYNOPSIS Forward router-facing OpenBMP ports from the Windows host into WSL. .DESCRIPTION Physical routers cannot reach the WSL VM's NAT address, and that address changes on every 'wsl --shutdown' (portability finding 4). This script (re)creates the netsh portproxy rules that forward the router-facing BMP port and Kafka from the Windows LAN IP into the current WSL address, plus the matching inbound firewall rules. Idempotent: existing rules for the same listen ports are replaced, so RE-RUN IT AFTER EVERY WSL RESTART. Must run in an ELEVATED PowerShell. .PARAMETER RouterPort Router-facing BMP listen port on Windows (default 1790, the IANA BMP port). Forwards to the collector's in-container port 5000. .PARAMETER WslIp WSL address to forward to. Default: auto-detected via 'wsl hostname -I'. .EXAMPLE powershell -ExecutionPolicy Bypass -File scripts\wsl-portproxy.ps1 powershell -ExecutionPolicy Bypass -File scripts\wsl-portproxy.ps1 -RouterPort 5000 #> param( [int]$RouterPort = 1790, [int]$CollectorPort = 5000, [int]$KafkaPort = 9092, [string]$WslIp = "" ) $ErrorActionPreference = "Stop" $id = [System.Security.Principal.WindowsIdentity]::GetCurrent() if (-not (New-Object System.Security.Principal.WindowsPrincipal($id)).IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Error "Run this from an ELEVATED PowerShell (netsh portproxy needs admin)." exit 1 } if (-not $WslIp) { $WslIp = (wsl hostname -I).Trim().Split(" ")[0] if (-not $WslIp) { Write-Error "Could not auto-detect the WSL IP; pass -WslIp."; exit 1 } } Write-Host "WSL address: $WslIp" # listenport => connectport ($RouterPort maps DOWN to the collector's 5000) $maps = @{ $RouterPort = $CollectorPort; $KafkaPort = $KafkaPort } foreach ($listen in $maps.Keys) { netsh interface portproxy delete v4tov4 listenport=$listen listenaddress=0.0.0.0 2>$null | Out-Null netsh interface portproxy add v4tov4 listenport=$listen listenaddress=0.0.0.0 ` connectport=$($maps[$listen]) connectaddress=$WslIp | Out-Null Write-Host "portproxy 0.0.0.0:$listen -> ${WslIp}:$($maps[$listen])" $ruleName = "OpenBMP $listen" if (-not (Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue)) { New-NetFirewallRule -DisplayName $ruleName -Direction Inbound ` -LocalPort $listen -Protocol TCP -Action Allow | Out-Null Write-Host "firewall rule added: $ruleName" } } Write-Host "" Write-Host "Active portproxy rules:" netsh interface portproxy show v4tov4 Write-Host "Routers target the Windows LAN IP on port $RouterPort (see docs/router-bmp-config.md)."