Firewalld 配置端口转发、SNAT、DNAT

Firewalld通过富规则(rich rules)和直接规则(direct rules)支持端口转发和NAT。 下面详细说明各种配置方法:

端口转发(Port Forwarding)

方法1:使用富规则(推荐)

基础端口转发(本地转发)

# 将外部访问 8080 端口的流量转发到本机 80 端口
firewall-cmd --add-forward-port=port=8080:proto=tcp:toport=80

# 永久生效
firewall-cmd --add-forward-port=port=8080:proto=tcp:toport=80 --permanent

# 转发到其他主机的端口
firewall-cmd --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=192.168.1.100

# 转发UDP端口
firewall-cmd --add-forward-port=port=53:proto=udp:toport=53:toaddr=192.168.1.53

查看和管理端口转发规则

# 查看所有转发规则
firewall-cmd --list-forward-ports

# 查看特定区域的转发规则
firewall-cmd --zone=public --list-forward-ports

# 删除转发规则
firewall-cmd --remove-forward-port=port=8080:proto=tcp:toport=80
firewall-cmd --remove-forward-port=port=8080:proto=tcp:toport=80:toaddr=192.168.1.100

方法2:使用富规则的完整语法

# 更详细的转发规则
firewall-cmd --add-rich-rule='
  rule family="ipv4"
  source address="192.168.1.0/24"
  forward-port port="8080" protocol="tcp" to-port="80" to-addr="192.168.1.100"
'

# 带日志记录的转发
firewall-cmd --add-rich-rule='
  rule family="ipv4"
  forward-port port="2222" protocol="tcp" to-port="22" to-addr="10.0.0.100"
  log prefix="SSH_FORWARD: " level="info"
'

SNAT配置(源地址转换)

SNAT:本地网络访问互联网

# 启用区域的IP伪装(masquerade) - 这是SNAT的简化版
firewall-cmd --zone=external --add-masquerade

# 永久生效
firewall-cmd --zone=external --add-masquerade --permanent

# 查看是否启用了伪装
firewall-cmd --zone=external --query-masquerade

# 禁用伪装
firewall-cmd --zone=external --remove-masquerade

自定义SNAT规则

# 方法1:使用富规则
firewall-cmd --add-rich-rule='
  rule family="ipv4"
  source address="192.168.1.0/24"
  masquerade
'

# 方法2:使用直接规则(更灵活)
# 将192.168.1.0/24的源IP转换为公网IP 203.0.113.100
firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 \
  -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 203.0.113.100

# 查看直接规则
firewall-cmd --direct --get-all-rules

DNAT配置(目的地址转换)

DNAT:将外部访问转发到内部服务器

# 方法1:使用端口转发(会自动设置DNAT)
firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=192.168.1.100

# 方法2:使用直接规则
# 将访问 203.0.113.100:80 的流量 DNAT 到 192.168.1.100:80
firewall-cmd --direct --add-rule ipv4 nat PREROUTING 0 \
  -d 203.0.113.100 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:80

# 如果是动态IP,使用MASQUERADE自动获取出口IP
firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 \
  -s 192.168.1.0/24 -o eth0 -j MASQUERADE

完整配置示例

示例1:家庭网关路由器

# 1. 配置接口区域
firewall-cmd --zone=external --add-interface=eth0    # WAN口
firewall-cmd --zone=internal --add-interface=eth1    # LAN口

# 2. 启用IP伪装(SNAT)
firewall-cmd --zone=external --add-masquerade

# 3. 设置端口转发(DNAT)
# 将外网SSH访问转发到内网服务器
firewall-cmd --add-forward-port=port=2222:proto=tcp:toport=22:toaddr=192.168.1.100

# 将外网Web访问转发到内网Web服务器
firewall-cmd --add-forward-port=port=80:proto=tcp:toport=80:toaddr=192.168.1.200
firewall-cmd --add-forward-port=port=443:proto=tcp:toport=443:toaddr=192.168.1.200

# 4. 允许内网访问外网
firewall-cmd --zone=internal --add-service=http
firewall-cmd --zone=internal --add-service=https

# 5. 保存配置
firewall-cmd --runtime-to-permanent

示例2:Web服务器负载均衡器

# 1. 启用伪装
firewall-cmd --zone=public --add-masquerade

# 2. 负载均衡:将80端口流量轮询转发到后端服务器
firewall-cmd --direct --add-rule ipv4 nat PREROUTING 0 \
  -p tcp --dport 80 -m statistic --mode nth --every 2 --packet 0 \
  -j DNAT --to-destination 192.168.1.101:80
  
firewall-cmd --direct --add-rule ipv4 nat PREROUTING 1 \
  -p tcp --dport 80 \
  -j DNAT --to-destination 192.168.1.102:80

# 3. 健康检查流量放行
firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 \
  -s 192.168.1.0/24 -d 192.168.1.101 -p tcp --dport 80 -j ACCEPT

示例3:开发环境端口转发

# 将本地开发服务器暴露给局域网
# 1. 启用伪装(如果需要)
firewall-cmd --zone=public --add-masquerade

# 2. 转发外部3000端口到本机3000端口
firewall-cmd --add-forward-port=port=3000:proto=tcp:toport=3000

# 3. 转发多个开发服务
firewall-cmd --add-forward-port=port=8080:proto=tcp:toport=8080
firewall-cmd --add-forward-port=port=9000:proto=tcp:toport=9000

