编号:L-01 严重级:high 工作线:监听与 HTTP(internal/listener、internal/httpx、serve 的 HTTP 装配) 来源:审查 P-04 依赖:无 被依赖:无
采用审查 P-04 的方案(总审查人读 listener 时也发现同一问题)。首字节 peek 有 10 秒超时,但读完就清掉了 deadline,之后各阶段都没有时限,而 MaximumClients=2000 只统计认证之后的会话:
MaximumClients=2000
classify
SetDeadline(now+10s)
Handshake()
handleConn
OnMQTT
SetReadDeadline(now+10s)
internal/broker/ws.go
AttachWS
OnConnect
refreshDeadline
http.Server
IdleTimeout: 120s
MaxHeaderBytes: 64<<10
ReadTimeout
WriteTimeout
Accept
http.NewResponseController(w)
internal/listener/server.go、conn.go;internal/broker/ws.go(仅 AttachWS 之前一行)。
internal/listener/server.go
conn.go
10 FF FF 2F
以下是本次复审各区审查报告的原文段落。A、M、I、P、S 开头的是原始发现编号(A 管理后台与网页、M 消息核心、I 身份认证群在线、P 传输平台部署、S SDK)。解决方案以本 issue 上方的"结论与统一方案"为准;原文里的方案与之不一致时,按上方执行。
conn.go:32-34
server.go:298-302
ReadPacket
clients.go:465-474
ws.go:29-39
ReadHeaderTimeout
server.go:121-125
155-159
IdleTimeout
session.go:109-113
listener.classify
c.SetDeadline(now+10s)
out.SetReadDeadline(now+10s)
ws.go
nc.SetReadDeadline(now+10s)
WSHandler
http.NewResponseController(w).SetReadDeadline(time.Time{})
SetWriteDeadline(time.Time{})
复审基线:main 4059a15(2026-09-30)。编号说明、各工作线的合并顺序、共享文件归属见总览 #7。
4059a15
已合入 origin/main 0c9b459。落地提交 c0b2903 fix: 修复监听 accept 退避与握手前超时上限 (#20)。
0c9b459
c0b2903
No dependencies set.
The note is not visible to the blocked user.
编号:L-01 严重级:high 工作线:监听与 HTTP(internal/listener、internal/httpx、serve 的 HTTP 装配) 来源:审查 P-04
依赖:无 被依赖:无
结论与统一方案
采用审查 P-04 的方案(总审查人读 listener 时也发现同一问题)。首字节 peek 有 10 秒超时,但读完就清掉了 deadline,之后各阶段都没有时限,而
MaximumClients=2000只统计认证之后的会话:classify的 TLS 分支先SetDeadline(now+10s)再Handshake(),成功后清零。handleConn调OnMQTT之前设SetReadDeadline(now+10s);internal/broker/ws.go在AttachWS之前对 NetConn 设同样的读超时。mochi 在OnConnect之后的refreshDeadline会覆盖它;argon2 排队期间不读包,不受影响。http.Server增加IdleTimeout: 120s、MaxHeaderBytes: 64<<10。如果再加ReadTimeout/WriteTimeout,必须在 WSAccept之前用http.NewResponseController(w)清掉,否则会带到被劫持的 WebSocket 连接上。改动文件
internal/listener/server.go、conn.go;internal/broker/ws.go(仅AttachWS之前一行)。与其他问题的交互 / 冲突说明
验收与测试
10 FF FF 2F,立即被关闭。问题明细(各区审查原文,证据含文件与行号)
[P-04] 握手前阶段没有超时,也没有并发上限:TLS 握手、MQTT CONNECT、WS 升级之后、HTTP 空闲长连接都能无限占用资源
conn.go:32-34)。之后各阶段都没有时限:Handshake()没有 deadline,客户端发一个 0x16 就能把连接挂住(server.go:298-302)。refreshDeadline,见 P-3 引用)。而且ReadPacket是先按剩余长度分配缓冲再读,客户端只发 5 个字节10 FF FF 2F,服务器就预分配约 768 KiB 并一直等下去(mochiclients.go:465-474)。AttachWS,同样没有 deadline(ws.go:29-39)。http.Server只设了ReadHeaderTimeout(server.go:121-125、155-159),IdleTimeout和ReadTimeout都是 0,keep-alive 空闲连接永不回收,请求体也能无限慢速上传。MaximumClients=2000只统计认证之后的会话,握手前的连接没有任何上限;30 秒握手计时器也是 CONNACK 之后才开始(session.go:109-113)。listener.classify的 TLS 分支:先c.SetDeadline(now+10s)再Handshake(),成功后清零。handleConn调OnMQTT之前out.SetReadDeadline(now+10s);ws.go在AttachWS之前nc.SetReadDeadline(now+10s)(coder 的 NetConn 支持)。mochi 在 OnConnect 之后调refreshDeadline会覆盖掉这个 deadline;argon2 排队期间不读包,不受影响。http.Server增加IdleTimeout: 120s和MaxHeaderBytes: 64<<10。如果还要加ReadTimeout或WriteTimeout,必须在WSHandler里Accept之前用http.NewResponseController(w).SetReadDeadline(time.Time{})和SetWriteDeadline(time.Time{})清掉,否则会带到被劫持的 WS 连接上。internal/listener/server.go、conn.go;internal/broker/ws.go10 FF FF 2F,立即被关闭。复审基线:main
4059a15(2026-09-30)。编号说明、各工作线的合并顺序、共享文件归属见总览 #7。已合入 origin/main
0c9b459。落地提交c0b2903fix: 修复监听 accept 退避与握手前超时上限 (#20)。