本文目录导读:

nftables 是 Linux 内核自 3.13 版本起引入的新一代防火墙框架,旨在替代传统的 iptables(以及 ip6tables、ebtables 等),它提供了更简洁的语法、更好的性能(规则集原子性替换)以及更清晰的架构。
以下是关于 nftables 管理 Linux 防火墙 的完整指南,从基础概念到常用操作。
核心架构概念
与 iptables(有多个表和固定链,不可扩展)不同,nftables 的核心是表 (Tables)、链 (Chains) 和规则 (Rules)。
- 表 (Table):规则集的最高层级容器,每个表通常对应一个地址族 (Address Family)。
ip:IPv4 协议(默认)ip6:IPv6 协议inet:同时适用于 IPv4 和 IPv6 的混合表(强烈推荐,能减少一半规则)arp:ARP 协议bridge:网桥(二层)过滤netdev:处理入口路径上的数据包(基于网卡,非常底层)
- 链 (Chain):规则的集合,有两种类型:
- 基础链 (Base Chain):直接挂载在协议栈钩子点(如
prerouting、input、forward、output、postrouting),需要指定钩子 (hook)、优先级 (priority) 和策略 (policy)(accept 或 drop)。 - 普通链 (Regular Chain):作为跳转目标,用于规则分组和复用(类似函数调用)。
- 基础链 (Base Chain):直接挂载在协议栈钩子点(如
- 规则 (Rule):匹配条件 + 动作(裁决),格式:
匹配表达式 动作表达式。 - 集 (Sets):nftables 最强大的功能之一,可以存储 IP 地址、端口、网卡等元素的列表或区间,供规则引用,支持匿名集(直接写在规则中)和命名集(可动态更新,性能极高)。
环境准备:安装与启用
大多数现代 Linux 发行版(CentOS 8+、RHEL 8+、Fedora、Ubuntu 20.04+、Debian 11+)已默认安装或可通过包管理器安装。
# 查看是否安装 nft --version # 如果未安装(以 Debian/Ubuntu 为例) sudo apt update && sudo apt install nftables # 以 RHEL/CentOS/Fedora 为例 sudo dnf install nftables
启动并设置开机自启(强烈建议先关掉旧的 iptables 避免冲突):
# 1. 停止并屏蔽旧的 iptables/ip6tables/ebtables 服务(如果有) sudo systemctl stop iptables ip6tables ebtables sudo systemctl disable iptables ip6tables ebtables # 2. 启用 nftables sudo systemctl enable nftables --now # 3. 检查状态 sudo systemctl status nftables
基础操作:nft 命令行
所有管理都通过 nft 命令完成,可以是交互式(nft -i)或单次命令。
1 查看当前规则
# 列出所有规则集(包括所有表、链、规则) sudo nft list ruleset # 只列出特定地址族和表 sudo nft list table inet filter # 格式化输出(便于阅读) sudo nft list ruleset | less
2 创建表
# 创建一个 inet 类型的表,名为 "filter"(最常用) sudo nft add table inet filter # 也可以创建 IPv4 专用表 sudo nft add table ip mytable
3 创建基础链(Base Chain)
# 在 inet filter 表中创建 input 链
sudo nft add chain inet filter input {
type filter hook input priority 0
policy drop # 关键点:设置默认策略(accept 或 drop)
}
# 创建 forward 和 output 链(default policy accept)
sudo nft add chain inet filter forward { type filter hook forward priority 0 \; policy accept \; }
sudo nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
hook:prerouting|input|forward|output|postrouting|ingress(netdev)priority:数字或名称(如raw=300,mangle=150,filter=0,nat=-100),数字越小优先级越高,越早处理。policy:accept(如果未匹配任何规则则允许)或drop(如果未匹配则丢弃)。对于input链,建议设为drop并显式放行需要的流量。
4 添加规则
规则按照顺序匹配,一旦匹配则执行动作(accept, drop, jump, continue, return 等)。
# 1. 允许本地回环接口 (lo 接口)
sudo nft add rule inet filter input iif lo accept
# 2. 允许与现有连接相关的回包(状态防火墙)
sudo nft add rule inet filter input ct state established,related accept
# 3. 允许 SSH (端口 22) 入站
sudo nft add rule inet filter input tcp dport 22 accept
# 4. 允许 HTTP/HTTPS (80, 443)
sudo nft add rule inet filter input tcp dport { 80, 443 } accept
# 5. 允许 ICMP (ping)
sudo nft add rule inet filter input ip protocol icmp accept
# 6. 拒绝所有其他 SSH 尝试(记录日志并拒绝)
sudo nft add rule inet filter input tcp dport 22 reject with tcp reset
# 7. 允许从特定 IP 访问 (源地址过滤)
sudo nft add rule inet filter input ip saddr 192.168.1.100 tcp dport 3306 accept
# 8. 允许来自特定网段的流量
sudo nft add rule inet filter input ip saddr 10.0.0.0/8 accept
# 9. 限制连接速率(防止端口扫描)
sudo nft add rule inet filter input tcp dport 2222 limit rate 10/minute accept
核武器:集 (Sets)
集是 nftables 的核心优势,大幅简化并加速复杂规则。
1 匿名集 (Anonymous Set)
直接在规则中用花括号 定义,适用于少量元素。
# 允许从 192.168.1.1, 192.168.1.2, 172.16.0.1 访问 SSH
sudo nft add rule inet filter input \
ip saddr { 192.168.1.1, 192.168.1.2, 172.16.0.1 } tcp dport 22 accept
2 命名集 (Named Set) —— 动态管理利器
命名集可以独立于规则被更新(添加/删除元素),无需重新加载整个规则集,非常适合动态 IP 黑/白名单。
# 1. 创建一个命名为 "whitelist" 的 IPv4 地址集
sudo nft add set inet filter whitelist {
type ipv4_addr
flags interval # 可选:支持子网 /24
elements = { 192.168.1.0/24, 10.10.10.5 }
}
# 2. 创建一个名为 "blacklist" 的 IPv4 地址集
sudo nft add set inet filter blacklist {
type ipv4_addr
}
# 3. 在规则中引用命名集
sudo nft add rule inet filter input ip saddr @whitelist accept # 白名单直接接受
sudo nft add rule inet filter input ip saddr @blacklist drop # 黑名单直接丢弃
sudo nft add rule inet filter input tcp dport 80 ip saddr @whitelist accept # 更精细的匹配
# 4. 动态管理命名集(添加/删除元素,无需重启 nft)
sudo nft add element inet filter whitelist { 172.16.0.10 }
sudo nft delete element inet filter blacklist { 10.0.0.1 }
# 5. 查看命名集内容
sudo nft list set inet filter whitelist
集合类型优点:使用 @set 引用集合比写多条独立规则性能高得多(哈希查找),且维护方便。
保存与加载规则
规则默认不持久化在配置文件中,你需要手动保存。
1 方法一:使用 nftables 服务(推荐)
nftables 默认读取 /etc/nftables.conf。
# 1. 将当前运行中的规则集导出到文件 sudo nft list ruleset > /etc/nftables.conf # 2. 或者通过 systemd 保存(自动调用 nft list ruleset > 某个位置) sudo systemctl restart nftables # 重启后会自动读取配置 # 但注意:直接 systemctl restart nftables 会清空运行中的规则,然后读取 /etc/nftables.conf # 所以最佳实践是:修改配置 -> 保存 -> 激活 sudo nft -f /path/to/your_rules.conf # 加载一个规则文件
2 方法二:使用 nft -f 加载文件
创建一个规则文件,~/my_rules.nft。
#!/usr/sbin/nft -f
# 清空整个规则集
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
ct state established,related accept
ip saddr @whitelist accept
tcp dport ssh accept
# ... 其他规则
}
chain forward {
type filter hook forward priority 0; policy drop;
# ...
}
chain output {
type filter hook output priority 0; policy accept;
}
set whitelist {
type ipv4_addr
elements = { 192.168.1.0/24, ... }
}
}
然后执行:
sudo nft -f ~/my_rules.nft
注意:flush ruleset 会清空所有现有规则,务必小心。
实用场景示例
1 标准 Linux 桌面防火墙(允许本地、已建立连接、SSH、Web)
sudo nft add table inet filter
sudo nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
sudo nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }
sudo nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
sudo nft add rule inet filter input iif lo accept
sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter input tcp dport { 22, 80, 443 } accept
sudo nft add rule inet filter input icmp type echo-request accept
2 简单的 NAT(网络地址转换)
# 创建一个 NAT 表
sudo nft add table ip nat
# 创建源 NAT 链 (postrouting)
sudo nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
# 添加 MASQUERADE(伪装):适用于动态 IP 的上网共享
sudo nft add rule ip nat postrouting oif eth0 masquerade
# 创建目的 NAT 链 (prerouting),并添加端口转发(将 2222 转发到内网 192.168.1.10 的 22 端口)
sudo nft add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
sudo nft add rule ip nat prerouting tcp dport 2222 dnat to 192.168.1.10:22
常见问题与排错
1 规则覆盖或顺序错误
- 检查规则顺序:
nft list ruleset查看执行顺序。 input链策略是drop,一定要有established,related放行规则放在前面。
2 锁死自己(SSH 被断)
绝对不要在不安全的 SSH 会话中设置 input policy drop 而不先添加 SSH 放行规则!
急救方法:
- 使用备用控制台(物理机或 IPMI)。
- 重启网络服务:
sudo systemctl restart networking(可能清空规则,取决于配置)。 - 直接清空规则:
sudo nft flush ruleset(会立即清空所有防火墙规则,谨慎使用,会暴露系统但恢复连接)。 - 使用 cron 或 at 定时任务:设置一个定时脚本在几分钟后恢复默认规则(如开机启动时)作为安全网。
3 日志记录
- 使用
log动作:sudo nft add rule inet filter input tcp dport 22 log prefix "SSH-ATTEMPT: " reject
- 日志通常会发往系统日志(
/var/log/syslog或journalctl)。
4 性能监控
-
使用
nft monitor实时查看被匹配的规则(调试用,生产慎用)。 -
查看计数器(
counter动作):sudo nft add rule inet filter input tcp dport 80 counter accept sudo nft list ruleset # 会显示匹配到的包和字节数
nftables vs iptables
| 特性 | nftables | iptables |
|---|---|---|
| 语法 | 规则为表达式(ip saddr 1.2.3.4 tcp dport 80 accept) |
命令式(iptables -A INPUT -s 1.2.3.4 -p tcp --dport 80 -j ACCEPT) |
| 内核架构 | 单一框架,规则集一次性原子替换 | 多个内核模块(ipt, ip6t, ebt, arpt)、不同表不同后端 |
| 集(Sets) | 原生、一流支持,高性能 | 需要 ipset 工具,两层管理 |
| 规则数量 | 单个表支持 inet 混合处理 IPv4/IPv6,规则数量减半 |
IPv4 和 IPv6 需要两套规则集 |
| 动态更新 | 支持原子性更新(添加/删除规则不会中断流量) | 重新加载规则集有短暂中断窗口(除非用 iptables-restore) |
| 兼容性 | 原生,推荐新系统使用 | 旧系统标准,通过 iptables-translate 可转换 |
对于 Linux 防火墙管理,强烈推荐使用 nftables,它在性能、可维护性、语法清晰度上都明显优于 iptables,一旦熟悉其基于表/链/集的词汇表和表达式语法,你会觉得比 iptables 更加直观和强大,从 iptables 迁移(通过 iptables-translate)也很容易。
标签: Linux防火墙