# Update-WSLDockerProxy.ps1 # Updates the portproxy rule for WSL Docker, self-elevating if needed. # Usage: . .\Update-WSLDockerProxy.ps1 (dot-source to import the function) # Update-WSLDockerProxy (then call it) # Or just run the script directly and it will execute automatically. function Update-WSLDockerProxy { [CmdletBinding()] param( [int]$Port = 2375, [string]$LogPath = "$env:TEMP\Update-WSLDockerProxy.log" ) function Write-Log { param([string]$Message) $line = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $Message" Write-Host $Message Add-Content -Path $LogPath -Value $line } # Self-elevate if not running as admin if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Host "Not running as admin, re-launching elevated..." -ForegroundColor Yellow $scriptPath = $MyInvocation.MyCommand.ScriptBlock.File if (-not $scriptPath) { Write-Error "Cannot self-elevate when dot-sourced without a file path. Run the script directly instead." return } Start-Process powershell.exe -Verb RunAs -ArgumentList "-NonInteractive -WindowStyle Hidden -File `"$scriptPath`" -Port $Port" return } # --- Get current WSL IP --- # wsl.exe emits UTF-16 output with embedded null bytes when its stdout isn't # attached to a real console (hidden window, scheduled task, self-elevated # relaunch, etc). That corrupts naive string parsing (e.g. results in "W" # instead of an IP). Strip null chars before parsing, and validate the # result looks like an actual IPv4 address before using it. $rawOutput = (wsl.exe hostname -I 2>$null) -join ' ' $cleaned = ($rawOutput -replace "`0", '').Trim() $WSL_IP = $null if ($cleaned) { $candidates = $cleaned -split '\s+' | Where-Object { $_ -match '^\d{1,3}(\.\d{1,3}){3}$' } $WSL_IP = $candidates | Select-Object -First 1 } if (-not $WSL_IP) { Write-Log "ERROR: Could not get a valid WSL IP. Raw output was: '$rawOutput'" return } Write-Log "WSL IP: $WSL_IP" # Remove existing rule if present $existing = netsh interface portproxy show v4tov4 | Select-String ":$Port" if ($existing) { Write-Log "Removing existing portproxy rule on port $Port..." netsh interface portproxy delete v4tov4 listenport=$Port listenaddress=127.0.0.1 | Out-Null } # Add new rule netsh interface portproxy add v4tov4 listenport=$Port listenaddress=127.0.0.1 connectport=$Port connectaddress=$WSL_IP | Out-Null Write-Log "Portproxy updated: 127.0.0.1:$Port -> ${WSL_IP}:$Port" } # Run automatically if script is executed directly (not dot-sourced) if ($MyInvocation.InvocationName -ne '.') { Update-WSLDockerProxy }