nginx代理tcp服务时,原生仅支持limit_conn进行并发连接数限制,不支持limit_rate等http限速指令;tcp带宽限速必须依赖tc等系统级工具实现,可通过iptables标记+tc分类实现端口级或客户端差异化限速。

Nginx 代理 TCP 服务时,本身不支持像 HTTP 那样直接用 limit_rate 控制上行/下行带宽,因为 limit_rate 属于 HTTP 模块指令,仅对响应体生效,无法作用于 stream(TCP/UDP)上下文。真正的 TCP 层流量整形需分场景处理:连接数控制靠 Nginx 自身 stream 模块,而带宽限速必须依赖操作系统级工具。
1. TCP 并发连接数限流(Nginx 原生支持)
这是最常用、最轻量的防护手段,防止连接洪泛耗尽资源。
-
在
nginx.conf全局(http 块外)定义连接计数区域:stream { limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m; limit_conn_zone $server_addr zone=total_conns:10m; } -
在具体
server块中启用限制:server { listen 8000; proxy_pass backend_tcp; limit_conn conn_per_ip 5; # 单 IP 最多 5 个并发连接 limit_conn total_conns 1000; # 全局最多 1000 个连接 proxy_timeout 30s; # 空闲连接 30 秒后断开 } 超限时 Nginx 直接发送 TCP RST,不排队、无延迟,开销极低。
2. TCP 上行/下行带宽限速(需系统级工具)
Nginx stream 模块没有 proxy_upload_rate 或类似指令,所谓“TCP 上传限速”必须交由内核处理:
-
使用
tc(Traffic Control)对网卡出口(上行)或入口(下行)做整形:# 限制 eth0 出口总上行带宽为 5Mbit/s(适用于所有经该网卡发出的 TCP 流量) tc qdisc add dev eth0 root tbf rate 5mbit burst 32kbit latency 400ms # 若只想限某端口(如 8000),可结合 iptables 标记 + tc 分类 iptables -t mangle -A OUTPUT -p tcp --sport 8000 -j MARK --set-mark 1 tc class add dev eth0 parent 1: classid 1:1 htb rate 5mbit tc filter add dev eth0 parent 1: protocol ip handle 1 fw flowid 1:1
注意:
tc规则作用于网络栈底层,对 Nginx worker 进程、后端服务、甚至其他进程的流量一并管控,需按实际拓扑设计策略。
3. 区分客户端做差异化限速(间接实现)
虽然不能在 stream 中动态设 limit_rate,但可通过前置识别+分流达成近似效果:
-
利用
map指令根据$remote_addr或$http_x_forwarded_for(若前端透传)打标签:map $remote_addr $bandwidth_class { default "normal"; ~^192\.168\.1\. "internal"; 203.0.113.45 "lowrate"; } 在
stream中配合split_clients或upstream分组,将不同类别路由到不同监听端口或后端集群;-
再对各端口单独配置
tc规则,例如:-
8000→ 默认带宽(不限) -
8001→ 标记为 lowrate 的流量走tc限 1Mbps
-
这样就实现了逻辑上的“按客户端类型限带宽”。
4. 配合系统与运维保障稳定性
-
调整系统资源上限:
fs.file-max = 2097152-
ulimit -n 65536(Nginx 启动前设置) -
worker_connections 4096;(events 块中)
-
开启 stream 日志定位问题:
stream { log_format stream_log '$remote_addr [$time_local] $status $bytes_sent $bytes_received'; access_log /var/log/nginx/stream.log stream_log; } 监控连接数:
ss -s | grep "TCP:"或netstat -an | grep :8000 | wc -l
不复杂但容易忽略