# 4. 限制只允许内网访问
firewall-cmd --add-rich-rule='
  rule family="ipv4" 
  source address="192.168.0.0/16"
  forward-port port="3000" protocol="tcp" to-port="3000"
  log prefix="DEV_FORWARD: "
'

高级NAT配置

一对一NAT(静态NAT)

# 将整个外部IP映射到内部IP
firewall-cmd --direct --add-rule ipv4 nat PREROUTING 0 \
  -d 203.0.113.100 -j DNAT --to-destination 192.168.1.100
  
firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 \
  -s 192.168.1.100 -j SNAT --to-source 203.0.113.100

多端口范围转发

# 转发端口范围
for port in {5000..5010}; do
  firewall-cmd --add-forward-port=port=$port:proto=tcp:toport=$port:toaddr=192.168.1.100
done

# 或者使用直接规则
firewall-cmd --direct --add-rule ipv4 nat PREROUTING 0 \
  -p tcp -m multiport --dports 5000:5010 \
  -j DNAT --to-destination 192.168.1.100

条件转发(基于源IP)

# 只允许特定IP访问转发服务
firewall-cmd --add-rich-rule='
  rule family="ipv4"
  source address="10.0.0.0/8"
  forward-port port="3389" protocol="tcp" to-port="3389" to-addr="192.168.1.150"
'

# 拒绝其他IP访问
firewall-cmd --add-rich-rule='
  rule family="ipv4"
  source address="0.0.0.0/0"
  port port="3389" protocol="tcp"
  reject
'

持久化配置

方法1:使用永久标志

# 添加规则时直接永久保存
firewall-cmd --add-forward-port=port=8080:proto=tcp:toport=80 --permanent

# 或者先添加运行时规则,再永久化
firewall-cmd --add-forward-port=port=8080:proto=tcp:toport=80
firewall-cmd --runtime-to-permanent

方法2:直接编辑XML配置文件

# 端口转发规则存储在区域配置中
sudo nano /etc/firewalld/zones/public.xml

# 添加如下内容:
<forward-port port="8080" protocol="tcp" to-port="80"/>

# 重载配置
firewall-cmd --reload

查看和验证配置

查看所有NAT相关配置

# 查看转发端口
firewall-cmd --list-forward-ports

# 查看富规则
firewall-cmd --list-rich-rules | grep forward-port

# 查看直接规则
firewall-cmd --direct --get-all-rules

# 查看伪装状态
firewall-cmd --zone=public --query-masquerade

# 查看完整的区域配置
firewall-cmd --zone=public --list-all

验证规则是否生效

# 1. 查看iptables规则(Firewalld底层生成)
sudo iptables -t nat -L -n -v

# 2. 检查具体的NAT规则
sudo iptables -t nat -L PREROUTING -n -v
sudo iptables -t nat -L POSTROUTING -n -v

# 3. 使用tcpdump监控流量
sudo tcpdump -i eth0 -n port 8080

# 4. 测试端口转发
# 从另一台机器测试
telnet 网关IP 8080

故障排除

常见问题解决

# 1. 端口转发不工作
# 检查是否启用了伪装
firewall-cmd --query-masquerade

# 2. 规则没保存
# 检查运行时和永久配置
firewall-cmd --list-forward-ports
firewall-cmd --list-forward-ports --permanent

# 3. 直接规则丢失
# 直接规则需要单独持久化
firewall-cmd --direct --add-rule ipv4 nat PREROUTING 0 ... --permanent

# 4. 冲突规则
# 检查是否有重复或冲突规则
iptables -t nat -L -n --line-numbers

调试命令

# 跟踪数据包路径
sudo iptables -t nat -L -n -v --line-numbers

# 清除并重新加载
sudo firewall-cmd --reload

# 临时关闭防火墙测试
sudo firewall-cmd --panic-on   # 紧急模式(拒绝所有)
sudo firewall-cmd --panic-off  # 恢复正常

# 查看日志
sudo journalctl -u firewalld -f
sudo tail -f /var/log/messages | grep firewalld

性能优化建议

# 1. 减少直接规则数量,尽量使用富规则
# 2. 合并端口范围,减少规则数量
# 3. 使用连接跟踪优化
sysctl -w net.netfilter.nf_conntrack_max=262144

# 4. 对于大量转发,考虑使用ipset
firewall-cmd --new-ipset=trusted_ips --type=hash:ip --permanent
firewall-cmd --ipset=trusted_ips --add-entry=192.168.1.100 --permanent
firewall-cmd --add-rich-rule='rule source ipset=trusted_ips forward-port port="80" to-port="8080"'

与iptables对比

功能 Firewalld方式 iptables方式
简单端口转发 --add-forward-port -A PREROUTING -j REDIRECT
SNAT --add-masquerade -A POSTROUTING -j SNAT
DNAT --add-forward-port toaddr= -A PREROUTING -j DNAT
条件转发 富规则 多个规则组合
持久化 自动/手动永久化 iptables-save/restore

总结

Firewalld配置端口转发和NAT的核心方法:

  1. 端口转发:使用 --add-forward-port
  2. SNAT:使用 --add-masquerade 或直接规则
  3. DNAT:使用 --add-forward-porttoaddr 或直接规则
  4. 复杂规则:使用富规则或直接规则

推荐策略:

  • 简单需求:使用Firewalld原生命令
  • 复杂场景:使用富规则
  • 特殊需求:使用直接规则(保持iptables语法兼容)
  • 生产环境:测试后永久保存,监控日志
posted @ 2026-01-24 19:37  开元澄  阅读(15)  评论(0)    收藏  举报