认识 nftables:Linux 防火墙、转发与 NAT 实践
在 Linux 服务器上配置防火墙、双网卡转发、端口映射或共享网络时,经常会看到 nft 命令。nft 并不是一款独立于内核的网络工具,而是 nftables 的用户态管理程序。它负责把管理员编写的规则提交给 Linux 内核,由内核在数据包经过网络协议栈时执行这些规则。
本文从 nftables 的基本原理讲起,并结合有线网卡 eno1 和无线网卡 wlp34s0 的互通场景,介绍过滤、路由转发、连接跟踪和 NAT 的实际用法。
一、nft、nftables 与 Netfilter 是什么关系
这三个名称经常同时出现,但它们指向不同层次。
Netfilter 是 Linux 内核中的网络包处理框架。数据包进入、离开或穿过主机时,Netfilter 会在若干关键位置提供处理入口。防火墙、NAT、端口转发等功能都建立在这些入口上。
nftables 是建立在 Netfilter 之上的现代规则系统。它定义了表、链、规则、集合等结构,用来描述哪些流量允许通过、哪些流量拒绝、哪些地址需要转换。
nft 是 nftables 的命令行客户端。管理员通过 nft 查看、添加、删除和批量加载规则。例如:
sudo nft list ruleset
这条命令读取当前内核中的完整 nftables 规则集。
可以将三者简单理解为:Netfilter 是内核执行框架,nftables 是规则体系,nft 是操作这套体系的命令行工具。
二、为什么逐步从 iptables 转向 nftables
iptables 曾长期作为 Linux 防火墙的主要工具,但 IPv4、IPv6、二层过滤和地址转换分别使用 iptables、ip6tables、ebtables、arptables 等命令,规则体系较为分散。
nftables 对这些能力进行了统一,主要优势包括:
- IPv4 和 IPv6 可以使用同一套
inet规则。 - 支持集合、映射和区间,处理大量地址或端口时更高效。
- 规则语法更一致,减少重复配置。
- 支持原子化加载规则文件,避免批量修改时出现短暂的中间状态。
- 计数器、日志、连接状态和 NAT 可以在同一规则体系中表达。
- 相同规则通常比传统 iptables 规则更简洁。
需要注意,部分系统中的 iptables 命令实际上使用的是 iptables-nft 后端,最终仍会转换为 nftables 规则。因此,同一台机器上可能同时看到 Docker、firewalld、iptables 和手工 nft 规则。修改前应先查看完整规则集,避免规则之间相互覆盖。
三、数据包经过主机时发生了什么
理解 nftables 的关键,不是背命令,而是判断数据包走哪条路径。
1. 访问本机
外部设备访问本机 SSH、Web 服务或数据库时,流量大致经过:
网卡接��� -> prerouting -> 路由判断 -> input -> 本机进程
控制这类流量通常使用 input 链。
2. 本机主动访问外部
本机进程访问互联网或局域网设备时,流量大致经过:
本机进程 -> output -> 路由判断 -> postrouting -> 网卡发送
控制这类流量通常使用 output 链。
3. 从一块网卡转发到另一块网卡
当主机承担路由器角色时,数据包并不交给本机应用,而是从一块网卡进入,再从另一块网卡离开:
eno1 -> prerouting -> 路由判断 -> forward -> postrouting -> wlp34s0
这类流量必须满足两个条件:
- 内核启用了 IP 转发。
forward链允许该数据包通过。
仅仅配置两块网卡的 IP 地址,不代表它们后面的设备就能互访。
四、nftables 的核心结构
nftables 规则由表、链和规则逐层组成。
1. Table:表
表是规则的顶层容器,同时指定协议族。常用协议族包括:
| 协议族 | 用途 |
|---|---|
ip | 仅处理 IPv4 |
ip6 | 仅处理 IPv6 |
inet | 同时处理 IPv4 和 IPv6 |
bridge | 处理 Linux 网桥中的二层流量 |
arp | 处理 ARP |
netdev | 在网卡入口处较早处理数据包 |
一般防火墙优先使用 inet 表;只针对 IPv4 的 NAT 可以使用 ip 表。
创建一张表:
sudo nft add table inet platform_filter
platform_filter 是自定义名称,不是系统固定名称。
2. Chain:链
链用来组织规则。普通链只是规则容器;基础链通过 hook 挂接到内核的数据包处理路径。
例如创建一个转发基础链:
sudo nft 'add chain inet platform_filter forward {
type filter hook forward priority 0;
policy drop;
}'
其中:
type filter表示用于过滤流量。hook forward表示处理经过本机转发的数据包。priority 0表示执行优先级。policy drop表示没有匹配任何放行规则时默认丢弃。
常见 Hook 包括 prerouting、input、forward、output 和 postrouting。
3. Rule:规则
规则由“匹配条件”和“动作”构成:
sudo nft add rule inet platform_filter forward \
iifname "eno1" oifname "wlp34s0" accept
这条规则表示:从 eno1 进入并准备从 wlp34s0 离开的流量允许通过。
常见动作包括:
accept:允许。drop:静默丢弃。reject:拒绝并向对端返回错误。log:记录日志。counter:统计数据包数和字节数。dnat:修改目标地址,常用于端口转发。snat或masquerade:修改源地址,常用于共享上网。
4. Set:集合
当规则涉及多个 IP 或端口时,可以使用集合,避免重复编写规则:
set management_hosts {
type ipv4_addr
elements = { 192.168.2.10, 192.168.2.11, 192.168.2.20 }
}
规则可以直接判断源地址是否属于集合:
ip saddr @management_hosts tcp dport 22 accept
集合是 nftables 相比传统规则体系更实用的能力之一。
五、状态防火墙与连接跟踪
nftables 可以使用 Netfilter 的连接跟踪系统判断数据包属于新连接,还是已有连接的后续数据包。
典型规则如下:
ct state established,related accept
常见状态包括:
new:正在建立新连接。established:属于已经建立的连接。related:与已有连接相关,例如部分协议产生的附属连接。invalid:无法被正常识别或状态异常。
假设只允许 eno1 侧主动访问 Wi-Fi 网络,可以这样设计:
iifname "eno1" oifname "wlp34s0" accept
iifname "wlp34s0" oifname "eno1" ct state established,related accept
第一条允许请求从 eno1 发出,第二条只允许这���连接的响应返回。Wi-Fi 侧不能随意新建连接访问 eno1 侧设备。
六、路由转发与 NAT 不是一回事
这两个概念经常混淆。
1. 纯路由转发
纯路由模式不会改变源地址。例如 192.168.2.100 访问 172.16.15.50 时,对端看到的源地址仍然是 192.168.2.100。
优点是网络关系清晰,双方可以双向通信。前提是 Wi-Fi 网段的路由器知道返回路径,例如在 172.16.15.1 上添加:
目标网段:192.168.2.0/24
下一跳:172.16.15.135
2. NAT 转发
如果无法修改上级路由器,可以使用源 NAT。192.168.2.100 发出的流量在离开 wlp34s0 时被改写为 172.16.15.135,返回流量再由本机恢复原地址。
ip saddr 192.168.2.0/24 oifname "wlp34s0" masquerade
masquerade 适用于出口地址可能变化的场景,例如 DHCP 获取地址的 Wi-Fi 网卡。
NAT 解决了返回路由问题,但通常只能由 eno1 侧主动发起连接。若要求 Wi-Fi 侧主动访问内网设备,需要配置静态路由,或者针对具体服务设置 DNAT 端口转发。
七、双网卡互通实例
假设主机网络为:
eno1:192.168.2.68/24
wlp34s0:172.16.15.135/24
Wi-Fi 网关:172.16.15.1
目标是允许 eno1 后方的设备通过 Wi-Fi 网络访问其他设备。
1. 配置 eno1 侧设备
例如:
IP 地址:192.168.2.100
子网掩码:255.255.255.0
默认网关:192.168.2.68
DNS:172.16.15.1
默认网关必须指向 Linux 主机的 eno1 地址,否则数据包不会交给该主机转发。
2. 开启内核转发
临时开启:
sudo sysctl -w net.ipv4.ip_forward=1
持久配置:
echo 'net.ipv4.ip_forward=1' | \
sudo tee /etc/sysctl.d/90-network-forward.conf
sudo sysctl --system
3. 配置过滤和 NAT
下面的规则允许 eno1 侧主动访问 Wi-Fi 网络,并允许响应流量返回:
table inet eno1_wifi_filter {
chain forward {
type filter hook forward priority filter;
policy drop;
ct state invalid drop
ct state established,related accept
iifname "eno1" oifname "wlp34s0" \
ip saddr 192.168.2.0/24 counter accept
}
}
table ip eno1_wifi_nat {
chain postrouting {
type nat hook postrouting priority srcnat;
policy accept;
ip saddr 192.168.2.0/24 oifname "wlp34s0" \
counter masquerade
}
}
可以将内容保存到单独文件,先检查语法:
sudo nft --check --file eno1-wifi.nft
确认无误后加载:
sudo nft --file eno1-wifi.nft
4. 验证链路
先查看地址和路由:
ip -br address
ip route
查看转发状态:
sysctl net.ipv4.ip_forward
查看规则和计数器:
sudo nft list ruleset
从 eno1 侧设备依次测试:
ping 192.168.2.68
ping 172.16.15.135
ping 172.16.15.1
ping 8.8.8.8
如果前两步成功、后两步失败,通常应检查转发规则和 NAT;如果 IP 地址能访问但域名不能访问,则重点检查 DNS。
八、常用 nft 命令
查看完整规则:
sudo nft list ruleset
查看指定表:
sudo nft list table inet eno1_wifi_filter
以带句柄的形式查看链:
sudo nft --handle list chain inet eno1_wifi_filter forward
删除指定规则:
sudo nft delete rule inet eno1_wifi_filter forward handle 12
检查规则文件但不加载:
sudo nft --check --file /etc/nftables.conf
加载规则文件:
sudo nft --file /etc/nftables.conf
监视规则集变化:
sudo nft monitor
清空所有 nftables 规则:
sudo nft flush ruleset
最后一条命令风险很高。远程服务器上执行后,可能破坏 SSH 放行规则、Docker 网络、端口映射和系统防火墙配置,不应作为日常清理手段。
九、规则如何持久化
直接通过 nft add rule 添加的规则保存在内核内存中,重启后通常消失。使用原生 nftables 服务的系统可以把规则保存到:
/etc/nftables.conf
然后启用服务:
sudo systemctl enable --now nftables
但在保存前,应先确认系统是否由 firewalld、ufw 或 NetworkManager 管理防火墙:
systemctl is-active firewalld
systemctl is-active nftables
sudo ufw status
如果 firewalld 正在运行,优先通过 firewalld 配置区域、转发和 masquerade;如果 ufw 正在运行,应使用 ufw 的规则体系。多个管理器同时接管相同 Hook,容易产生难以判断的优先级和覆盖关系。
Docker 也会创建转发和 NAT 规则。不要为了加载自己的配置而直接执行 flush ruleset,否则可能导致容器网络中断。
十、常见故障排查
1. 本机能访问两个网段,网卡后的设备不能访问
重点检查:
sysctl net.ipv4.ip_forward
sudo nft list ruleset
本机访问属于 input 或 output 路径,网卡后的设备跨网段访问属于 forward 路径,两者不是同一种流量。
2. 请求可以发出,但没有响应
通常是返回路由缺失。可在上级路由器添加静态路由,或在出口使用 masquerade。
3. 规则存在但计数器始终为零
说明流量没有命中该规则。检查接口名、源网段、目标网段和路由选择:
ip route get 172.16.15.50 from 192.168.2.100
还可以抓包确认数据是否进入和离开主机:
sudo tcpdump -ni eno1
sudo tcpdump -ni wlp34s0
4. Wi-Fi 侧无法主动访问有线侧
NAT 默认不能替代反向路由。应在 Wi-Fi 路由器上添加到 192.168.2.0/24 的静态路由,并放行双向 forward。另外还要检查无线接入点是否启用了客户端隔离。
5. 加载规则后 SSH 中断
这通常是 input 链采用 policy drop,却没有提前允许已建立连接和 SSH 端口。远程修改防火墙时应保留一个本地终端,并设置自动回滚任务,确认连接正常后再取消回滚。
十一、使用 nftables 的基本原则
- 先画清楚数据包路径,再决定修改
input、forward还是 NAT。 - 默认拒绝时,先放行
established,related,再逐项开放业务流量。 - 使用独立表名管理自定义规则,避免直接修改 Docker 或系统防火墙生成的表。
- 批量变更优先使用规则文件,并通过
nft --check检查语法。 - 为关键规则添加
counter,让排查有明确依据。 - 能配置静态路由时优先使用路由;无法控制上级网络时再使用 NAT。
- 远程服务器不要随意执行
flush ruleset,任何默认拒绝策略都应准备回滚方案。
结语
nftables 的本质,是在 Linux 数据包经过内核网络栈的关键位置执行匹配和处理。它既能构建主机防火墙,也能让一台普通 Linux 设备承担路由器、NAT 网关和端口转发器的角色。
掌握 nftables 时,最重要的是理解三个问题:数据包从哪里进入、准备从哪里离开、对端是否知道返回路径。明确这三个问题后,表、链和规则只是对网络设计的具体表达。
许可协议:CC BY-NC 4.0
更新于 1 小时前
觉得文章有帮助?点个赞吧!
0 条评论


