Mirrored networking: host->WSL localhost broken; loopback relay connects to wrong destination ports in the guest
Windows Version
Microsoft Windows [Version 10.0.26200.8894]
WSL Version
2.9.4.0 (pre-release; also reproduced on 2.7.8.0 stable)
Are you using WSL 1 or WSL 2?
WSL 2
Kernel Version
6.18.35.2-1
Distro Version
Ubuntu 26.04 LTS
Other Software
Tailscale 1.98.9 (bug reproduces with Tailscale disconnected). No third-party AV/firewall (Defender only). No Docker.
Repro Steps
.wslconfig:
[wsl2]
vmIdleTimeout=-1
networkingMode=mirrored
[experimental]
bestEffortDnsParsing=true- In WSL:
python3 -m http.server 8765 --bind :: - From Windows:
curl.exe -m 4 http://127.0.0.1:8765/
Expected Behavior
HTTP 200 — the connection should be relayed into the WSL guest at destination port 8765.
Control machine: a second machine on the same Windows build (10.0.26200.8894), WSL 2.7.10.0, mirrored mode, same Tailscale version, works correctly.
Actual Behavior
Connection times out. The mirrored-mode loopback relay dials into the guest at the wrong destination ports.
An AF_PACKET capture on loopback0 inside the guest, during a single curl.exe http://127.0.0.1:8765/ from the host, shows the relay connecting to incorrect, incrementing destination ports (never 8765), each correctly RST'd by the guest since nothing listens there:
TCP 127.0.0.1:65292 -> 127.0.0.1:55818 [S]
TCP 127.0.0.1:55818 -> 127.0.0.1:65292 [AR]
TCP 127.0.0.1:65292 -> 127.0.0.1:55819 [S]
TCP 127.0.0.1:55819 -> 127.0.0.1:65292 [AR]
TCP 127.0.0.1:65292 -> 127.0.0.1:55820 [S]
TCP 127.0.0.1:55820 -> 127.0.0.1:65292 [AR]
TCP 127.0.0.1:65293 -> 127.0.0.1:62562 [S]
TCP 127.0.0.1:62562 -> 127.0.0.1:65293 [AR]
TCP 127.0.0.1:65293 -> 127.0.0.1:62563 [S]
TCP 127.0.0.1:62563 -> 127.0.0.1:65293 [AR]
...Not port-specific: probing a listener on port 3000 produced relay SYNs to 24142 and 24145. IPv6 ([::1]) fails identically. Once, transiently, a probe succeeded (HTTP 200), so the relay can map correctly on this machine but almost never does.
Additional diagnostics performed:
- Host-side pktmon (filter port 8765): the original SYN (
127.0.0.1:src -> 127.0.0.1:8765) traverses TCPIP → WFP Native Filter → VFP Extension → VMS Ext Filter/Protocol and is last seenRxat the[VM Nic]component, correctly addressed to the guestloopback0MAC; no drop counters increment anywhere. - Inbound from the network works perfectly: other LAN/Tailscale hosts reach the same WSL listener on this machine's mirrored addresses. Only host→guest loopback is broken.
- Guest plumbing verified:
loopback0up,net.ipv4.conf.loopback0.route_localnet=1, rp_filter loose,ip rule/table 127 (127.0.0.1 via 169.254.x.x dev loopback0) all present and identical to the working control machine. Empty nftables ruleset, no firewall services. - Windows→WSL loopback traffic counters on
loopback0do increment during probes — but entirely from the relay's wrong-port SYNs and the guest's RSTs.
Ruled out (verified identical to the working control machine, bug persists after each):
- Hyper-V firewall: effective (ActiveStore) VMSetting identical (
Enabled True / DefaultInboundAction Block / LoopbackEnabled True / AllowHostPolicyMerge True); also tested with explicitDefaultInboundAction Allow netsh interface portproxy reset(stale NAT-era rules removed)- Windows Defender Firewall profiles identical; NDIS adapter bindings identical (all-stock Microsoft components)
- Tailscale: same version/config as control; fails with
tailscale down - WSL upgrade 2.7.8.0 → 2.9.4.0 (pre-release)
- Full Windows reboot
- HNS state reset (stopped
hns, removedHNS.data, reboot)
This looks like the same relay port-scrambling family as #40343 (there: WSL→host direction, SYN-ACK returned to the wrong ephemeral port; here: host→guest direction, relay dials the wrong destination port).
Diagnostic Logs
Happy to provide the pktmon ETL/text captures, the in-guest packet captures, and collect-networking-logs.ps1 output on request.
Source: microsoft/WSL