在linux中用nftables实现子网新建连接数“刚性红线”拦截,核心是匹配ct state new、设limit rate 60/minute burst 1 packets drop,仅限新连接、禁突发、不误伤长连接,规则须置input链靠前并固化验证。

在 Linux 中使用 nftables 的 limit 表达式实现对特定业务子网的每分钟新建连接数“刚性红线”拦截,核心在于:用 ct state new 匹配首次建立的连接,并结合 limit 模块设定精确速率(如 60/minute),再通过 drop 实现超限即断,不排队、不缓冲、不放行——这才是真正的“刚性拦截”。
明确匹配目标:只限新连接,不碰已有会话
关键点是必须限定在连接跟踪状态为 new 的数据包,否则会误伤已建立的长连接(如数据库连接、SSH 会话)。nftables 不像旧版 iptables 那样依赖 connlimit 模块,它原生支持基于连接状态的精准过滤:
-
ct state new是硬性前提,确保仅对 TCP SYN 或 UDP 首包等新建连接行为生效 - 避免使用
tcp flags & (fin | syn | rst | ack) == syn这类手工标志匹配——不可靠,且不适用于 UDP 或非标准协议 - 若业务含多端口(如 Web + API + 管理端口),建议统一用
ip saddr子网匹配,而非逐端口写规则
配置刚性 limit:rate + burst + drop 组合拳
limit 表达式默认采用令牌桶算法,但要达成“刚性红线”,需关闭突发容忍(burst 设为 1)并严格绑定速率。例如限制 192.168.10.0/24 子网每分钟最多 60 个新连接:
nft add rule ip filter input ip saddr 192.168.10.0/24 ct state new limit rate 60/minute burst 1 packets drop
-
rate 60/minute:表示每 60 秒重置计数器,窗口严格对齐分钟边界(nftables v0.9.4+ 支持精确时间单位) -
burst 1:禁止任何突发,第 61 个新连接包立即被丢弃,不缓存、不延迟、不警告 -
packets:按包计数(非字节),适配连接新建场景;若用bytes则无意义 - 务必放在
input链中靠前位置(早于 ACCEPT 规则),否则可能被提前放行
验证与固化:确保规则持久且可测
临时规则重启即失效,生产环境必须固化;同时需验证是否真“刚性”生效:
- 保存规则:
nft list ruleset > /etc/nftables.conf(或使用发行版对应服务如nftables.service) - 模拟压测:用
for i in {1..70}; do timeout 0.1s nc -zv 192.168.10.100 80 & done快速发起 70 次连接尝试,观察后 10 个是否全部失败(返回Connection refused或超时) - 实时监控:
nft monitor trace可捕获匹配过程;nft list chain ip filter input查看当前计数器值(部分内核版本支持counter附加统计) - 注意:limit 计数器不跨 CPU 核心同步,高并发下极短时间内可能出现微小越界(通常 ≤ 2–3 个),属内核设计限制,不影响分钟级刚性约束
进阶加固:配合日志与子网隔离
单纯 drop 不留痕不利于审计,建议叠加轻量日志并隔离策略域:
- 添加日志(不降低性能):
log prefix "LIMIT_BLOCK: " level warn放在drop前,仅记录被限流的首包 - 独立链提升可维护性:创建专用链
business-limit,将子网限流规则放入其中,再从input跳转,便于后续扩展白名单或分级限速 - 若子网内含可信管理主机(如跳板机),可在限流规则前加例外:
ip saddr 192.168.10.200 counter accept - 勿与
nf_conntrack_max参数混淆——那是系统级连接总数上限,和 per-subnet 的新建速率控制无关











