Skip to content

fix: dedupe direct UDP session dials and skip self as DNS fallback - #126

Merged
nange merged 4 commits into
masterfrom
fix/tun-direct-connection-leaks
Aug 28, 2026
Merged

fix: dedupe direct UDP session dials and skip self as DNS fallback#126
nange merged 4 commits into
masterfrom
fix/tun-direct-connection-leaks

Conversation

@nange

@nange nange commented Aug 28, 2026

Copy link
Copy Markdown
Owner

背景

修复两个问题:

1. direct UDP 会话重复拨号导致连接泄漏

directUDPRelay 在 map 查找与插入之间存在竞态窗口:同一 (client, target) 流的并发 datagram 会重复 dial,产生孤儿 socket 及其 read goroutine(最多泄漏至 2 分钟读超时);更严重的是孤儿 readLoop 退出时无条件删除 map 条目,会误删 LIVE 会话,导致长连接流(QUIC、游戏、VoIP)每 ~2 分钟 churn 一个新 socket。

修复

  • 新增 directUDPFactory in-flight 去重(与 proxied 路径的 udpExchangeFactory 对称),保证每个流恰好一个 socket + 一个 readLoop
  • readLoop 退出时仅在 map 条目仍指向本 session 时才删除,孤儿清理不再误删 LIVE 条目
  • dial 成功后检查 closing 标志,服务关闭期间新建的 socket 立即关闭,不泄漏

2. DNS forward 服务器以自身作为 fallback 上游造成递归

TUN 模式 + EnableForwardDNS 时系统 DNS 被设置为 127.0.0.1(即本 forward 服务器自身)。当 builtin DNS 服务器全部不可达时,fallback 会递归回自身(查询 -> fallback -> 127.0.0.1:53 -> 同一查询),堆积 goroutine 和 UDP socket 直到查询超时。

修复systemDNSServers() 过滤掉指向自身监听地址的条目。

测试

  • 新增 TestDirectUDPRelayConcurrentDial:验证并发 datagram 只拨号一次
  • 新增 TestDirectUDPRelayStaleReadLoopKeepsLiveEntry:验证孤儿 readLoop 退出不误删 LIVE 条目(含正向对照)
  • 新增 TestForwardQuerySkipsSelfAsUpstream:验证系统 DNS 中的自身条目被过滤
  • go test ./client/dns/...go test ./client/proxy/ -run DirectUDP 全部通过

nange added 4 commits August 28, 2026 13:26
- directUDPRelay raced between the map lookup and insert: concurrent
  datagrams for the same flow dialed twice, orphaning one socket and
  letting its cleanup evict the LIVE map entry every ~2 minutes; add a
  directUDPFactory in-flight dedup (mirroring the proxied path) and make
  the read loop delete only its own session
- the DNS forward server used 127.0.0.1 as a fallback upstream when TUN
  set it as the system DNS, recursing into itself while the builtin
  servers were unreachable; filter out its own listen address
@nange
nange merged commit af451b6 into master Aug 28, 2026
6 checks passed
@nange
nange deleted the fix/tun-direct-connection-leaks branch August 28, 2026 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant