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

nftables set timeout 自动清理临时地址的配置

来源:17golang原创

时间:2026-11-13 19:04:46 123浏览 收藏

如果临时封禁地址直接写进一条永久规则,最容易出现两个问题:封禁结束后忘记删除,或者为了清理地址再额外维护一套定时任务。nftables 的命名集合可以把地址从规则中拆出来,再用 timeout 给集合元素设置寿命。元素到期后不再参与集合匹配,清理动作由 nftables 的集合机制负责。

官方地址:https://wiki.nftables.org/

本文只讨论 IPv4 临时地址集合:集合默认存活时间、单个地址的覆盖时长、输入链引用、生命周期观察,以及如何把静态规则和动态地址分开。示例中的地址与时长都是说明值,不代表已经在某台机器上执行。

先分清 timeout、expires 和规则匹配

timeout 是集合或元素使用的时长配置;expires 是当前元素还剩多久的倒计时。创建集合时可以设置一个默认 timeout,添加某个地址时也可以显式指定该地址的 timeout。规则只负责引用集合,例如 ip saddr @temporary_block;它不负责逐个删除到期地址。

对象作用生产上要关注什么
命名集合保存可动态更新的地址名称和类型要稳定,供规则引用
集合 timeout为未单独指定时长的元素提供默认值控制临时地址的最长预期寿命
元素 timeout覆盖某个地址的默认时长用在不同风险等级或不同来源的临时封禁上
expires展示当前倒计时它会减少,不能当成固定配置保存回配置文件

需要特别注意:重新加载一份只包含静态集合定义的规则文件,可能会改变或覆盖运行时动态元素。动态地址与静态防火墙骨架最好分开管理,并在发布前决定是否允许重载清空临时状态。

nftables 临时地址集合、timeout 配置与输入链 drop 规则之间的静态关系图
图1:nftables 集合、元素寿命和输入链匹配关系的结构说明图;这不是运行截图。

创建带 timeout 的 IPv4 命名集合

先创建一个可命名、可更新的集合。集合类型写成 ipv4_addr,flags timeout 表示元素允许带超时;timeout 10m 是未单独指定时的默认寿命。集合名要短且稳定,因为后续规则会使用这个名字。

# 创建独立表,避免把示例集合混入已有业务表。
nft add table inet temporary_guard

# 用分号结束集合属性;默认元素 10 分钟后失效。
nft 'add set inet temporary_guard temporary_block { type ipv4_addr; flags timeout; timeout 10m; }'

# 验证集合的静态定义,重点看 type、flags 和 timeout。
nft list set inet temporary_guard temporary_block

如果系统已经有同名表或集合,不要盲目重复执行创建命令。生产脚本应先明确“首次安装”和“更新已有规则”两条路径:首次安装可以创建对象,更新路径则应使用预期的配置管理方式,避免把重复对象错误解释成地址清理失败。

集合的默认 timeout 只影响之后添加且没有单独指定时长的元素。它不是“每十分钟清空整个集合”的定时器,也不会改变输入链本身的匹配语义。

把集合接入输入链,再添加临时地址

集合创建后,还需要一条规则引用它。下面的示例创建一个输入链,并让集合中的源地址被丢弃;随后添加一个使用默认 10 分钟寿命的地址,再添加一个只保留 90 秒的高优先级临时地址。

# 建立带 input hook 的链;priority 设为 0,便于在示例中明确顺序。
nft 'add chain inet temporary_guard input { type filter hook input priority 0; policy accept; }'

# 集合命中时丢弃来源地址,未命中流量仍按链的默认策略处理。
nft add rule inet temporary_guard input ip saddr @temporary_block counter drop

# 未指定时长的元素使用集合默认 timeout=10m。
nft add element inet temporary_guard temporary_block { 192.0.2.10 }

# 为单个地址设置更短的 90 秒寿命,覆盖集合默认值。
nft add element inet temporary_guard temporary_block { 192.0.2.11 timeout 90s }

这里的 counter 只是帮助观察规则是否被命中,不是 timeout 的实现依赖。若临时地址来自自动化系统,应让自动化系统只负责提交地址和业务原因,集合本身负责到期删除;不要同时再启动一个“按分钟扫描并删除”的清理器。

临时封禁前要确认地址来源是可信的内部判定结果。示例使用文档保留地址,避免把真实用户地址或敏感网络拓扑写进文章和配置。

