开篇:为什么需要NAT?
想象你家有10台设备要上网,但宽带运营商只给了1个公网IP——这就像10个人要共用1张身份证出门,NAT技术就是那个“身份证代办处”,通过巧妙的地址转换让多设备共享网络。其中SNAT和DNAT是最核心的两种“转换魔法”。
firewalld作为主流Linux系统的防火墙工具,其配置方式随版本迭代有重要变化:旧版firewalld依赖Direct接口配置NAT,新版已废弃Direct并推荐使用Policy(策略)。本文会同时覆盖两种配置方式,帮你适配不同系统版本。
一图看懂SNAT:内网设备的“集体伪装术”

生活类比:公司前台代收快递
当你(内网主机192.168.1.100)网购时,快递单上写的收货地址是公司前台(防火墙公网IP 203.0.113.10),前台收到后再转给你。这里:
- 你 = 内网主机(私网IP)
- 前台 = 防火墙(公网IP)
- 快递单地址 = 数据包源IP
技术拆解:三步完成“身份转换”
- 内网发请求:你的电脑发送数据包,源IP是192.168.1.100,目标是百度服务器(180.101.49.12)
- 防火墙换“身份证”:数据包到达防火墙的POSTROUTING链(相当于“快递打包处”),源IP被换成公网IP 203.0.113.10
- 公网回包:百度服务器将响应发给203.0.113.10,防火墙查“收件人登记表”(连接跟踪表),把目标IP换回192.168.1.100并转发给你
firewalld配置SNAT:分版本适配
第一步:通用前置操作(所有版本必做)
# 永久开启IP转发(内核层面“打通任督二脉”)
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
第二步:旧版firewalld(依赖Direct接口)
适用于CentOS 7、RHEL 7等老版本系统,Direct接口仍可用但不推荐长期使用:
# 添加SNAT规则(静态公网IP)
firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 \
-s 192.168.1.0/24 -o eth0 -j SNAT --to-source 203.0.113.10
# 动态公网IP(家庭宽带)替换为MASQUERADE
firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 \
-s 192.168.1.0/24 -o eth0 -j MASQUERADE
# 重载规则生效
firewall-cmd --reload
第三步:新版firewalld(推荐Policy模式)
适用于CentOS 8/9、Rocky Linux、RHEL 8/9等新版本,完全替代废弃的Direct接口:
# 1. 创建自定义SNAT策略
firewall-cmd --permanent --new-policy=SNAT-Policy
# 2. 绑定策略到出口网卡所属zone(public)
firewall-cmd --permanent --policy=SNAT-Policy --add-ingress-zone=public
firewall-cmd --permanent --policy=SNAT-Policy --set-target=ACCEPT
# 3. 静态公网IP:添加SNAT的rich rule
firewall-cmd --permanent --policy=SNAT-Policy --add-rich-rule='
rule family="ipv4"
source address="192.168.1.0/24"
masquerade
to source="203.0.113.10"
'
# 动态公网IP:简化版rich rule
# firewall-cmd --permanent --policy=SNAT-Policy --add-rich-rule='
# rule family="ipv4" source address="192.168.1.0/24" masquerade
# '
# 4. 重载规则生效
firewall-cmd --reload
一图看懂DNAT:内网服务的“对外窗口”

