Skip to content

fix: unify stream idle timeout derivation and apply it to direct TCP relays - #127

Merged
nange merged 2 commits into
masterfrom
fix/unify-stream-idle-timeout
Aug 28, 2026
Merged

fix: unify stream idle timeout derivation and apply it to direct TCP relays#127
nange merged 2 commits into
masterfrom
fix/unify-stream-idle-timeout

Conversation

@nange

@nange nange commented Aug 28, 2026

Copy link
Copy Markdown
Owner

背景

此前存在两处不一致:

  1. config.DefaultStreamIdleTimeout(硬编码 300s)与 config.StreamIdleTimeout(base)(10 × base 派生公式)是两份独立定义,仅靠注释维持同步,存在漂移风险。
  2. 客户端直连 TCP 路径(SOCKS5 CONNECT direct / HTTP CONNECT direct)固定使用 DefaultStreamIdleTimeout(300s),不跟随用户配置的 base timeout——当用户配置 timeout=60s 时,代理路径与服务端的流空闲超时为 600s,而直连路径仍是 300s,行为不一致。
  3. 默认流空闲超时 StreamIdleTimeout 采用 10 × base(默认 300s)偏大,半开/死连接需等 5 分钟才被回收。

改动

统一超时来源 + 直连 TCP 跟随用户配置

  • config/types.goDefaultStreamIdleTimeout 由常量改为 var,从 StreamIdleTimeout(DefaultTimeout) 公式导出,timeouts.go 成为唯一事实来源。
  • client/proxy/socks5.go:删除 directRelayIdleTimeout 常量;Socks5Server 新增 streamIdleTimeout 字段;NewSocks5Server 新增对应参数(≤0 时兜底 DefaultStreamIdleTimeout);relayTCP 新增 idleTimeout 参数。
  • client/proxy/http_proxy.go:CONNECT direct 两处 relayTCP 改为 config.StreamIdleTimeout(s.timeout) 派生;base 兜底 30 * time.Second 统一引用 config.DefaultTimeout
  • runner/runner.goNewSocks5Server 传入已派生的 streamIdleTimeout(与代理路径同源)。

默认流空闲超时 10× → 4×

  • config/timeouts.goStreamIdleTimeout(base)10 * base 改为 4 * base(默认 30s → 120s),同步更新注释。
  • config/types.go:相关注释中的数值(300s → 120s)同步更新;DefaultStreamIdleTimeout 由公式导出,自动跟随。
  • config/timeouts_test.goTestStreamIdleTimeout 期望值更新。

测试

  • config/timeouts_test.go:新增 TestDefaultStreamIdleTimeoutDerived,守护"默认值恒等于公式在默认 base 下的结果"约束;更新 TestStreamIdleTimeout 期望值。
  • client/proxy/direct_relay_test.go(新增):
    • TestRelayTCPIdleTimeoutClosesBoth:验证 idle 超时后两端连接均被关闭(copy goroutine 不会悬挂)。
    • TestRelayTCPHalfCloseAndCompletion:用两对 TCP(应用↔代理、代理↔远端)忠实模拟生产拓扑,验证 FIN 双向传播(CloseWrite half-close)、relay 完成后所有连接关闭。
  • 更新 4 处 NewSocks5Server 调用(含测试)。

行为变化

  • 默认配置(30s)下:流空闲超时由 300s 变为 120s;直连 TCP 与该值一致。
  • 用户配置 timeout ≠ 30s 时:所有路径(代理、直连、服务端)随 base 按 4 × 统一缩放。

验证

  • go build ./...go vetgo test ./...(全仓)通过
  • 新测试 -count=5 重复运行稳定
  • make lint:0 issues

nange added 2 commits August 28, 2026 17:45
…relays

Make config.DefaultStreamIdleTimeout derive from the StreamIdleTimeout(base) formula (single source of truth) and route the direct SOCKS5/HTTP CONNECT relay through the user-configured base timeout instead of a hardcoded 300s, matching the proxied path and server side.
…eout

120s instead of 300s at the default 30s base: reaps half-open peers sooner while staying generous enough for idle SSH/long-polling connections.
@nange
nange merged commit 8b787fb into master Aug 28, 2026
6 checks passed
@nange
nange deleted the fix/unify-stream-idle-timeout branch August 28, 2026 10:10
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