登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

nftables 动态集合维护临时封禁地址

来源:17golang原创

时间:2026-10-10 16:23:26 248浏览 收藏

我更愿意把 nftables 的临时封禁写成“命名集合 + 一条匹配规则”,而不是让封禁程序不断改写整份规则集。集合只保存地址,规则只负责引用集合;地址的存活时间交给元素级 timeout,到期后它自然不再匹配。这样既方便接入 fail2ban 一类的检测程序,也不会把一次短时封禁变成永久配置。

要点速览
  • 临时封禁集合至少要明确元素类型、超时策略和容量上限。
  • timeout 决定元素多久失效,gc-interval 主要影响过期元素何时回收内存。
  • 外部程序可用 add element 维护地址;需要每次命中都续期时,才考虑规则里的 update。

nftables 临时封禁的集合边界

这篇只处理 IPv4 源地址的临时封禁:inet guard 是表,input 是入口链,temp_ban 是命名集合,最后由 ip saddr @temp_ban drop 引用它。表和链属于规则结构,集合则是会被维护的地址容器,四者不要混成一段定时生成的大规则。

如果现有规则有内网白名单,封禁规则应放在白名单放行之后;如果机器同时提供 IPv6 服务,应另外设计 ipv6_addr 集合或使用明确的双栈方案,不能假设 IPv4 集合会自动匹配 IPv6。

用 timeout 集合表达自动失效

下面的命令使用文档保留地址 203.0.113.0/24,只用于示例。集合设置了 15 分钟默认有效期、30 秒垃圾回收间隔和 65536 个元素的上限;封禁规则本身不保存某个地址,所以后续维护只需要操作集合。

# 建立专用于临时封禁的 inet 表;已有同名表时不要重复执行
sudo nft add table inet guard

# 创建 IPv4 地址集合:默认 15 分钟失效,并限制集合最大容量
sudo nft add set inet guard temp_ban "{ type ipv4_addr; flags timeout; timeout 15m; gc-interval 30s; size 65536; }"

# 建立入口链;生产环境要把 priority 和现有链路一起评估
sudo nft add chain inet guard input "{ type filter hook input priority 0; policy accept; }"

# 集合命中的源地址计数后丢弃,集合内容仍可独立维护
sudo nft add rule inet guard input ip saddr @temp_ban counter drop

这里使用 flags timeout,意味着每个元素可以携带自己的超时值。若所有地址都使用默认的 15 分钟,可以直接添加地址;需要更短或更长的封禁时,在元素后写出具体时间:

# 对单个地址设置 10 分钟封禁,timeout 从添加时开始倒计时
sudo nft add element inet guard temp_ban "{ 203.0.113.10 timeout 10m }"

# 另一个地址使用更短的临时封禁,地址范围仅为文档示例网段
sudo nft add element inet guard temp_ban "{ 203.0.113.11 timeout 90s }"
nftables 临时封禁中 inet 表、temp_ban 地址集合、timeout 参数与 drop 规则的静态关系说明图
图1:结构说明图,展示临时封禁集合与 drop 规则之间的静态边界,不是运行截图。

把封禁地址写入并按需续期

实际项目通常由日志分析器、认证服务或人工处置脚本调用 nft add element。添加成功后,规则会自动看到这个地址;到期后元素从匹配集合中消失。要提前解除封禁,可以显式删除元素:

# 外部检测程序可以重复调用这条命令写入新的临时地址
sudo nft add element inet guard temp_ban "{ 203.0.113.12 timeout 15m }"

# 误封或提前恢复时删除元素,不需要改动 input 链规则
sudo nft delete element inet guard temp_ban "{ 203.0.113.12 }"

# 仅查看当前集合,便于确认地址是否仍在封禁窗口内
sudo nft list set inet guard temp_ban

add 和 update 的选择要谨慎:维护程序定期重申封禁、但不想让每次命中都延长窗口时,用 add 更符合“封禁一次,等待过期”的语义;如果规则路径本身要在持续异常时续期,则需要支持动态更新的集合,并用 update 刷新元素超时。规则内动态添加还应同时设计 size 与元素超时,避免异常流量把集合无限推大。

观察 expires 与容量边界

nft list set inet guard temp_ban 会显示集合元素及其 expires 倒计时。这个字段适合排查“地址还在不在封禁窗口”,但不要把它当成持久化数据库:服务重启后是否恢复,要由发行版的 nftables 配置加载机制或你自己的编排流程决定。

参数解决的问题维护判断
timeout元素多久失效按风险设置封禁时长,元素级值可覆盖默认值
gc-interval过期元素何时回收不改变到期时间;短周期集合可适当降低间隔
size集合最多容纳多少元素按峰值封禁量和内存预算设置,满载时要有告警
expires当前元素还剩多久只用于观察和排障,不应被业务当作永久状态

官方 nft 手册特别强调,垃圾回收间隔不改变元素的超时点,只影响过期条目的回收和集合计数下降。间隔过大时,元素虽然已经过期,空间仍可能暂时没有释放,集合也可能因为计数尚未回收而接近上限;短时、高频封禁场景需要把这个边界纳入容量测试。

nftables temp_ban 集合中 timeout、expires、gc-interval 与 size 的静态关系说明图
图2:边界说明图,展示过期观察、垃圾回收和容量上限的关系,不是运行截图。

常见问题

为什么设置了 timeout,地址看起来还在集合里?

先看 expires 是否已经归零,再考虑垃圾回收间隔。过期元素的回收可能不是在到期瞬间完成,但它不应继续命中有效的封禁判断;如果仍被丢弃,应检查是否还有另一条规则或另一个集合在匹配。

重复 add 会不会自动延长封禁时间?

不要依赖“重复 add”实现续期。需要明确延长窗口时,由维护程序删除后重新添加,或采用官方支持的动态集合更新语义,并把续期策略写进程序日志。

如何让临时封禁重启后仍然存在?

把表、链和集合声明纳入系统的 nftables 配置文件或配置管理流程;运行时加入的元素是否需要恢复,则要由应用保存封禁来源和剩余时长,不能只依赖内核中的瞬时集合。

当封禁来源、默认时长、集合上限和恢复策略都明确后,nftables 动态集合就只是一个边界清晰的地址容器:规则保持稳定,变化集中在集合元素本身。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>