1. 项目概述为什么是 nftables如果你在 Linux 服务器上折腾过防火墙大概率绕不开iptables。它曾是 Linux 网络包过滤的绝对主力但它的架构在今天看来确实有些“年迈”了。复杂的规则链、IPv4 和 IPv6 需要两套工具iptables和ip6tables、性能瓶颈以及那让人又爱又恨的语法都催生了对新一代工具的渴望。nftables就是这个“继任者”。简单说nftables是 Linux 内核从 3.13 版本开始引入的新一代网络包过滤框架旨在取代iptables、ip6tables、arptables和ebtables这一大家子工具。它用一个统一的命令行工具nft和一套更简洁、更强大的语法解决了老框架的诸多痛点。内核社区也明确表示nftables是未来的方向iptables本身在用户空间也提供了向后兼容层iptables-nft但底层已经切换到了nftables框架。所以学习nftables不再是“要不要”的问题而是“什么时候”和“怎么学”的问题。无论你是运维工程师、开发人员还是任何需要管理 Linux 网络安全的用户掌握nftables都是一项越来越重要的技能。它能让你用更少的规则做更多的事管理起来也更清晰尤其是在面对复杂的云原生或容器网络环境时优势会更加明显。2. nftables 核心概念与架构解析要玩转nftables首先得理解它的几个核心概念。这就像搭积木知道了每一块是什么才能搭出稳固的房子。2.1 表、链、规则与集合这是nftables规则的四个基本层级从上到下层层递进。表这是最高级别的容器用于隔离不同用途的规则集。一个表与一个特定的“地址族”绑定。常见的地址族有ip处理 IPv4 数据包对应旧的iptables。ip6处理 IPv6 数据包对应旧的ip6tables。inet同时处理 IPv4 和 IPv6 数据包。这是最常用、最推荐的表类型因为它可以让你用一套规则同时管理两种协议。arp处理 ARP 层数据包。bridge处理桥接网络的数据包。netdev在数据包进入任何网络层协议栈之前进行处理通常用于入口流量整形或过滤。链链存在于表中是规则的容器。链定义了规则生效的“钩子点”和“策略”。钩子点决定了数据包在协议栈的哪个位置被处理例如input发往本机的数据包。output从本机发出的数据包。forward经过本机路由转发的数据包。prerouting数据包进入路由决策之前。postrouting数据包离开路由决策之后。 链的“策略”决定了当数据包不匹配链中任何规则时的默认行为可以是accept接受或drop丢弃。规则规则是具体的过滤或操作指令存放在链中。一条规则由两部分组成表达式用于匹配数据包的条件例如ip saddr 192.168.1.100、tcp dport 22、ct state new。语句定义对匹配数据包执行的操作例如accept、drop、log、counter计数、masquerade地址伪装。集合这是nftables的一大亮点。集合是一个命名的元素列表如 IP 地址、端口号可以在规则中被引用。它分为两种匿名集合在规则行内直接定义例如ip saddr { 10.0.0.1, 10.0.0.2 }。规则加载后这个集合就不可单独管理了。命名集合可以单独创建、修改和删除规则通过集合名称引用它。这对于管理大量动态变化的元素如黑名单 IP非常方便。2.2 nftables 相对于 iptables 的核心优势理解了架构我们再看看它具体好在哪里统一的语法和工具一套nft命令搞定所有协议IPv4/IPv6等学习成本降低管理更统一。更高效的规则处理nftables使用类似虚拟机的规则集解释器规则被编译成字节码后由内核执行效率更高。对于大型规则集其性能通常优于iptables。更简洁强大的语法支持类似编程语言的特性如变量、映射和级联动作。一条nft规则可以完成多条iptables规则才能实现的功能。原生支持集合和映射这是革命性的改进。你可以轻松创建 IP 地址、端口号的集合并动态更新它们而无需重载整个规则集。映射则可以实现类似“键值对”的查找匹配例如将源 IP 映射到不同的目标端口。更好的可读性和可维护性规则结构更清晰支持 JSON 格式导出/导入便于版本控制和自动化配置。注意虽然nftables是未来但当前很多发行版和云镜像可能默认仍使用iptables实际上是iptables-nft兼容层。在完全切换前务必确认你的应用和脚本是否兼容。3. 安装与基础环境准备在开始编写规则之前我们需要确保系统已经安装了nftables。3.1 检查内核支持与安装软件包首先确认你的内核支持nftables主流发行版近几年的版本都支持lsmod | grep nf_tables如果有输出说明内核模块已加载。也可以检查/proc/net/netfilter/nf_tables文件是否存在。接下来安装用户空间工具nft。不同发行版的命令如下Debian/Ubuntu:sudo apt update sudo apt install nftablesRHEL/CentOS/Rocky Linux/AlmaLinux 8:sudo dnf install nftablesFedora:sudo dnf install nftablesopenSUSE:sudo zypper install nftablesArch Linux:sudo pacman -S nftables安装完成后可以设置nftables服务开机自启并立即启动以 systemd 系统为例sudo systemctl enable nftables --now3.2 理解 nftables 的配置文件与持久化这是新手最容易踩坑的地方。nftables的规则默认是运行在内存中的重启后会丢失。为了让规则永久生效我们需要将它们保存到配置文件中。默认配置文件通常是/etc/nftables.conf。但请注意这个文件的具体位置和内容可能因发行版而异。有些发行版如某些版本的 Ubuntu在安装nftables包后会生成一个包含基础框架的配置文件。持久化流程使用nft命令行交互式地添加、测试规则。测试无误后将当前内存中的规则集导出到配置文件。配置nftables服务在启动时加载这个配置文件。关键命令sudo nft list ruleset查看当前内存中的所有规则。sudo nft -f /path/to/config-file从文件加载规则集会替换当前内存中的规则。sudo nft flush ruleset清空当前内存中的所有规则。标准持久化操作# 1. 将当前运行的规则导出到标准配置文件 sudo nft list ruleset /etc/nftables.conf # 2. 让 nftables 服务重启时加载这个配置 # 对于 systemd通常服务单元文件已经指向了 /etc/nftables.conf sudo systemctl restart nftables # 3. 验证规则是否已加载 sudo nft list ruleset实操心得我强烈建议在修改生产环境规则前先在一个测试文件如~/my-rules.nft中编写和测试。使用sudo nft -f ~/my-rules.nft加载测试确认无误后再导出到正式配置文件。这能避免因一条错误规则导致自己“被踢出”服务器的尴尬情况。4. nftables 语法精讲与实战规则编写现在进入最核心的部分如何用nft命令编写规则。我们将从最简单的例子开始逐步构建一个实用的防火墙配置。4.1 基础命令格式与常用操作nft命令的基本结构是nft [选项] 对象 命令 规则定义。对象table,chain,rule,set,map等。命令add,delete,list,flush等。常用操作示例# 1. 创建一个表地址族为 inet同时处理 IPv4/IPv6 sudo nft add table inet my_filter # 2. 在表中创建一条链 # 类型为 filter过滤钩子点为 input输入优先级为 0数字越小优先级越高默认策略为 drop丢弃 sudo nft add chain inet my_filter input_chain { type filter hook input priority 0 \; policy drop \; } # 3. 向链中添加一条规则 # 允许来自任何地址到本机 22 端口SSH的 TCP 新连接 sudo nft add rule inet my_filter input_chain tcp dport 22 ct state new accept # 4. 查看特定表的所有内容 sudo nft list table inet my_filter # 5. 删除一条规则需要指定规则句柄通过 list 命令查看 sudo nft list table inet my_filter -a # 查看规则句柄handle sudo nft delete rule inet my_filter input_chain handle 3 # 6. 清空一个链中的所有规则 sudo nft flush chain inet my_filter input_chain4.2 构建一个实用的基础防火墙规则集让我们编写一个完整的、适用于典型服务器的nftables.conf文件内容。我们将使用inet地址族一次性管理 IPv4 和 IPv6。#!/usr/sbin/nft -f # 这是一个完整的 nftables 配置文件示例 # 清空所有现有规则从头开始 flush ruleset table inet filter { # 定义集合受信任的 IPv4 地址用于 SSH 白名单 set trusted_ipv4 { type ipv4_addr elements { 192.168.1.100, 203.0.113.50 } } # 定义集合要开放的 TCP 端口 set tcp_accept_ports { type inet_service elements { 22, 80, 443 } } # 定义集合要开放的 UDP 端口如 DNS set udp_accept_ports { type inet_service elements { 53, 123 } } chain input { type filter hook input priority 0; policy drop; # 默认拒绝所有入站 # 1. 允许本地回环接口流量lo这是必须的 iifname lo accept # 2. 允许已建立的和相关的连接这是状态防火墙的核心极大简化规则 ct state established, related accept # 3. 允许 ICMP (ping) 和 ICMPv6网络诊断必需 ip protocol icmp accept ip6 nexthdr icmpv6 accept # 4. 从受信任 IP 集合来的 SSH 连接 tcp dport 22 ip saddr trusted_ipv4 accept # 5. 开放 TCP 端口集合中定义的端口如 Web 服务 tcp dport tcp_accept_ports accept # 6. 开放 UDP 端口集合中定义的端口 udp dport udp_accept_ports accept # 7. 记录并拒绝其他所有入站流量记录最后一条被拒绝的规则 log prefix nftables-input-denied: group 0 drop } chain forward { type filter hook forward priority 0; policy drop; # 默认不转发 # 如果这台机器是路由器或 Docker 主机需要在这里添加规则 # ct state established, related accept # iifname eth0 oifname eth1 accept 等 } chain output { type filter hook output priority 0; policy accept; # 默认允许所有出站 # 通常出站限制较少如果需要可以在这里添加规则 } }将这个配置保存到/etc/nftables.conf然后加载并测试sudo nft -f /etc/nftables.conf sudo nft list ruleset # 确认规则已加载 sudo systemctl restart nftables # 确保重启后生效4.3 高级特性命名集合与映射的动态管理命名集合的强大之处在于可以动态更新而无需重载整个规则集或中断现有连接。动态管理示例# 1. 首先在配置文件中定义一个空的、可动态更新的命名集合 # 在 table inet filter 中添加 set bad_guys { type ipv4_addr flags timeout # 支持超时元素 size 65535 # 集合最大容量 } # 2. 在 input 链中添加一条引用该集合的规则放在 accept 规则之后log/drop 之前 ip saddr bad_guys log prefix Bad IP detected: drop # 3. 重新加载配置文件后可以动态操作这个集合 # 添加一个 IP 到黑名单并设置 1 小时3600 秒后自动过期 sudo nft add element inet filter bad_guys { 10.10.10.5 timeout 1h } # 查看集合内容 sudo nft list set inet filter bad_guys # 从集合中删除一个 IP sudo nft delete element inet filter bad_guys { 10.10.10.5 } # 添加一个永久生效的 IP无超时 sudo nft add element inet filter bad_guys { 192.168.2.200 }映射的使用示例映射可以实现更复杂的策略。例如根据源 IP 决定目标端口。# 创建一个映射将源网络映射到允许的目标端口 map port_mapper { type ipv4_addr : inet_service elements { 192.168.10.0/24 : 8080, 10.0.0.0/8 : 22, } } # 在规则中使用映射 # 这条规则的意思是如果源IP在映射中则数据包的目标端口必须等于映射中对应的值才接受 tcp dport map port_mapper accept5. 从 iptables 迁移到 nftables对于已有iptables规则的用户迁移是必经之路。有两种主要方式5.1 使用 iptables-translate 工具半自动大多数发行版的iptables包现在提供iptables-translate和ip6tables-translate工具可以将iptables命令粗略地翻译成nftables命令。iptables-translate -A INPUT -p tcp --dport 80 -j ACCEPT # 输出nft add rule ip filter INPUT tcp dport 80 counter accept注意翻译工具并不完美特别是对于复杂的匹配扩展-m和目标扩展-j可能无法准确转换或需要手动调整。它主要提供一个起点和参考。5.2 手动重写与思维转换推荐我更推荐理解规则意图后用nftables的思维重新编写。关键思维转换如下-A INPUT- 在inet表的input链中添加规则。-p tcp --dport 80-tcp dport 80。-m state --state ESTABLISHED,RELATED-ct state established, relatednftables内置连接跟踪语法更简洁。-j ACCEPT/DROP/LOG-accept/drop/log。-s 192.168.1.0/24-ip saddr 192.168.1.0/24。多端口匹配-m multiport --dports 80,443-tcp dport { 80, 443 }使用匿名集合。迁移步骤建议备份sudo iptables-save iptables-backup.rules。分析仔细阅读备份文件理解每条规则的目的。设计新结构规划新的nftables表、链和集合。利用inet表统一 IPv4/IPv6。逐条转换在测试环境中使用新的nft语法重写规则。优先保证核心功能如 SSH、Web服务的规则正确。测试在新规则生效后全面测试网络服务的可访问性。切换确认无误后将新的nftables配置设置为默认并禁用旧的iptables服务sudo systemctl disable --now iptables注意不同发行版服务名可能不同。6. 常见问题排查与运维技巧即使规则写得再小心在实际运维中也会遇到各种问题。这里记录一些典型场景和排查命令。6.1 基础状态检查与规则调试# 1. 查看完整规则集最常用 sudo nft list ruleset # 2. 查看特定表 sudo nft list table inet filter # 3. 查看规则时显示计数器如果规则中使用了 counter 语句 sudo nft list ruleset -a # 输出会包含类似 counter packets 12345 bytes 987654321 的信息用于流量分析。 # 4. 实时监控规则命中情况动态追踪 sudo nft monitor trace # 这个命令非常强大它会显示每个数据包匹配了哪条规则以及最终的处理结果。 # 在另一个终端尝试访问被拒绝的服务这里会打印出详细的匹配过程。6.2 典型问题速查表问题现象可能原因排查命令与解决思路规则加载失败语法错误sudo nft -c -f /etc/nftables.conf-c选项只检查语法不加载服务无法访问如 SSH规则顺序错误默认策略阻止1.sudo nft list chain inet filter input查看 input 链规则顺序。2. 确保允许规则在policy drop之前且ct state established, related accept规则存在并靠前。自己锁死服务器错误的规则阻断了所有流量包括当前 SSH 会话重要在配置防火墙时务必通过本地控制台或带外管理如云平台的 VNC操作或者设置一个定时回滚的cron任务。规则不生效1. 表/链地址族错误如用ip表处理 IPv6。2. 钩子点hook选择错误。1. 确认数据包协议IPv4/IPv6。2. 使用nft monitor trace跟踪数据包路径看它经过了哪些链。性能问题规则数量过多或顺序不合理1. 将最频繁匹配的规则如established,related放在最前面。2. 使用集合和映射来合并多条规则。3. 避免在频繁匹配的链中使用log语句。6.3 运维实用技巧规则注释在配置文件中可以使用#添加注释。在命令行中添加规则时可以使用comment语句附加注释便于日后维护。sudo nft add rule inet filter input tcp dport 22 accept comment \Allow SSH from anywhere (temporary)\ sudo nft list ruleset | grep -A2 -B2 comment # 查看带注释的规则规则优化nftables规则是按顺序匹配的。将匹配概率最高的规则放在链的前面可以显著提升性能。例如ct state established, related accept这条规则应该放在很靠前的位置因为它会匹配当前所有活跃连接的数据包避免了后续规则的无谓匹配。与 Docker/容器兼容Docker 默认会操作iptables。如果你同时使用nftables可能会产生冲突。建议的解决方案是在 Docker 的配置文件中/etc/docker/daemon.json设置iptables: false并让 Docker 使用nftables后端较新版本支持或者完全由你自己的nftables规则来管理容器网络流量这需要更精细的链和规则设计。配置文件管理将你的nftables.conf纳入版本控制系统如 Git。每次修改前做备份修改后充分测试。可以使用sudo nft -c -f new_rules.nft sudo nft -f new_rules.nft这样的组合命令来先检查后加载。从iptables迁移到nftables初期可能会觉得有些陌生但一旦熟悉了其简洁统一的语法和强大的集合功能你就会发现管理和维护防火墙规则变成了一件更清晰、更高效的事情。关键在于动手实践从一个简单的配置文件开始逐步添加复杂规则并善用nft monitor trace这个利器来观察和理解数据包的流动。