生活类比:公司前台转接电话
客户(公网主机220.181.38.148)拨打公司总机(防火墙公网IP 203.0.113.10:80),前台(防火墙)根据分机表转给技术部(内网服务器192.168.1.20:80)。这里:
- 客户 = 公网主机
- 总机号 = 公网IP:端口
- 分机号 = 内网服务器IP:端口
技术拆解:三次“地址魔术”
- 公网发请求:客户访问203.0.113.10:80,数据包到达防火墙的PREROUTING链(相当于“总机接线处”)
- 防火墙换“目标地址”:目的IP从203.0.113.10换成192.168.1.20,目的端口保持80(如需端口转换可设为192.168.1.20:8080)
- 内网回包:服务器响应数据包经防火墙时,SNAT自动把源IP换成203.0.113.10,客户收到后以为是总机直接回复
firewalld配置DNAT:分版本适配
目标:将内网Web服务器(192.168.1.20:80)通过公网IP 203.0.113.10:8080发布。
方式1:旧版firewalld(Direct接口)
# 1. 添加DNAT规则
firewall-cmd --permanent --direct --add-rule ipv4 nat PREROUTING 0 \
-d 203.0.113.10 -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.20:80
# 2. 允许8080端口访问
firewall-cmd --permanent --add-port=8080/tcp
# 3. 带IP限制的增强版(仅允许114.222.33.0/24访问)
# firewall-cmd --permanent --direct --add-rule ipv4 nat PREROUTING 0 \
# -s 114.222.33.0/24 -d 203.0.113.10 -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.20:80
# 4. 重载规则
firewall-cmd --reload
方式2:新版firewalld(Policy模式)
# 1. 创建DNAT专用策略
firewall-cmd --permanent --new-policy=DNAT-Policy
firewall-cmd --permanent --policy=DNAT-Policy --add-egress-zone=public
firewall-cmd --permanent --policy=DNAT-Policy --set-target=ACCEPT
# 2. 基础版DNAT规则
firewall-cmd --permanent --policy=DNAT-Policy --add-rich-rule='
rule family="ipv4"
destination address="203.0.113.10"
port port="8080" protocol="tcp"
forward-port to-port="80" to-addr="192.168.1.20"
'
# 带IP限制的增强版
# firewall-cmd --permanent --policy=DNAT-Policy --add-rich-rule='
# rule family="ipv4"
# source address="114.222.33.0/24"
# destination address="203.0.113.10"
# port port="8080" protocol="tcp"
# forward-port to-port="80" to-addr="192.168.1.20"
# '
# 3. 开放8080端口
firewall-cmd --permanent --policy=DNAT-Policy --add-port=8080/tcp
# 4. 重载规则
firewall-cmd --reload
核心对比:SNAT与DNAT的“灵魂区别”
| 对比维度 | SNAT(源地址转换) | DNAT(目的地址转换) |
|---|---|---|
| 修改字段 | 数据包的“发件人”(源IP) | 数据包的“收件人”(目的IP) |
| 操作链 | POSTROUTING(数据包出站时) | PREROUTING(数据包入站时) |
| 核心作用 | 内网→公网:多设备共享上网 | 公网→内网:发布内网服务 |
| 形象比喻 | 前台帮员工代收快递 | 总机帮部门转接电话 |
| 旧版配置 | Direct + SNAT/MASQUERADE | Direct + DNAT |
| 新版配置 | Policy + masquerade规则 | Policy + forward-port规则 |
实战:分版本验证NAT规则
1. 旧版firewalld(Direct接口)验证
# 查看所有direct规则(含SNAT/DNAT)
firewall-cmd --direct --get-all-rules
# 查看开放端口
firewall-cmd --list-ports --permanent
2. 新版firewalld(Policy模式)验证
# 查看所有自定义策略
firewall-cmd --get-policies
# 查看SNAT策略详情
firewall-cmd --policy=SNAT-Policy --list-all
# 查看DNAT策略详情
firewall-cmd --policy=DNAT-Policy --list-all
# 查看策略中的rich rule
firewall-cmd --policy=DNAT-Policy --list-rich-rules
验证成功示例
- 旧版:执行
firewall-cmd --direct --get-all-rules能看到SNAT/DNAT规则条目; - 新版:执行
firewall-cmd --policy=DNAT-Policy --list-all能看到forward-port映射规则。
总结
- 版本适配核心:老版本(CentOS 7/RHEL 7)用Direct接口配置SNAT/DNAT,新版本(CentOS 8+/RHEL 8+)优先用Policy模式替代废弃的Direct接口。
- SNAT配置要点:静态公网IP用SNAT规则,动态IP(家庭宽带)用MASQUERADE,核心是修改数据包源IP实现共享上网。
- DNAT配置要点:通过端口映射将公网请求转发到内网服务,务必添加IP限制或端口放行规则,提升内网安全性。
- 规则验证:旧版用
--direct --get-all-rules,新版用--policy=<策略名> --list-all,无需依赖iptables命令。