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

nftables 动态集合怎样让临时封禁规则自动过期怎样在批处理代码中减少额外分配

来源:17golang原创

时间:2026-11-10 06:02:13 119浏览 收藏

如果临时封禁还在为每个地址创建一条独立规则,过期时再逐条删除,批量任务很快就会变成频繁改写规则集。更适合的做法是把地址放进 nftables 的 named set:规则只引用集合,集合元素分别携带 timeout,到期后由 nftables 清理元素。

官方地址:https://wiki.nftables.org/wiki-nftables/index.php/Sets

临时封禁的关键迁移是“规则固定、集合变化”:用 flags timeout 开启超时元素,用元素级 timeout 表达不同封禁时长;批处理则把多个元素合并到一次 nft 输入中,减少重复进程和重复解析。
要点速览
  • named set 可以独立更新,规则不必随着每个地址变化。
  • flags timeout 与元素级 timeout 配合,能让地址自动失效。
  • 批处理一次提交多个元素,通常比循环执行多次 nft add element 更省进程启动与解析开销。

先把临时规则迁移到可更新的 named set

单条规则的生命周期和封禁地址绑定在一起:地址增加就要改规则,地址过期又要删除规则。named set 则把这两个职责拆开,规则只负责匹配 @temp_ban,地址和过期时间由集合保存。nftables 官方文档也明确区分了 anonymous set 与 named set:前者绑定规则、不能单独更新,后者可以被持续更新。

方案变化对象过期处理批量代价
每个地址一条规则规则集脚本逐条删除规则解析和进程调用次数多
named set集合元素元素自动超时规则固定,批量更新集合
静态集合集合元素没有独立超时需要额外清理任务

如果封禁规则还需要计数、日志或限速,仍然可以让规则负责这些动作;集合只保存“哪些地址在封禁窗口内”。这样迁移后,封禁策略的结构更稳定,批处理代码也不必反复生成完整规则。

新写法:为集合和元素分别设置超时

下面是一段适合放进现有规则文件的最小结构示意。它把集合声明、规则引用和元素加入分开写,便于由配置管理或批处理程序按需更新。示例中的地址使用文档保留网段,仅作说明。

# 创建一个独立的 inet 表,实际环境可复用已有表。
nft 'add table inet guard'

# 开启超时元素,并设置垃圾回收检查间隔。
nft 'add set inet guard temp_ban { type ipv4_addr; flags timeout; gc-interval 1m; }'

# 规则固定引用集合,地址变化时不需要重建这条规则。
nft 'add chain inet guard input { type filter hook input priority filter; policy accept; }'
nft 'add rule inet guard input ip saddr @temp_ban drop'

# 每个元素可以拥有自己的临时封禁时长。
nft 'add element inet guard temp_ban { 192.0.2.10 timeout 15m, 192.0.2.11 timeout 5m }'

flags timeout 是集合支持超时元素的开关,gc-interval 只在启用超时时有意义。集合级默认 timeout 可以作为统一策略,元素级 timeout 则适合表达“高风险地址封 30 分钟、普通地址封 5 分钟”这类差异。不要把 gc-interval 当成封禁时长,它只是垃圾回收检查的时间间隔。

nftables 动态集合、超时元素与固定过滤规则之间的静态职责关系说明图
图1:结构说明图展示固定过滤规则、动态集合、超时元素和垃圾回收之间的职责边界,不是运行截图。

批处理时合并输入,减少重复进程和临时对象

旧脚本常见的写法是循环执行多次 nft add element。每次调用都要启动进程、解析输入并更新集合。地址数量较多时,可以先在批处理内形成一份元素文本,再通过一次 nft -f - 提交。这样减少的是进程启动和重复解析,不是把超时时间交给脚本自己计时。

#!/usr/bin/env bash
set -euo pipefail

# 批量任务只构造一份 nft 输入,避免每个地址启动一次 nft。
{
  printf '%s\n' 'add element inet guard temp_ban {'
  for ip in 192.0.2.10 192.0.2.11 192.0.2.12; do
    # 统一在元素上声明过期时间,时间到了由 nftables 负责移除。
    printf '  %s timeout 15m,\n' "$ip"
  done
  printf '%s\n' '}'
} | nft -f -

# 只读取集合定义,不重新生成规则。
nft list set inet guard temp_ban

批量地址来自外部文件时,应先限制每行格式、去重并控制集合容量,再拼接 nft 输入。不要把未经处理的整行文本直接插入规则;如果任务需要不同的封禁时长,先在内存中按业务结果分组,然后每组生成一次元素集合。批处理完成后不必启动定时删除线程,超时元素会按 nftables 的集合语义失效。

批处理输入、动态集合元素、超时策略与过滤规则之间的静态关系说明图
图2:关系说明图展示批处理输入如何汇聚到集合元素,并与固定过滤规则和超时策略保持分离,不是执行结果截图。

回归检查:只确认集合状态和引用边界

迁移后先检查集合是否启用了超时、元素是否带有预期的时间信息,再确认过滤规则引用的是集合,而不是旧的逐条地址规则:

# 查看集合声明、元素和 timeout 信息。
nft list set inet guard temp_ban

# 查询单个地址是否仍在集合中;不存在时应按已过期或未加入处理。
nft get element inet guard temp_ban { 192.0.2.10 }

# 查看过滤链,确认规则引用 @temp_ban。
nft list chain inet guard input

这几个命令只用于读取本机规则状态。自动化任务应该把“元素不存在”视为一个可处理的状态,而不是无条件重试加入;否则过期地址可能被旧任务重新写回集合。若需要上限,给集合配置 size,并在批处理端对超限进行明确的丢弃或延迟策略。

迁移清单:把规则变化收敛到集合元素

  1. 保留一条稳定的过滤规则,用 @temp_ban 引用 named set。
  2. 集合声明使用正确的 type,临时地址集合开启 flags timeout。
  3. 按元素设置 timeout,不要把 gc-interval 误当作封禁时长。
  4. 批处理先去重、限量,再一次提交多个元素,避免每个地址独立启动 nft。
  5. 检查集合大小、元素过期和旧规则残留,确认任务不会把已过期地址重新加入。

这套结构适合短期、可自动失效的地址封禁;如果需要审计、人工审批或跨主机一致性,集合之外仍要保留事件记录和配置来源,不能把 nftables 集合当成完整的策略数据库。

相关问题

集合有了 timeout,还需要脚本定时删除元素吗?

通常不需要为正常过期再写删除线程。脚本的职责是加入和更新元素,集合负责按 timeout 失效;但业务审计和异常回滚仍可以保留独立记录。

为什么不直接给每条规则设置 timeout?

逐条规则会让规则集频繁变化,批量任务还要处理规则顺序与删除失败。把地址放进 named set 后,规则结构稳定,临时变化集中在元素层。

gc-interval 越小越好吗?

不是。它影响垃圾回收检查的节奏,过小会增加管理开销;封禁准确时长由元素的 timeout 表达,应根据地址规模和管理频率选择合理间隔。

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