Ctrl K
ComunidadGuías…

host/windows/refresh-portproxy.ps1

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# DevBox portproxy refresh - keeps Windows port-forwards tracking the WSL guest IP.
#
# WHY THIS EXISTS: the dev box is devssh's WSL2 distro; its NAT IP rotates on
# every WSL restart, and the netsh portproxy rules that forward host ports to it
# hold a literal IP - nothing refreshed them before, so every WSL restart could
# silently strand them (known-issues.md). This script converges the rules to the
# live guest IP and the tailnet+localhost-only listener policy.
#
# LISTENER POLICY (2026-08-08, pure-IP-over-tailscale switch): listeners bind
# 127.0.0.1 and the host's tailnet IP 100.93.197.10 ONLY - never 0.0.0.0. The
# LAN must not reach these ports; the tailnet is the access control.
#
# RUNS AS: SYSTEM (scheduled task DevBox-Portproxy-Refresh; at startup + every
# 15 min). Deliberately does NOT call wsl.exe: devssh's distro is invisible to
# other accounts, so the guest IP is discovered by probing instead - first the
# currently-configured target, then the vSwitch neighbor table. The dev box is
# identified by answering BOTH :80 (traefik) and :9090 (prometheus), which
# yr055's unrelated WSL VM on the same switch does not.
#
# Mirrored in the Bothy repo at host/windows/refresh-portproxy.ps1.

$ErrorActionPreference = 'Stop'
$Ports     = 80, 3000, 3001, 8080, 8081, 9000, 9090
$Listeners = '127.0.0.1', '100.93.197.10'
$LogFile   = 'C:\Users\Public\devbox\portproxy-refresh.log'

function Write-Log($msg) {
    $line = "{0} {1}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $msg
    Add-Content -Path $LogFile -Value $line
}

function Test-DevBox($ip) {
    foreach ($p in 80, 9090) {
        $c = New-Object Net.Sockets.TcpClient
        try {
            if (-not $c.ConnectAsync($ip, $p).Wait(1500)) { return $false }
        } catch { return $false } finally { $c.Dispose() }
    }
    return $true
}

# --- 1. Discover the live guest IP -----------------------------------------
$rules = @(netsh interface portproxy show v4tov4 |
    Select-String '^\s*([\d.]+)\s+(\d+)\s+([\d.]+)\s+(\d+)' |
    ForEach-Object { [pscustomobject]@{
        Listen = $_.Matches[0].Groups[1].Value
        Port   = [int]$_.Matches[0].Groups[2].Value
        Target = $_.Matches[0].Groups[3].Value } })

$target = $null
$known = $rules | Where-Object { $_.Port -eq 80 } | Select-Object -First 1
if ($known -and (Test-DevBox $known.Target)) { $target = $known.Target }

if (-not $target) {
    $candidates = Get-NetNeighbor -AddressFamily IPv4 -ErrorAction SilentlyContinue |
        Where-Object { $_.InterfaceAlias -like '*WSL*' -and $_.State -in 'Reachable','Stale','Permanent' } |
        Select-Object -ExpandProperty IPAddress -Unique
    foreach ($ip in $candidates) {
        if (Test-DevBox $ip) { $target = $ip; break }
    }
}

if (-not $target) {
    Write-Log "FAIL no live dev-box guest found (distro down? repetition will retry)"
    exit 1
}

# --- 2. Converge (no-op when already correct) -------------------------------
$desired = foreach ($p in $Ports) { foreach ($l in $Listeners) { "$l|$p|$target" } }
$actual  = $rules | Where-Object { $_.Port -in $Ports } |
    ForEach-Object { "$($_.Listen)|$($_.Port)|$($_.Target)" }
if (-not (Compare-Object $desired $actual)) {
    exit 0   # silent no-op: log only changes, the task fires every 15 min
}

foreach ($p in $Ports) {
    foreach ($l in '0.0.0.0', '127.0.0.1', '100.93.197.10') {
        netsh interface portproxy delete v4tov4 listenaddress=$l listenport=$p 2>$null | Out-Null
    }
    foreach ($l in $Listeners) {
        netsh interface portproxy add v4tov4 listenaddress=$l listenport=$p connectaddress=$target connectport=$p | Out-Null
    }
}

# --- 3. Verify ---------------------------------------------------------------
$c = New-Object Net.Sockets.TcpClient
try {
    $ok = $c.ConnectAsync('127.0.0.1', 80).Wait(2000)
} catch { $ok = $false } finally { $c.Dispose() }
Write-Log "converged $($Ports.Count) ports -> $target (localhost:80 probe: $(if ($ok) {'OK'} else {'FAILED'}))"
if (-not $ok) { exit 1 }