Skip to content

fix(conntracker): swap upload/download counters on UDP PacketCon #55

@oballm

Description

@oballm

Summary

trackedPacketConn.UnwrapPacketReader / UnwrapPacketWriter 的 upload/download 计数器映射与同文件 TCP 路径相反,导致使用 UDP PacketConn 的协议(Hysteria2、TUIC 的 UDP relay)流量上下行被互换计费。

根因

conntracker.go 里两套实现的方向语义本应一致:

  • 入站方向"读"(从客户端来) = upload
  • 入站方向"写"(发给客户端) = download

TCP 路径(trackedConn, line 669-680)写对了:

UnwrapReader() → &c.us.upload   // 从入站读 = 用户上传 ✅
UnwrapWriter() → &c.us.download // 向入站写 = 用户下载 ✅

 UDP 路径trackedPacketConn, line 790-802方向反了UnwrapPacketReader() → &c.us.download // ❌
UnwrapPacketWriter() → &c.us.upload   // ❌

影响

- 协议:使用 N.PacketConn 的入站主要是 Hysteria2TUIC  UDP 数据通道
- 现象用户面板看到的上下行数字与实际相反按上行计费的策略流量包QoS限速作用到反向流量上
- 范围 UDP 计费方向不影响认证归因或 TCP 流量

Fix

两行对调使 UDP 路径与 TCP 路径方向一致func (c *trackedPacketConn) UnwrapPacketReader() (N.PacketReader, []N.CountFunc) {
     if c.us == nil {
         return c.PacketConn, nil
     }
-    return c.PacketConn, []N.CountFunc{c.makeCountFunc(&c.us.download)}
+    return c.PacketConn, []N.CountFunc{c.makeCountFunc(&c.us.upload)} // 从入站读 = 用户上传
 }

 func (c *trackedPacketConn) UnwrapPacketWriter() (N.PacketWriter, []N.CountFunc) {
     if c.us == nil {
         return c.PacketConn, nil
     }
-    return c.PacketConn, []N.CountFunc{c.makeCountFunc(&c.us.upload)}
+    return c.PacketConn, []N.CountFunc{c.makeCountFunc(&c.us.download)} // 向入站写 = 用户下载
 }

Test plan

- 部署 patched 二进制仅用 Hysteria2 客户端发起一次大流量下载 1GB 测速文件- 面板侧确认该用户记录 d下行 / download增加 ~1GBu上行 / upload保持小量
- 反向验证用客户端上传 1GB 文件确认 u 增加而非 d
- TCP 路径回归测试Shadowsocks / VMess 大文件下载确认数字方向未变

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions