https防御slowloris攻击的核心是将超时控制嵌入tls握手后、http处理前;需谨慎配置client_header_timeout(8–12秒)、client_body_timeout(保持proxy_request_buffering on)、keepalive_timeout(5–8秒并启用reset_timedout_connection)、send_timeout(普通接口8–12秒,流式接口60–300秒)。

HTTPS 全链路中防御 Slowloris 类慢速连接攻击,核心不是加密本身,而是把超时控制嵌入到 TLS 握手之后、HTTP 处理之前的关键阶段。Nginx 在 HTTPS 场景下仍沿用同一套 timeout 机制,但需注意 TLS 层延迟会叠加在 HTTP 超时上,因此参数设置要更谨慎,不能简单照搬 HTTP 配置。
client_header_timeout:HTTPS 下的第一道硬闸
该参数在 HTTPS 中依然从 TCP 连接建立后收到第一个字节(即 TLS 握手完成后的首个 HTTP 请求行)开始计时,到完整请求头(含 \r\n\r\n)接收完毕为止。TLS 握手本身耗时(通常 50–200ms)不计入此超时,但弱网或中间设备引入的额外延迟会压缩实际可用窗口。
- 普通 HTTPS 网站或 API:建议设为 8–12 秒,比纯 HTTP 略宽,覆盖 TLS + 弱网双重延迟
- 内网 HTTPS 网关(如 Service Mesh Ingress):可压至 4–6 秒,链路稳定且无公网 NAT 干扰
- 含大量 Cookie 或 SSO 头的登录页:先开启日志记录 $request_time 和 $status,观察 P95 头部接收耗时,再加 2–3 秒缓冲,上限不超过 15 秒
client_body_timeout 与 buffering 的协同陷阱
HTTPS 下 POST 请求体传输受 TLS 加密开销影响,小包吞吐效率略低。若关闭 proxy_request_buffering off(常见于 Kubernetes Ingress 大文件上传优化),Nginx 将不再校验 body 完整性,client_body_timeout 会完全失效——攻击者可直接穿透到后端服务,而后者往往缺乏等效防护。
- 必须保持 proxy_request_buffering on(默认值),确保 client_body_timeout 生效
- 搭配 client_max_body_size 20M,防攻击者声明极大 Content-Length 占满内存缓冲区
- 对真实大文件上传场景,设 client_body_timeout 300s,但仅限特定 location,且必须配 rate-limit 或 IP 白名单
keepalive_timeout + reset_timedout_connection:HTTPS 长连接的快速清道夫
HTTPS 的 keep-alive 连接比 HTTP 更易被滥用:一个 TLS 握手成功后的空闲连接,可能被 Slow Read 攻击者长期挂起,占用 socket 和 worker 连接槽位。默认 75 秒太长,尤其在高并发 HTTPS 场景下会快速堆积 TIME_WAIT。
- 对外 HTTPS 服务:设 keepalive_timeout 5–8 秒
- 必须启用 reset_timedout_connection on,让超时后发 RST 包而非 FIN,跳过四次挥手,立即释放句柄
- 配合 limit_conn perip 10(基于 $binary_remote_addr),限制单 IP 初始连接数,防多源扫荡
send_timeout 与流式响应的平衡点
HTTPS 响应发送阶段同样面临 Slow Read 攻击:客户端建好 TLS 连接,收完 header 后极慢读取 body(如 SSE、长轮询)。send_timeout 控制两次 write 操作间隔,设太短会误伤弱网用户,设太长则资源滞留。
- 普通 HTML/JSON 接口:设 send_timeout 8–12 秒
- 流式接口(如 /events):需提高至 60–300 秒,同时关闭 proxy_buffering off,并确保后端自身有读取超时(如 Node.js 的 req.setTimeout)
- 所有 HTTPS server 块中,禁用 gzip_vary off 和冗余 header,减少 TLS 分片和首包延迟











