必须在http.Server上设置MaxHeaderBytes硬限制防超大Cookie导致DoS,推荐4096字节;再辅以Echo中间件二次校验Cookie长度不超过2048字节。

超大Cookie会直接压垮Echo的HTTP解析器,导致panic或OOM,这不是“性能问题”,而是明确的DoS入口。
为什么Echo默认不拦截超大Cookie
Echo基于net/http,而标准库http.Request在读取Header时不会主动限制Cookie字段长度——它把整个Header行(含所有Cookie)一次性读入内存,再交给http.ReadRequest解析。一旦攻击者构造一个几MB的Cookie头,Echo还没走到路由逻辑,就在http.ServeHTTP阶段崩溃。
- 常见现象:
fatal error: runtime: out of memory或http: server closed idle connection伴随大量500日志 - 触发点不在业务代码,而在
echo.Echo.ServeHTTP调用前的底层net/http解析阶段 - 即使你用
echo.HTTPErrorHandler也捕获不到——panic发生在中间件链启动之前
必须在net/http层做Header大小硬限制
不能依赖Echo中间件,必须在http.Server实例上设限。Echo的e.Start()底层仍用http.Server,所以要手动构建并配置它:
server := &http.Server{
Addr: ":8080",
Handler: e,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
// 关键:限制Header总大小,间接控Cookie
MaxHeaderBytes: 4096, // 推荐值:4KB,足够容纳多数合法Cookie(含Domain/Path/Secure等属性)
}
-
MaxHeaderBytes是唯一有效的防线,它控制整个HTTP请求头的字节数上限 - 不要设成
0(无限制)或过大(如1048576即1MB),攻击者可轻松绕过 - 4096是平衡点:正常登录态Cookie一般
,加域名、路径、标志后仍远低于此值 - 注意:这个值对所有Header生效,不是只针对
Cookie;但Cookie通常是Header里最大的单项
额外加固:在Echo中间件中二次校验Cookie内容
Header限制防不住“合法大小但恶意构造”的Cookie(比如超多key=value对引发解析开销)。可在echo.MiddlewareFunc里快速检查:
func cookieSizeLimit(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) error {
cookieHeader := c.Request().Header.Get("Cookie")
if len(cookieHeader) > 2048 { // 单独再卡一次Cookie长度
return echo.NewHTTPError(http.StatusBadRequest, "cookie too large")
}
return next.ServeHTTP(c)
})
}
// 然后注册:e.Use(cookieSizeLimit)
- 这个中间件只在Header已通过
MaxHeaderBytes检查后才执行,不会重复OOM - 2048是经验值:远小于
MaxHeaderBytes,但比单个Session ID长得多,留出合理余量 - 别在这里做
http.ParseCookie——解析本身就有CPU开销,攻击者可用海量无效key=value耗尽CPU
真正难防的是Header限制与业务需求的冲突:某些老系统真需要3KB以上的Cookie(比如含JWT+用户偏好+权限列表)。这时只能拆解——把非关键数据移出Cookie,改用localStorage或服务端Session ID查表。安全边界从来不在“能不能”,而在“值不值得为这点便利放弃防护”。