用 list 观察元素是否正在倒计时

查看集合时,元素通常会同时展示它的 timeout 和 expires。前者是加入时采用的寿命配置,后者是当前剩余时间。不要把一次 list 输出中的 expires 值复制回持久化文件,因为它是随时间变化的运行时状态。

# 查看集合与元素倒计时;输出中的 expires 会随时间减少。
nft list set inet temporary_guard temporary_block

# 需要脚本消费时使用 JSON 输出,避免依赖普通文本的列对齐。
nft --json list set inet temporary_guard temporary_block

静态说明上可以这样判断:如果元素仍在集合里,输入链引用它时仍会命中;倒计时结束后,元素会被移出集合,后续同一来源地址不再因为这条集合规则命中。这个过程不等于连接跟踪表的超时,也不等于 TCP 会话被主动断开。

nftables 集合元素从加入到 timeout 到期并停止匹配的生命周期说明图
图2:临时地址元素从加入、倒计时到到期移除的操作示意图;这不是运行截图。

生产配置的权限、日志与持久化边界

生产环境建议把“谁能修改集合”和“谁能修改完整防火墙策略”分开。能执行 nft add element 的身份原则上也能改变临时封禁范围,因此不要把该权限无条件授予普通业务进程;更稳妥的是由一个受控服务接收经过鉴权的事件,再由最小权限的执行单元更新集合。

日志方面,集合元素自身的到期不天然等于一条业务审计事件。如果需要追溯“为什么封禁、由谁添加、何时解除”,应在调用 nft 命令的自动化入口记录事件 ID、地址、原因、申请者和预期时长;不要把 expires 的展示值当作审计时间戳。

持久化时,把静态规则骨架和运行时临时集合分成两层:

  • 静态层保存表、链、策略和集合定义,变更前做文本审阅。
  • 运行时层只添加或删除临时元素,保留调用记录和幂等键。
  • 重载静态层前先说明是否保留运行时集合;不要用一次全量 flush 代替有范围的变更。
  • 回滚时先恢复静态规则,再决定是否清空临时地址,避免把安全策略和业务状态混成一次操作。
# 发布前先列出目标表,避免在错误的 family 或 table 上操作。
nft list table inet temporary_guard

# 发布脚本只做有范围的元素删除,不把整张表作为清理目标。
nft delete element inet temporary_guard temporary_block { 192.0.2.10 }

# 回滚前保留规则快照;这里的输出应由发布系统写入受控审计目录。
nft list ruleset

发布前检查清单与常见问题

上线这类临时集合时,可以用下面的顺序减少误操作:

  1. 确认集合类型是 ipv4_addr,且规则引用的集合名称完全一致。
  2. 确认集合启用了 flags timeout,默认 timeout 与业务封禁时长匹配。
  3. 对一个测试地址使用短 timeout,观察 expires 是否出现并自然消失。
  4. 确认删除集合元素不会误删表、链或其它业务集合。
  5. 确认持久化重载策略不会在没有告警的情况下清空仍需保留的运行时状态。

为什么添加了地址,却没有看到 expires?

常见原因是集合没有开启 flags timeout,或者实际添加的不是预期集合。先用 nft list set 查看集合定义,再确认添加命令使用了相同的 family、table 和 set 名称。

把 expires 写入配置文件能让倒计时继续吗?

不能把它当作固定配置。expires 是观察时刻的剩余时间;配置文件应记录业务允许的 timeout,运行时元素则由自动化入口重新添加。需要跨重启保留临时状态时,应明确记录原始加入时间和剩余策略,再由受控程序恢复,而不是直接复制一次 list 输出。

timeout 到期会主动断开已经建立的连接吗?

不会把集合元素 timeout 等同于连接跟踪或已建立连接的生命周期。它控制的是该地址是否仍在集合中、是否继续命中引用集合的规则;连接是否结束取决于其它防火墙规则和协议状态。

小结:用命名集合承载临时 IPv4 地址,用 flags timeout 开启元素寿命,用集合默认 timeout 覆盖常规场景,再用单元素 timeout 处理例外。输入链只引用集合,自动化入口负责鉴权和审计,发布系统负责把静态规则与运行时状态分层管理,这样临时地址到期后能自然失效,也不容易被一次重载或误删操作扩大影响。

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