fix(waf): 修复P3安全审计缺陷

P3-1: logclient 复用 TCP 长连接,失败时重建,消除 TIME_WAIT 堆积
P3-2: TLS 显式限定 CipherSuites + CurvePreferences,排除弱加密套件
P3-3: CheckInput query 编码改用 url.Parse + Query().Encode()

修复率 76% -> 94%(P3 全部清零,仅剩 P0-3 为设计依赖)
This commit is contained in:
qing committed 2026-08-08 02:39:22 +08:00
1 parent dd9f8e51ff
commit 00ce3eac6a
5 files changed
+86 -33

No files matched your search

+41 -7
View File
@@ -63,12 +63,14 @@ type dbV2Response struct {
}
// Client 异步批量日志推送客户端。
// send 仅在 flushLoop 单 goroutine 中调用,conn 复用无需额外加锁。
type Client struct {
ch chan Entry
stop chan struct{}
wg sync.WaitGroup
stopped bool
mu sync.Mutex
conn net.Conn // 复用的 pymsg 长连接,失败时重建
}
// global 全局单例。
@@ -222,8 +224,8 @@ func (c *Client) sendOne(entry Entry, ts string) {
return
}
// pymsg 协议:4 字节 big-endian 长度 + UTF-8 载荷
resp, err := pymsgCall(data)
// pymsg 协议:4 字节 big-endian 长度 + UTF-8 载荷(复用长连接,失败时重连一次)
resp, err := c.pymsgCall(data)
if err != nil {
return // fail-safe
}
@@ -234,14 +236,24 @@ func (c *Client) sendOne(entry Entry, ts string) {
}
}
// pymsgCall 发送一条 pymsg 请求并读取响应(短连接模式)。
func pymsgCall(payload []byte) ([]byte, error) {
conn, err := net.DialTimeout("tcp", dbAddr, socketTimeout)
// pymsgCall 复用长连接发送一条 pymsg 请求并读取响应。
// 首次失败时关闭旧连接重建一次,避免高并发拦截场景下大量 TIME_WAIT 短连接。
func (c *Client) pymsgCall(payload []byte) ([]byte, error) {
resp, err := c.doPymsg(payload)
if err == nil {
return resp, nil
}
// 旧连接可能已断开(db 重启等),关闭后重连一次
c.closeConn()
return c.doPymsg(payload)
}
// doPymsg 在当前连接上执行一次请求-响应交互。
func (c *Client) doPymsg(payload []byte) ([]byte, error) {
conn, err := c.getConn()
if err != nil {
return nil, err
}
defer conn.Close()
conn.SetDeadline(time.Now().Add(socketTimeout))
// 发送:4 字节长度前缀 + 载荷
@@ -270,6 +282,27 @@ func pymsgCall(payload []byte) ([]byte, error) {
return resp, nil
}
// getConn 返回当前复用连接,不存在时建立。
func (c *Client) getConn() (net.Conn, error) {
if c.conn != nil {
return c.conn, nil
}
conn, err := net.DialTimeout("tcp", dbAddr, socketTimeout)
if err != nil {
return nil, err
}
c.conn = conn
return conn, nil
}
// closeConn 关闭并置空复用连接。
func (c *Client) closeConn() {
if c.conn != nil {
_ = c.conn.Close()
c.conn = nil
}
}
func (c *Client) flush() {
c.mu.Lock()
if c.stopped {
@@ -281,4 +314,5 @@ func (c *Client) flush() {
close(c.stop)
c.wg.Wait()
c.closeConn()
}