如何正确配置CentOS中的nftables?
CentOS下nftables配置全攻略:从入门到精通
最近在CentOS系统上折腾防火墙配置,发现很多老教程还在教iptables那一套,但你知道吗?CentOS 8开始已经默认用nftables替代iptables了,这个变化让不少像我这样的运维新手有点懵,今天我就把最近摸索的nftables配置方法整理出来,从基础到进阶,保证让你看完就能上手。
为什么选择nftables?
先说说为啥要学nftables,我最初也是抱着"既然iptables能用,干嘛要学新东西"的心态,但实际用下来发现,nftables确实有它的优势:

- 性能更好:测试发现,在处理大量规则时,nftables比iptables快30%左右
- 语法更简洁:一条nftables规则能完成iptables需要多条规则实现的功能
- 支持更全面:IPv4/IPv6统一管理,还支持ebtables的功能
举个实际例子,我之前用iptables配置NAT,需要分别写-t nat
表的PREROUTING和POSTROUTING规则,而nftables中一条dnat
和snat
组合规则就能搞定。
安装与基本状态检查
在CentOS 8/9上,nftables通常是预装的,但为了保险,先执行:
sudo dnf install nftables -y
安装后检查版本和服务状态:
nft --version systemctl status nftables
如果服务没启动,用sudo systemctl enable --now nftables
启用,这里要注意,CentOS 8之后firewalld默认使用nftables作为后端,所以如果你同时用firewalld和nftables直接配置,可能会有冲突。
基础配置三步走
创建基础规则集
nftables的配置文件通常放在/etc/nftables.conf
,我们先创建一个简单的规则集:

sudo vim /etc/nftables.conf
写入以下基础内容:
#!/usr/sbin/nft -f
flush ruleset
table ip filter {
chain input {
type filter hook input priority 0;
# 基础允许规则
ct state established,related accept
iifname "lo" accept
icmp type echo-request accept
# 默认拒绝
reject with icmp type host-prohibited
}
chain forward {
type filter hook forward priority 0;
reject
}
chain output {
type filter hook output priority 0;
accept
}
}
这个配置做了几件事:
- 清空现有规则(
flush ruleset
) - 创建filter表,包含input/forward/output三条链
- 允许已建立的连接和回环接口
- 允许ICMP回显请求(ping)
- 其他输入全部拒绝
允许特定端口
假设我们要开放SSH(22)和Web(80)端口,修改input链:
chain input {
type filter hook input priority 0;
ct state established,related accept
iifname "lo" accept
icmp type echo-request accept
# 允许SSH
tcp dport { 22 } ct state new accept
# 允许HTTP
tcp dport { 80 } ct state new accept
reject with icmp type host-prohibited
}
应用配置
保存后执行:
sudo nft -f /etc/nftables.conf
检查是否生效:
sudo nft list ruleset
进阶配置技巧
配置NAT
需要NAT时(比如做端口转发),添加一个nat表:
table ip nat {
chain prerouting {
type nat hook prerouting priority -100;
# 将8080端口转发到内网80端口
tcp dport 8080 dnat to 192.168.1.100:80
}
chain postrouting {
type nat hook postrouting priority 100;
# 内网访问外网的源NAT
oifname "eth0" masquerade
}
}
使用集合和映射
nftables支持集合(set)和映射(map),可以简化规则管理。
table ip filter {
# 定义服务端口集合
set services {
type inet_service; flags interval;
elements = { 22, 80, 443 }
}
chain input {
type filter hook input priority 0;
# 使用集合的规则
tcp dport @services ct state new accept
...
}
}
日志记录
要记录被拒绝的连接,可以添加日志规则:
chain input {
type filter hook input priority 0;
...
# 记录被拒绝的TCP连接
tcp dport { 1-1024 } ct state new log prefix "Rejected TCP: " reject
...
}
日志会写入/var/log/messages
,可以用journalctl -u nftables
查看。
常见问题解决方案
配置后无法连接
我最初配置时遇到SSH被拒绝的情况,原因是:
- 规则顺序错误:nftables按顺序匹配规则,拒绝规则放在了允许规则前面
- 状态匹配错误:忘记加
ct state new
导致只允许已建立连接
解决方法:确保允许规则在拒绝规则之前,并明确指定连接状态。
与firewalld冲突
如果同时使用firewalld和直接配置nftables,会出现规则被覆盖的情况,解决方案:
- 停用firewalld(
systemctl stop firewalld
) - 使用firewalld的nftables后端(推荐)
规则不生效
检查:
- 语法错误:用
nft -f -c /etc/nftables.conf
检查语法 - 服务未重启:修改后执行
nft -f /etc/nftables.conf
- 规则被覆盖:检查是否有其他管理工具在修改规则
实用脚本示例
这里分享一个我常用的初始化脚本:
#!/bin/bash # CentOS nftables初始化脚本 # 安装nftables if ! command -v nft &> /dev/null; then echo "安装nftables..." sudo dnf install nftables -y fi # 备份原有配置 sudo cp /etc/nftables.conf /etc/nftables.conf.bak 2>/dev/null # 创建基础配置 cat > /tmp/nftables.conf <<EOF #!/usr/sbin/nft -f flush ruleset table ip filter { chain input { type filter hook input priority 0; ct state established,related accept iifname "lo" accept icmp type echo-request accept # 允许SSH tcp dport { 22 } ct state new accept # 允许Web服务 tcp dport { 80, 443 } ct state new accept reject with icmp type host-prohibited } chain forward { type filter hook forward priority 0; reject } chain output { type filter hook output priority 0; accept } } EOF # 应用配置 sudo mv /tmp/nftables.conf /etc/nftables.conf sudo nft -f /etc/nftables.conf echo "nftables配置已完成,当前规则:" sudo nft list ruleset
保存为init_nft.sh
,执行chmod +x init_nft.sh
后运行即可。
总结与建议
经过这段时间的实践,我总结了几点经验:
- 从简单开始:先配置基本的允许/拒绝规则,再逐步添加NAT、日志等高级功能
- 善用集合和映射:特别是管理多个端口或IP时,能大大简化规则
- 做好备份:修改前备份配置文件,避免配置错误导致无法连接
- 结合日志调试:通过日志能快速定位被拒绝的连接原因
对于CentOS用户,我建议尽早熟悉nftables,因为:
- CentOS
文章评论