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

nftables set 地址怎么配置或排查

来源:17golang原创

时间:2026-09-13 13:24:21 449浏览 收藏

我在 nftables 里处理一组白名单地址时,最容易误判的不是命令本身,而是“集合已经存在”和“规则真的引用了它”被混成了一件事。地址集合要先挂在正确的 table 上,元素类型要和匹配表达式一致,规则里还要用 @集合名 引用。

最稳妥的排查顺序是:先看 table 和 set 的定义,再看元素,再看规则引用,最后才查防火墙链路。IPv4 地址集合通常定义为 type ipv4_addr,规则匹配则写成 ip saddr @trusted_hosts
要点速览
  • named set 可以独立增删元素;匿名集合只能跟随规则改写。
  • 集合所在的 family、元素类型和规则表达式必须对齐。
  • nft list set 看定义和内容,nft get element 适合核对一个地址。

先把地址集合定义在正确的 table 中

下面用 inet 表承载一组 IPv4 白名单。它只是配置示例,不代表已经在某台机器上执行;生产环境应先确认现有规则不会被覆盖。

# 创建一个同时支持 IPv4/IPv6 规则的表,并定义 IPv4 地址集合
nft add table inet filter
nft add set inet filter trusted_hosts { type ipv4_addr\; comment "可信来源地址"\; }

# 查看集合的定义、类型和当前元素
nft list set inet filter trusted_hosts

这里的 trusted_hosts 是 named set,所以后续可以独立添加和删除地址。type ipv4_addr 只接受 IPv4 地址或 IPv4 网段;如果规则写的是 ip6 saddr,就应另建 type ipv6_addr 的集合。若系统已存在同名 table 或 set,先用 list tableslist sets 确认,不要盲目重复创建。

nftables inet filter 中 trusted_hosts IPv4 地址集合定义关系示意图
图1:nftables 地址集合定义的静态关系示意图,不是实际运行截图。

添加地址并确认规则确实引用了 set

定义完成后,元素管理和规则引用分开处理。一个地址、多个地址和网段都可以放进同一个集合;规则侧使用 @ 而不是把集合名当普通字符串。

# 向 named set 添加单个地址和一个网段
nft add element inet filter trusted_hosts { 192.0.2.10 }
nft add element inet filter trusted_hosts { 198.51.100.0/24 }

# 将集合引用到输入链;注释说明这条规则保护的范围
nft add chain inet filter input
nft add rule inet filter input ip saddr @trusted_hosts accept comment "允许可信来源"

排查时先看三处输出:nft list set inet filter trusted_hosts 是否有地址,nft list chain inet filter input 是否出现 @trusted_hosts,以及规则是否位于实际经过的链。只看到集合存在,并不能说明数据包已经命中它。

现象优先检查常见原因
添加时报类型错误set 的 typeIPv4、IPv6 或端口类型写错
集合有地址但规则不生效规则表达式和链没有使用 @set,或流量没有经过该链
想删一个地址却删不掉地址的精确写法添加的是网段,删除时却写成单个主机

用 list、get 和 flush 缩小排查范围

list set 适合看整体,get element 适合核对一个元素。需要清空集合时用 flush set,它会保留集合定义但移除其中元素;误用 delete set 则会连集合本身一起删除。

# 精确查询一个地址是否位于集合中;地址必须符合集合类型
nft get element inet filter trusted_hosts { 192.0.2.10 }

# 删除一个元素,保留 set 和引用它的规则
nft delete element inet filter trusted_hosts { 192.0.2.10 }

# 清空元素但保留集合结构;执行前确认这不是线上白名单
nft flush set inet filter trusted_hosts

如果 get element 查不到地址,先修元素而不是改规则;如果能查到而规则仍无效,再检查地址族、源地址是否被 NAT 改写、链的 hook/优先级和前面的终止性规则。这个顺序能避免把集合问题误诊成网络问题。

nftables list set get element flush set 与规则引用的排查边界示意图
图2:nftables 集合排查中定义、元素和规则引用的静态边界图。

interval、timeout 和持久化配置别混用

需要保存连续地址范围时,可以在集合创建时声明 flags interval;需要让元素自动过期时使用 flags timeout。两者解决的是不同问题,不要为了“功能更全”随意叠加 flag;也不要把动态更新场景和只读常量集合混在一起。

table inet filter {
    # interval 适合表达连续地址范围,元素仍按 IPv4 解析
    set office_ranges {
        type ipv4_addr
        flags interval
        elements = { 192.0.2.0/24 }
    }

    # 规则使用 @ 名称引用集合;配置可由 nft -f 文件加载
    chain input {
        type filter hook input priority filter; policy drop;
        ip saddr @office_ranges accept
    }
}

把配置写进文件后,可用 nft -c -f firewall.nft 做语法检查,再按发行版的 nftables 服务方式加载。最后再次执行 nft list ruleset,确认 set 和规则都出现在预期的 family/table 下。

常见问题

nftables set 地址能不能直接写在规则里?

可以,花括号里的匿名集合适合一次性规则;需要后续增删地址时使用 named set,维护更清晰。

为什么 set 里有地址,匹配仍然失败?

重点看规则是否写成 ip saddr @set名、流量是否经过该链,以及地址是否在 NAT 后发生了变化。

删除元素前要不要先 flush?

不需要。删除单个地址用 delete element;只有要清空全部元素并保留集合定义时才使用 flush set

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