experimental/windivert: P2.1+P2.2 with WinDivert NETWORK+SOCKET layers

WIP snapshot before pivot to sing-box+TUN. Reached:
- TCP redirect via streamdump pattern (swap+Outbound=0+reinject)
- SOCKET layer for SYN-stage flow detection (avoids FLOW Establish-too-late race)
- Lazy PID→name resolution (catches Update.exe inside procscan tick)
- UDP forward via SOCKS5 UDP ASSOCIATE relay + manual reinject
- Result: chat works, voice times out (Discord IP discovery / RTC handshake fails)

Reason for pivot: WinDivert NAT-reinject pattern has subtle layer-3
semantics issues that DLL-injection / TUN-based proxies sidestep
entirely. Going with embedded sing-box + wintun as the engine —
proven path for Discord voice through SOCKS5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-01 22:27:54 +03:00
parent 8ceb7775d7
commit 4074e68715
19 changed files with 2666 additions and 62 deletions
+15
View File
@@ -78,6 +78,21 @@ func (r *Redirector) SetMapping(srcPort uint16, dstIP net.IP, dstPort uint16) {
r.mu.Unlock()
}
// GetMapping returns the original (dstIP, dstPort) for a recorded flow
// keyed by src port, or ok=false if no mapping exists. Used by the
// engine's diverterLoop on the return path to look up the original
// target port when rewriting packets going from the listener back to
// the client.
func (r *Redirector) GetMapping(srcPort uint16) (net.IP, uint16, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
m, ok := r.flows[srcPort]
if !ok {
return nil, 0, false
}
return m.dstIP, m.dstPort, true
}
// Close stops accepting and tears down active flows.
func (r *Redirector) Close() error {
r.cnl()