面向实战的 nftables 防火墙配置指南:从入门到高级

目录

  1. 初步准备:基础概念与常见命令
  2. 场景一:基础服务器防火墙(过滤规则)
  3. 场景二:NAT 网关(SNAT / MASQUERADE / DNAT / 端口转发)
  4. 场景三:黑名单 / 白名单 / 大量 IP 的批量管理
  5. 场景四:记录日志与限速(log / limit / meter)
  6. 场景五:仅允许特定网卡或特定连接状态(iif/oif/ct state)
  7. 场景六:桥接防火墙、VLAN 与 ingress 过滤(bridge / vlan / ingress)
  8. 场景七:IPv6 网络配置要点
  9. 其它必备命令:查看 / 修改 / 删除 / 清空规则
  10. 附:从 iptables 迁移到 nftables 的注意事项
  11. 参考资料与建议

初步准备:基础概念与常见命令

  1. Netfilter & nftables

    • Netfilter 是 Linux 内核中的网络数据包处理子系统,nftables 则是其新一代的用户态工具,用来管理防火墙和 NAT 规则。
    • 它替代了传统的 iptables、ip6tables、arptables、ebtables,提供统一的配置方式和更灵活的语法。
  2. 基本结构

    • 表(table):用于容纳“链”
    • 链(chain):一组规则的集合,同时指定在哪个处理阶段(hook)应用,如 preroutinginputforwardoutputpostrouting
    • 规则(rule):具体的匹配条件 + 动作(如 dropacceptdnatsnatlogrejectmasquerade 等)。
  3. 常见命令行

    • sudo nft add table <family> <tablename>:创建表
    • sudo nft add chain <family> <tablename> <chainname> { ... }:创建链,指定类型、hook、priority、policy 等
    • sudo nft add rule <family> <tablename> <chainname> <match> <action>:添加规则
    • sudo nft list ruleset:查看当前完整配置
    • sudo nft delete rule/chain/table ...:删除对应对象
    • sudo nft flush ruleset清空所有规则(谨慎操作)
  4. 协议族 (family)

    • ip(仅 IPv4),ip6(仅 IPv6),inet(同时管理 IPv4/IPv6),arpbridge 等。
    • 一般推荐使用 inet 统一管理 IPv4/IPv6 防火墙规则(但NAT 通常只能使用 ipip6)。
  5. 常见 hook

    • prerouting:数据包刚进来,还没决定路由
    • input:发往本机的数据包
    • forward:要转发给其他目的地的数据包
    • output:本机发出的数据包
    • postrouting:数据包即将离开本机,常用于 SNAT
    • ingress:更早阶段的过滤,在协议栈处理之前(见场景六
  6. 默认策略 (policy)

    • accept:默认放行
    • drop:默认丢弃
    • 常用做法:在关键链(如 inputforward 等)上设置 policy drop,然后再加特定的放行规则(白名单式)。
  7. 优先级 (priority)

    • 每个 hook 可以设置 priority,以决定规则生效的先后顺序。
    • 常见做法:
      • prerouting(DNAT)常用 priority -100
      • filter(如 inputforward)常用 priority 0
      • postrouting(SNAT)常用 priority 100

场景一:基础服务器防火墙(过滤规则)

在一台常见的服务器上,你可能只想开放 SSH、HTTP、HTTPS,其他都拒绝,并且对本地回环 (lo) 和已建立连接 (established) 要放行。这是典型的应用场景。

1. 创建一个表和链

# 创建一个名为 "firewall" 的表,协议族 "inet"(同时管IPv4+IPv6)
sudo nft add table inet firewall

# 在该表下创建一个链,类型 filter,挂到 input 阶段,优先级 0,默认策略为 drop
sudo nft add chain inet firewall input {
    type filter hook input priority 0;
    policy drop;
}

2. 添加基础规则

# 允许本地回环接口 (主要是127.0.0.1)
sudo nft add rule inet firewall input iifname "lo" accept

# 允许已建立(ESTABLISHED)或相关(RELATED)状态的连接继续
sudo nft add rule inet firewall input ct state established,related accept

# 允许 SSH (tcp/22)、HTTP (tcp/80)、HTTPS (tcp/443)
sudo nft add rule inet firewall input tcp dport {22,80,443} accept

# IPv4情况下:允许ICMP ping
sudo nft add rule inet firewall input ip protocol icmp icmp type echo-request accept

# IPv6情况下:允许ICMPv6 ping
sudo nft add rule inet firewall input ip6 nexthdr icmpv6 icmpv6 type echo-request accept

# 对于其他想要“显式拒绝”的端口或协议,
# 可以考虑用 reject 动作:
# sudo nft add rule inet firewall input tcp dport 23 reject with tcp reset
# (比 drop 动作更“可见”,会返回 RST 给对端)

# 以上未匹配到的流量(因为policy=drop)均丢弃

这样就完成了一个最常见的服务器防火墙规则:只允许某些常用端口和已建立的连接,其他丢弃


场景二:NAT 网关(SNAT / MASQUERADE / DNAT / 端口转发)

如果你的机器同时扮演网关角色,需要做源地址转换 (SNAT/MASQUERADE) 和目的地址转换 (DNAT),则可以在 prerouting / postrouting 阶段进行 NAT 配置。

注意:NAT 功能通常仅在 ipip6 family 下使用。常见的是 ip nat(IPv4)。

1. SNAT:出站地址转换

如果网关对外网的 IP 是 203.0.113.5,内网网卡为 eth1,外网网卡为 eth0,要让内网 192.168.1.x 的流量通过网关统一 NAT 成 203.0.113.5

sudo nft add table ip nat

# 创建 chain: postrouting,用于 SNAT
sudo nft add chain ip nat postrouting {
    type nat hook postrouting priority 100;
    policy accept;
}

# SNAT 规则
sudo nft add rule ip nat postrouting \
    oifname "eth0" \
    snat to 203.0.113.5
使用 MASQUERADE(适合动态外网 IP)

如果外网 IP 不是固定的,比如 PPPoE 拨号或 DHCP,会用 masquerade 动作,而不是手动指定 IP:

sudo nft add rule ip nat postrouting oifname "eth0" masquerade

这样系统会自动使用 eth0 当前的 IP 做 NAT,无需频繁修改。

2. DNAT:入站地址转换 / 端口转发

如果外网访问 203.0.113.5:80,想转发到内网 192.168.1.10:8080

sudo nft add chain ip nat prerouting {
    type nat hook prerouting priority -100;
    policy accept;
}

sudo nft add rule ip nat prerouting \
    tcp dport 80 \
    dnat to 192.168.1.10:8080

这样,访问网关 203.0.113.5 的 80 端口时,会重定向到内网服务器 192.168.1.10:8080

提示:在做 DNAT 后,别忘了在防火墙 forward 链里适当放行该流量,或使用 policy accept(视安全策略而定)。


场景三:黑名单 / 白名单 / 大量 IP 的批量管理

当你需要屏蔽大量可疑 IP,或者放行某些特定网段时,一条条写规则会非常繁琐。nftables 提供了 set / map 等数据结构,可一次性管理多值。

1. 黑名单示例

# 在 table inet firewall 下创建一个黑名单 set
sudo nft add set inet firewall blacklist {
    type ipv4_addr;
    flags interval;  # 可以使用网段
}

# 往黑名单里添加元素
sudo nft add element inet firewall blacklist { 1.2.3.0/24, 5.6.7.8 }

# 在 input 链的规则中引用这个 set
sudo nft add rule inet firewall input ip saddr @blacklist drop

这样就不用写多条 ip saddr X drop,以后只要

sudo nft add element inet firewall blacklist { <IP 或网段> }

即可。

动态封禁 / 过期

nftables 允许给 set 中的元素添加 “timeout” 参数,实现自动过期。适合类似“fail2ban”的场景:

sudo nft add set inet firewall blacklist {
    type ipv4_addr;
    timeout 1h;   # 每个元素默认过期时间
}

# 往里面加元素时,也可以自定义过期时长
sudo nft add element inet firewall blacklist { 1.2.3.4 timeout 10m }

到期后 1.2.3.4 会自动从黑名单中移除。

2. 白名单示例

如果只想允许一批 IP,其余全部丢弃,可以把默认策略设为 drop,然后在规则里写:

# 创建一个名为 whitelist 的 set
sudo nft add set inet firewall whitelist {
    type ipv4_addr;
    flags interval;
}

# 为了演示,先加几个IP
sudo nft add element inet firewall whitelist { 192.168.1.0/24, 10.10.10.10 }

# 在 input 链中
sudo nft add rule inet firewall input ip saddr @whitelist accept

因为链的 policy=drop,不在白名单的全部拒绝。

3. 使用 map 简化多动作映射(verdict map)

除了 set,还可以用 map 来进行“值 → 动作”的映射(或“值 → 值”的映射),进一步简化配置。例如,根据 IP 地址直接映射到不同动作:

sudo nft add map inet firewall action_map {
    type ipv4_addr : verdict;
}

sudo nft add element inet firewall action_map {
    1.2.3.4 : drop,
    10.0.0.0/8 : accept
}

# 一条规则即可处理多种动作
sudo nft add rule inet firewall input ip saddr vmap @action_map

这样比多条 if (saddr=...) drop; if (saddr=...) accept; 要简洁得多。


场景四:记录日志与限速(log / limit / meter)

1. 记录日志(log)

有时你想记录所有被丢弃的数据包或特定攻击流量,用 log 动作即可。示例:

sudo nft add rule inet firewall input ip saddr 1.2.3.4 log prefix "BLOCKED_IP " drop
  • prefix "BLOCKED_IP ":出现在日志的前缀
  • 系统日志可在 journalctl -kdmesg/var/log/syslog 中查看(具体路径与发行版相关)。

2. 限速(limit)

如果不想每个数据包都写日志,比如要限制日志过于频繁,可以:

sudo nft add rule inet firewall input ip saddr 1.2.3.4 \
    limit rate 3/second \
    log prefix "BLOCKED_IP " \
    drop
  • limit rate 3/second:表示只有在这个速率以内的包才会触发日志动作,超出速率时跳过日志动作(但 drop 依然执行)。

3. 更高级的 meter / quota 等

nftables 支持更丰富的“状态计数”功能,如 meterquota 等,用来做连接数限制或带宽配额等更复杂的场景。例如:

sudo nft add rule inet firewall input meter ddos_meter {
    ip saddr limit rate 10/second
} log prefix "DOS_ATTEMPT " drop

meter 可以对特定字段(如 IP)进行自定义统计,超过阈值时执行特定动作等,适合抵御 DDOS 或限流。


场景五:仅允许特定网卡或特定连接状态(iif/oif/ct state)

1. 按网络接口名过滤

常见于服务器多网卡环境,如内网网卡 eth1、外网网卡 eth0,只允许某些流量从内网进来:

sudo nft add rule inet firewall input iifname "eth1" accept
sudo nft add rule inet firewall input iifname "eth0" drop

或者要反过来,拦截除了 eth0 外所有接口,就用:

sudo nft add rule inet firewall input iifname != "eth0" drop

2. 按连接状态 (ct state)

nftables 同样使用连接跟踪机制,可以区分数据包是 newestablishedrelatedinvalid 等。

# 只允许已建立或相关连接
sudo nft add rule inet firewall input ct state established,related accept

# 拒绝无效连接
sudo nft add rule inet firewall input ct state invalid drop

# 允许新建连接访问 80 端口
sudo nft add rule inet firewall input ct state new tcp dport 80 accept

场景六:桥接防火墙、VLAN 与 ingress 过滤(bridge / vlan / ingress)

1. 桥接 (bridge) family

如果你的 Linux 服务器做“二层交换/桥接”或者管理 VLAN,需要用到 bridge family 或 VLAN 相关匹配:

sudo nft add table bridge brtable
sudo nft add chain bridge brtable forward {
    type filter hook forward priority 0;
    policy drop;
}

# 例如 只允许从特定源MAC地址通过
sudo nft add rule bridge brtable forward ether saddr aa:bb:cc:dd:ee:ff accept

需要注意的是,在桥接场景下,你必须在 bridge family 下创建表/链,否则无法拦截二层包。此外,如果需要在桥上查看/过滤 IP 层的信息,通常还需要内核模块 br_netfilter 并启用 net.bridge.bridge-nf-call-iptables=1 等相关 sysctl。

2. VLAN 匹配

# 过滤 VLAN ID=100 的数据包
sudo nft add rule bridge brtable forward vlan id 100 drop

或者更细的匹配:vlan pcp 等等。

3. ingress hook(更早阶段过滤)

nftables 也支持 ingress hook(基于 TC ingress 机制),可以在数据包进入协议栈之前进行过滤,适合DDoS防护等需要尽早丢包的场景。例如:

sudo nft add chain inet firewall ingress {
    type filter hook ingress device eth0 priority -500;
    policy drop;
}
sudo nft add rule inet firewall ingress ip saddr 1.2.3.4 drop

ingress 上无法使用部分连接跟踪特性,请根据需求确认可行性。


场景七:IPv6 网络配置要点

若你在 IPv6 环境下部署防火墙,可以:

  1. 使用 inet family:同时管理 IPv4/IPv6

    • 规则里可以写 ip(仅针对 IPv4)或 ip6(仅针对 IPv6),或者直接用通用条件(如 tcp dport 80)同时生效。
  2. ICMPv6 规则非常重要

    • IPv6 依赖 ICMPv6 做邻居发现 (NDP) 等功能。若把 ICMPv6 全部阻断,可能导致网络中断。
    • 常见做法是明确放行 NDP:
      sudo nft add rule inet firewall input \
        icmpv6 type { nd-neighbor-solicit, nd-neighbor-advert, nd-router-advert } accept
      
  3. NAT in IPv6?

    • 原则上 IPv6 不推荐做 NAT。但技术上也可以配置 snat/dnat 之类,只是场景较少。
    • 如果确有需求,使用 ip6 nat family 并在 prerouting/postrouting 钩子上加 NAT 规则即可(写法与 IPv4 类似)。

其它必备命令:查看 / 修改 / 删除 / 清空规则

  1. 查看当前所有规则

    sudo nft list ruleset
    

    这会打印所有表、链和规则的完整结构。

  2. 查看指定表 / 链

    sudo nft list table inet firewall
    sudo nft list chain inet firewall input
    
  3. 查看规则的 handle ID

    sudo nft list chain inet firewall input -a
    

    -a 会显示每条规则的 handle 编号,便于定向删除或修改。

  4. 删除规则

    • 根据规则表达式删除:
      sudo nft delete rule inet firewall input ip saddr 1.2.3.4 drop
      
    • 或根据 handle ID 删除:
      # 先查看 handle
      sudo nft list chain inet firewall input -a
      # 假设要删 handle=10 的那条
      sudo nft delete rule inet firewall input handle 10
      
  5. 删除链 / 表

    • 必须先删除或清空该链内的规则,然后才能删链,再删除表:
      sudo nft delete chain inet firewall input
      sudo nft delete table inet firewall
      
  6. 清空/刷新整个规则集

    • 如果想一次性把所有链、表、规则都清除:
      sudo nft flush ruleset
      
    • 这是一个非常“暴力”的操作,执行后系统可能暂时没有任何防火墙规则,要谨慎使用。
  7. 实时监控 (monitor)

    sudo nft monitor
    

    可以动态观察规则的添加、删除、修改操作。

  8. 脚本批量加载

    • 可以把规则写到一个 .nft 文件中,然后通过 -f 参数一次性加载:
      sudo nft -f /path/to/your_rules.nft
      

附:从 iptables 迁移到 nftables 的注意事项

  1. 现代发行版默认使用 “nftables 后端”的 iptables

    • 执行 iptables -L 时,可能实际上调用的是 iptables-nft,会影响 nftables 规则集。
    • 最好尽量只使用 nftables,避免混合写两套规则导致冲突。
  2. 语法思维差异

    • iptables 中常用 -A-I-D 等,nftables 采用 nft add rule / nft insert rule / nft delete rule 的方式。
    • iptables 里 NAT、filter 是不同命令行,这些在 nftables 里都是同一个工具 nft,只是在创建链时指定 type nattype filter
  3. Docker / Container / Kubernetes 环境

    • 现代 Docker 默认也基于 nftables,或者使用一套 iptables-nft 规则;它会自动向系统规则集注入 NAT/forward 规则。
    • 手动编写 NAT 或 forward 规则时,要注意不要与 Docker 的规则冲突或相互覆盖。
    • 在 Kubernetes 环境下(如使用 kube-proxy iptables 模式),也需要留意 iptables-nft 后端的影响。
  4. 服务自启动 / 持久化

    • 如果以前在 /etc/iptables/rules.v4rules.v6 中写规则,那么在 nftables 下可以改为 /etc/nftables.conf
    • 大多数发行版可以通过 systemctl enable nftables + systemctl start nftables 来管理开机启动;或者编辑 /etc/default/nftables/etc/nftables.conf 等。
    • 常用做法:
      # 将当前规则输出到配置文件
      sudo nft list ruleset > /etc/nftables.conf
      # 确保开机加载
      sudo systemctl enable nftables
      
  5. flowtable(可选的高性能转发)

    • 如果你做网关且对性能要求很高,可了解 nftables 的 flow offload / flowtable 特性(Linux 4.18+),可将转发加速至内核 fast path 或硬件。
    • 典型示例(非常简化):
      nft add table inet xflow
      nft add chain inet xflow forward {
          type filter hook forward priority 0; policy accept;
      }
      nft add rule inet xflow forward ip protocol tcp \
          flow offload @DEV { eth0, eth1 } accept
      
    • 具体配置要根据内核版本、硬件环境来调整,非所有场景都适合。

参考资料与建议

  • 官方文档与 Wiki
  • man nft 手册
    • 终端输入 man nftnft --help
  • 调试思路
    • 使用 sudo nft list ruleset 确认最终规则
    • dmesgjournalctl -k 查看日志
    • 同时注意网络接口名、IP 地址是否正确;经常出现 NAT 链类型不匹配、priority 值冲突、IPv4/IPv6 混淆等问题
  • 发行版文档
    • 部分发行版可能对 nftables 做了额外封装(如 Debian/Ubuntu 的 nftables 服务、Red Hat 系的 nftables.conf 位置等),请查看对应发行版的官方指南。

总结

  1. nftables 的基本结构始终是:表(table) → 链(chain) → 规则(rule)
  2. 应用场景决定是做 过滤(type filter) 还是 NAT(type nat),以及要挂载到哪个 hook(如 inputpreroutingpostroutingingress 等)。
  3. 常见匹配包括源/目的 IP、端口、协议、接口名、连接状态 (ct state)、MAC 地址等;动作可为 accept, drop, reject, snat, dnat, masquerade, log 等。
  4. 高级用法set(批量黑白名单)、map(值→动作映射)、log(记录日志)、limit/meter(限速或计数)能够减少重复规则,提高可读性和性能。
  5. 注意发行版、内核版本、Docker/k8s 等环境差异,以免默认配置或自动生成的规则与手动写的规则冲突。也要关注持久化方式和服务启动脚本的配置。

通过以上 场景化 的例子与高级用法扩展,相信你能更准确地定位自己的需求,然后套用相应的链、规则写法来部署 nftables。祝一切顺利!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值