匿名集合是结构化表达方式,用于将多个固定值打包进大括号以减少规则数量、提升可读性,适用于策略稳定且变更频率低的场景,如内网白名单、端口开放列表等。

匿名集合不是“省事小技巧”,而是用对时机的结构化表达方式——它把多个固定值打包进一对大括号,让一条规则承担原本需要多条规则完成的任务,前提是这些值短期内不会变。
什么时候该用匿名集合?
适合策略稳定、变更频率低的场景:
- 内网管理网段白名单(如只允许 10.10.0.0/16 和 172.16.5.0/24 访问后台)
- 基础服务端口开放列表(如仅放行 22、80、443、3000)
- 固定接口信任列表(如只接受来自 eth0 和 br0 的入向流量)
- 协议与端口组合(如 tcp dport {22, 80, 443} + udp dport {53, 123})
只要半年内调整不超过两三次,匿名集合就能显著减少规则数量、提升可读性。
怎么写才真正简洁又安全?
关键在语法准确和位置合理:
- 多个值用英文逗号分隔,前后不加空格:{22,80,443,3000}(不是 {22, 80, 443, 3000})
- 混合类型要对应字段:ip saddr 放 IP/网段,tcp dport 放端口号,不能混用
- 用 != 表示“不在集合中”,常用于静默封禁:tcp dport != {22,80,443} ct state new drop
- 必须放在所有 accept 规则之前,否则会被跳过
哪些坑最容易踩?
匿名集合本身简单,但误用会导致策略失效或维护困难:
- 想临时加一个IP?不行——只能整条规则删掉重写,没有“追加”操作
- 想看某条规则里用了哪些端口?nft list ruleset 会原样显示大括号内容,但没法单独提取或统计
- 加了注释?shell 会报错——匿名集合不支持任何注释语法
- 配了 counter?不生效——匿名集合无法嵌入计数器,需改用命名集合
一旦发现端口或IP开始频繁增减,就该切换到命名集合,而不是硬撑。
和命名集合比,到底差在哪?
核心区别是“可维护性”:
- 匿名集合:写死在规则里,改=删+重建,适合一次配好长期不动
- 命名集合:独立存在,用 nft add element 动态增删,适合需响应变化的生产环境
- 命名集合还能带 timeout 自动过期、支持 interval 匹配网段、可绑定 counter 统计命中
- 查当前元素?nft list set ip filter allowed_ips 直接列出,清晰可控
别为了省一行命令牺牲后续三个月的运维效率。

















