示例说明
默认 http.Server 的多数超时是零——无限等待。慢速攻击正是利用这一点:每个连接以每分钟一个字节的速度发请求,几千个连接就能耗尽句柄池。四段超时各有分工:ReadHeaderTimeout 拦截慢速头部、ReadTimeout 约束请求体、WriteTimeout 限制响应时长、IdleTimeout 回收 keep-alive 空闲连接——组合起来慢速攻击彻底失效。
技术要点
- 四段超时覆盖连接全生命周期
- MaxHeaderBytes 封顶头部体积
- 方法校验前置减少无效处理
代码解读
newHardenedServer 一次性声明全部时限:头部五秒、读十秒、写三十秒、空闲两分钟,头部上限一兆字节。处理器先校验方法并设置 Allow 头——把错误在最早阶段礼貌拒绝。ListenAndServe 的错误直接致命退出,配置错误不该静默。
使用建议
写超时要大于最慢合法响应的耗时,SSE 等长连接需单独豁免。反向代理场景超时要全链路形成漏斗。生产再加限流与并发连接数上限。
代码示例
package main
import (
"fmt"
"log"
"net/http"
"time"
)
func newHardenedServer(addr string) *http.Server {
return &http.Server{
Addr: addr,
ReadHeaderTimeout: 5 * time.Second, // 头部必须快速到达
ReadTimeout: 10 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
MaxHeaderBytes: 1 << 20, // 头部上限 1MiB
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.Header().Set("Allow", http.MethodPost)
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
fmt.Fprintln(w, "accepted")
}),
}
}
func main() {
srv := newHardenedServer(":8080")
log.Fatal(srv.ListenAndServe())
}