核心是启用并参数化 Nginx 的 proxy_socket_keepalive(如 on 240s 10s 3),配合 upstream keepalive 连接池、proxy_http_version 1.1、proxy_set_header Connection '',同时调优系统 TCP keepalive 参数(tcp_keepalive_time=300 等)以匹配运营商防火墙 30–300 秒空闲超时。

要解决跨公网代理中连接被运营商防火墙静默断开的问题,核心是让 TCP 连接在空闲期主动“说话”,避免被中间设备当成死连接清理。运营商防火墙普遍设置较短的空闲超时(常见 30–300 秒),而 Linux 默认的 TCP Keepalive(7200 秒才发第一个探测)完全跟不上节奏——必须从 Nginx 配置和系统内核两层同步调优。
必须配齐的四项 Nginx 基础配置
单独打开 proxy_socket_keepalive 没用,它只是“探测开关”,真正起效需要整条链路配合:
-
upstream 中启用 keepalive 连接池:例如
keepalive 64;,否则 Nginx 不复用连接,保活就失去对象 -
显式声明 HTTP/1.1:在 location 或 server 块中加
proxy_http_version 1.1;,确保后端接受长连接 -
清空 Connection 头:加上
proxy_set_header Connection "";,防止 Nginx 自动注入Connection: close导致后端立刻断连 -
开启并参数化 proxy_socket_keepalive:不能只写
on,必须带值,例如proxy_socket_keepalive on 240s 10s 3;
根据运营商防火墙超时定制探测参数
运营商设备超时值通常不公开,但实测多落在 5 分钟(300 秒)以内。探测窗口(idle + interval × probes)必须略小于该值,才能抢在断连前主动清理失效 socket:
-
idle(首次探测延迟):设为预估超时的 70%~80%,如不确定可先试
300s或240s -
interval(探测间隔):建议
5s–15s,10s是多数场景平衡点,太小易触发内核限速 -
probes(失败重试次数):
3足够,既能容忍偶发丢包,又不会拖长失效感知时间 - 错误示例:
proxy_socket_keepalive on 60s 60s 1;—— 第一次探测还没发出,连接已被清掉
同步调整系统级 TCP Keepalive 参数
Nginx 的 proxy_socket_keepalive 依赖内核行为。若系统参数仍为默认(tcp_keepalive_time=7200),Nginx 即使配了小 idle,内核也可能不响应探测请求:
- 执行:
sysctl -w net.ipv4.tcp_keepalive_time=300 - 执行:
sysctl -w net.ipv4.tcp_keepalive_intvl=10 - 执行:
sysctl -w net.ipv4.tcp_keepalive_probes=3 - 写入
/etc/sysctl.conf并运行sysctl -p永久生效
验证是否真正生效
光配完不验证容易白忙一场。推荐两个低成本验证方式:
- 用
tcpdump抓包观察:运行tcpdump -i any 'host [upstream_ip] and tcp[tcpflags] & (tcp-ack|tcp-push) != 0',空闲一段时间后看是否有周期性 ACK 探测包发出 - 模拟空闲压测:发起一个长连接请求后停止发数据,等待超过
idle时间,再发新请求,确认不再出现Connection reset by peer或超时 - 注意:若后端服务自身禁用了 SO_KEEPALIVE(如某些 Java 应用),探测包会被直接丢弃,需一并检查后端配置

















