iptables连接限制必须在filter表INPUT链使用--syn和connlimit模块,raw表不支持;正确命令为iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 20 -j DROP,需确保nf_conntrack已加载、规则位置靠前且阈值合理。

这条命令本身存在语法错误,无法直接运行生效,更谈不上“刚性熔断”。问题出在几个关键位置:-T Raw 指定表名后不能直接跟 -A Prerouting(链名写法错误),-P Tcp 应为 -p tcp(协议参数是小写 -p,不是大写 -P),且 raw 表不支持 connlimit 模块——该模块仅在 filter 表的 INPUT 或 FORWARD 链中可用。
真正能起效、贴近你意图的方案,是把连接限制逻辑放在 filter 表的 INPUT 链,并确保规则在 SYN 包进入连接跟踪前就完成判断。以下是可落地的操作要点:
✅ 正确写法与执行逻辑
这条命令应修正为:
iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 20 -j DROP
说明:
- 必须用
-p tcp(小写 p),不是-P Tcp -
connlimit只在filter表生效,raw表不识别该模块 -
--syn已隐含匹配 TCP 新连接请求,无需额外-m state --state NEW -
-j DROP是静默丢弃,比REJECT更节省资源(不发 RST 包)
⚙️ 配合生效的关键前提
- 确保
nf_conntrack模块已加载:lsmod | grep nf_conntrack - 规则必须放在其他
ACCEPT规则之前(例如在iptables -A INPUT -p tcp --syn -j ACCEPT之前),否则会被提前放过 - 若使用
DOCKER或KUBERNETES,需注意其自动生成规则可能覆盖或干扰你的策略,建议加-I INPUT 1插入最前
? 阈值设置要合理
--connlimit-above 20 表示单个 IP 同时发起超过 20 个未完成的 TCP 连接(即处于 SYN_RECV 状态)即触发拦截。这个值需按业务调整:
- 静态网页/轻量 API:10~30 较稳妥
- Websocket 长连接服务:需提高到 100+,否则误杀正常用户
- 含 CDN 或 NAT 环境:阈值要大幅下调(如 3~5),因多个真实用户共享一个出口 IP
? 建议搭配的增强措施
- 加上速率限制防突发:
iptables -A INPUT -p tcp --syn -m hashlimit \ --hashlimit-name syn_per_ip \ --hashlimit-mode srcip \ --hashlimit 5/sec \ --hashlimit-burst 15 \ -j ACCEPT iptables -A INPUT -p tcp --syn -j DROP
- 封禁后记录日志便于溯源(加
-j LOG --log-prefix "SYN_FLOOD "再接DROP) - 配合内核参数启用兜底防护:
echo 1 > /proc/sys/net/ipv4/tcp_syncookiesecho 4096 > /proc/sys/net/ipv4/tcp_max_syn_backlog
不复杂但容易忽略。


















