firewalld 配置 internal 到 public 区域的流量转发

firewalld 支持通过 Policy 对象实现跨区域流量转发。本文介绍如何配置策略,允许 internal 区域的流量转发到 public 区域,使内网主机可以通过防火墙访问外部网络。

前提条件

  • firewalld 已安装并运行(systemctl status firewalld
  • 有 root 或 sudo 权限
  • 了解 firewalld 的 Zone 和 Policy 概念

创建转发策略

firewalld 的 Zone 控制接口上的流量方向,而 Policy 用于定义跨区域的流量转发规则。我们需要创建一个 Policy,将 internal 作为入口区域,public 作为出口区域。

# 创建新策略
sudo firewall-cmd --permanent --new-policy allow-internal-to-public

# 设置入口区域(源)为 internal,出口区域(目标)为 public
sudo firewall-cmd --permanent --policy allow-internal-to-public --add-ingress-zone internal
sudo firewall-cmd --permanent --policy allow-internal-to-public --add-egress-zone public

# 设置动作为 ACCEPT,并给予高优先级(确保不被其他策略覆盖)
sudo firewall-cmd --permanent --policy allow-internal-to-public --set-target ACCEPT
sudo firewall-cmd --permanent --policy allow-internal-to-public --set-priority -100

关键参数说明:

参数说明
--add-ingress-zone流量进入的区域(源区域)
--add-egress-zone流量出去的区域(目标区域)
--set-target ACCEPT匹配该策略的流量默认放行
--set-priority -100优先级数值越小越优先,负数确保优先于默认策略

开启伪装(MASQUERADE)

为了让内网 IP 的流量通过 public 区域的出口 IP 访问外部网络,需要为 public 区域开启源地址伪装(SNAT):

sudo firewall-cmd --permanent --zone=public --add-masquerade

启用 IP 转发

Linux 内核默认关闭 IP 转发功能,需要手动开启:

# 临时启用(重启后失效)
sudo sysctl -w net.ipv4.ip_forward=1

# 永久启用
echo net.ipv4.ip_forward=1 | sudo tee -a /etc/sysctl.d/99-ipforward.conf

重载防火墙

以上所有 --permanent 操作需要重载后才会生效:

sudo firewall-cmd --reload

验证配置

# 查看策略列表
sudo firewall-cmd --get-policies

# 查看策略详情
sudo firewall-cmd --info-policy allow-internal-to-public

# 查看 public 区域是否开启伪装
sudo firewall-cmd --zone=public --query-masquerade

# 查看 IP 转发状态
sysctl net.ipv4.ip_forward

常见问题

内网主机无法访问外部? 检查以下几点:

  1. 确认 net.ipv4.ip_forward 已设为 1
  2. 确认 public 区域的伪装已开启
  3. 确认 internal 区域的接口绑定正确:sudo firewall-cmd --zone=internal --list-all
  4. 确认内网主机的默认网关指向防火墙的 internal 接口 IP

策略优先级被覆盖? 使用更小的优先级数值(如 -200),firewalld 优先级范围是 -3276832767,数值越小越优先。

参考