Linux nftables set 怎样按集合管理访问规则
来源:17golang原创
时间:2026-11-02 14:01:51 365浏览 收藏
Linux nftables 里,set 适合把一批同类型的地址、端口或接口名集中起来,再让一条规则引用这批成员。真正需要长期维护访问名单时,应使用 named set;只在某一条规则中做一次匹配时,匿名集合就够了。这样新增或删除地址时只改集合,不必重复改写所有规则。
官方资料地址:https://wiki.nftables.org/wiki-nftables/index.php/Sets
最实用的落地路径是:先声明集合类型,再用@集合名接入规则,之后通过add element、delete element和list set维护成员。临时封禁再加timeout,网段集合则考虑interval与auto-merge。
先分清匿名集合和 named set
nftables 的集合本质上是同一数据类型的一组元素。匿名集合直接写在规则里,例如端口集合:
# 一次性匹配 SSH 和 HTTPS;集合跟随这条规则存在。
nft add rule inet filter input tcp dport { 22, 443 } accept
这种写法短而直接,但它没有独立名字,后续不能像资源清单一样单独增删成员。如果名单会被多条规则共享,或需要由脚本定期更新,就应该创建 named set。官方文档也明确区分了两者:匿名集合绑定在规则上,named set 则可以单独更新。

创建地址集合并接入访问规则
下面的例子用 inet 表族创建一个 IPv4 地址集合。集合的 type 必须和成员类型一致,规则中的 ip saddr 也要与它相匹配。
# 创建表和输入链;重复执行前请先确认名称没有冲突。
nft add table inet edge_filter
nft 'add chain inet edge_filter input { type filter hook input priority 0; policy drop; }'
# 声明一个可独立维护的 IPv4 地址集合。
nft 'add set inet edge_filter trusted_v4 { type ipv4_addr; }'
# 把可信来源加入集合,再让规则引用集合。
nft 'add element inet edge_filter trusted_v4 { 192.0.2.10, 198.51.100.0/24 }'
nft 'add rule inet edge_filter input ip saddr @trusted_v4 tcp dport 22 accept'
这里的重点不是把地址写进规则,而是让规则只依赖集合名。后续名单变化时,规则仍然保留。生产环境中应按自己的默认策略补齐 established/related、回环和管理入口等规则,避免把这个示例直接当成完整防火墙策略。
只修改成员,不重写规则
named set 的价值在于成员生命周期独立于规则。管理员可以把一批地址一次性加入,也可以删除单个成员;集合引用关系不需要变化。
# 批量加入新的可信地址;花括号内的元素必须符合 ipv4_addr 类型。
nft 'add element inet edge_filter trusted_v4 { 192.0.2.11, 203.0.113.7 }'
# 删除不再信任的单个地址;删除成员不会删除引用它的规则。
nft 'delete element inet edge_filter trusted_v4 { 203.0.113.7 }'
# 查看集合的完整成员和声明,便于记录变更前后的状态。
nft list set inet edge_filter trusted_v4
# 查询一个地址是否存在;大集合或区间集合更适合用 get 判断。
nft 'get element inet edge_filter trusted_v4 { 192.0.2.11 }'
如果 add element 报类型错误,先检查集合声明而不是盲目改地址格式。比如把 IPv6 地址加入 ipv4_addr 集合,属于模型不匹配;应新建 ipv6_addr 集合,或在规则和表族设计中明确双栈边界。

临时封禁用 timeout,网段集合用 interval
如果名单只应保留一段时间,可以在集合上启用 flags timeout,并为每个成员指定过期时间。超时是成员属性,不需要额外定时任务去执行删除。
# 创建支持成员超时的临时封禁集合;size 预留上限便于规划资源。
nft 'add set inet edge_filter temp_block { type ipv4_addr; flags timeout; size 4096; }'
# 新增地址并设置 10 分钟有效期;到期后成员会从集合中消失。
nft 'add element inet edge_filter temp_block { 198.51.100.23 timeout 10m }'
# 用集合命中后丢弃来源流量;集合为空时规则不会匹配到地址。
nft 'add rule inet edge_filter input ip saddr @temp_block drop'
如果集合用来保存连续地址段,则考虑 flags interval。多个相邻或重叠元素可能导致规则文件加载冲突,此时可以使用 auto-merge 让 nftables 合并相邻或重叠区间。auto-merge 只适用于 interval 集合,不要把它当成普通地址集合的通用开关。
table inet edge_filter {
# interval 集合用于表达地址段,auto-merge 减少重叠区间冲突。
set office_ranges {
type ipv4_addr
flags interval
auto-merge
elements = { 192.0.2.0/28, 198.51.100.0/25 }
}
}
按三层清单做变更和回滚
我在实际维护中会把 nftables set 的变更拆成集合、规则、文件三层。集合层回答“成员是谁”,规则层回答“命中后做什么”,文件层回答“重启或恢复时从哪里加载”。三层混在一起时,最容易出现临时命令生效、重启后却丢失的问题。
# 先保存当前规则集,便于审查修改范围和准备回滚文件。
nft list ruleset > /var/tmp/edge-filter-before.nft
# 只查看目标集合,确认成员、类型和 timeout 等属性。
nft list set inet edge_filter temp_block
# 删除误加入的临时成员;这比删除整条规则影响面更小。
nft 'delete element inet edge_filter temp_block { 198.51.100.23 }'
# 需要恢复时加载已审查的 nftables 文件,避免手工遗漏规则。
nft -f /etc/nftables.conf
若使用发行版的 nftables 服务,还应把最终配置写入该服务加载的规则文件,并确认文件中的集合定义与运行时临时变更一致。nft list ruleset 只说明当前内核规则集,不会自动替你把临时变更写回配置文件。
常见错误与迁移清单
| 现象 | 优先检查 | 处理方向 |
|---|---|---|
| 集合无法加入成员 | type 与地址、端口类型不一致 | 重新确认 ipv4_addr、ipv6_addr、inet_service 等类型 |
| 规则找不到集合 | 表族、表名、集合名是否一致 | 使用完整的 family table set 路径 |
| 匿名集合无法动态更新 | 集合是否直接写在 rule 中 | 改为 named set,再让规则引用 @集合名 |
| 临时封禁不自动消失 | 是否声明 flags timeout 且元素带 timeout | 同时检查集合属性和元素属性 |
| 网段加载报 conflicting intervals | interval 元素是否重叠 | 合并网段或启用 auto-merge |
| 重启后名单丢失 | 临时命令是否写回配置文件 | 保存并审查 nftables.conf,再由服务加载 |
把重复条件改成集合,解决的是规则维护成本,不会自动解决默认策略、连接跟踪、双栈设计和配置发布流程。正式变更前保留规则集备份,先在低风险入口确认集合类型和作用范围,再逐步扩大名单。
named set 和匿名集合应该怎么选?
规则内一次性匹配用匿名集合;需要被多条规则引用或需要独立增删成员时,用 named set。
删除 named set 会不会自动删除规则?
不应把删除集合当成安全的回滚动作。先找出引用该集合的规则,再按集合、规则的依赖关系修改。
timeout 是集合级还是成员级?
集合需要声明支持 timeout,具体持续时间可以在新增元素时按成员设置。
为什么地址段集合加载失败?
常见原因是 interval 元素重叠或相邻但未合并;检查 flags interval,并按需要启用 auto-merge。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
269 收藏
-
209 收藏
-
420 收藏
-
239 收藏
-
276 收藏
-
419 收藏
-
371 收藏
-
490 收藏
-
307 收藏
-
273 收藏
-
277 收藏
-
126 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习