FirewallD 实践场景与最佳实践(firewalld包含哪些规则)

FirewallD作为Linux系统中动态的防火墙管理工具,其“区域(Zone)”概念和动态管理特性使其在多种场景下都能灵活应用。

1. FirewallD的常见应用场景和实际使用示例

FirewallD通过区域、服务、端口和富规则等功能,可以满足不同网络环境的安全需求。

1.1 Web服务器防火墙配置

Web服务器通常需要对外开放HTTP(80/tcp)和HTTPS(443/tcp)端口,同时可能需要SSH(22/tcp)用于管理。

场景描述:一台Web服务器,对外提供HTTP和HTTPS服务,管理员通过SSH进行远程管理。

配置示例

将服务器网卡(例如eth0)分配到public区域:
firewall-cmd --zone=public --add-interface=eth0 --permanent  
firewall-cmd --reload
说明:public区域是默认区域,通常用于不信任的网络,只允许明确放行的流量。
在public区域开放HTTP和HTTPS服务:
 firewall-cmd --zone=public --add-service=http --permanent  
firewall-cmd --zone=public --add-service=https --permanent  
firewall-cmd --reload
说明:FirewallD预定义了http和https服务,无需记住端口号。
在public区域开放SSH服务:
firewall-cmd --zone=public --add-service=ssh --permanent  
firewall-cmd --reload
说明:SSH是远程管理必备服务。
(可选)如果SSH端口不是默认的22,或者需要限制SSH访问源IP:开放自定义SSH端口(例如2222):
firewall-cmd --zone=public --remove-service=ssh --permanent # 先移除默认SSH服务 sudo firewall-cmd --zone=public --add-port=2222/tcp --permanent 
firewall-cmd --reload
只允许特定IP(例如192.168.1.100)访问SSH:
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept' --permanent  
firewall-cmd --reload
说明:使用富规则可以实现更精细的访问控制。

1.2 数据库服务器防火墙配置

数据库服务器通常只允许应用服务器或特定管理IP访问其数据库端口,安全性要求较高。

场景描述:一台数据库服务器,只允许来自应用服务器(IP:192.168.1.50)和管理机(IP:192.168.1.100)的MySQL(3306/tcp)连接。

配置示例

将服务器网卡分配到internal或public区域(根据实际网络环境选择,这里假设public):
firewall-cmd --zone=public --add-interface=eth0 --permanent 
 firewall-cmd --reload
默认情况下,public区域会拒绝所有传入连接。使用富规则只允许特定IP访问MySQL服务:
允许应用服务器访问MySQL 
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.50" port port=3306 protocol=tcp accept' --permanent # 允许管理机访问MySQL  
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port=3306 protocol=tcp accept' --permanent 
firewall-cmd --reload
说明:这里直接指定端口号,因为FirewallD可能没有预定义所有数据库服务。
(可选)如果数据库服务器也需要SSH管理,同样限制SSH访问源IP:
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept' --permanent 
firewall-cmd --reload

1.3 家庭/办公网络防火墙配置

在家庭或小型办公网络中,可能需要信任内部设备,同时对外保持较高的安全性。

场景描述:一台Linux主机作为家庭/办公网络中的服务器,连接到内部网络(eth0)和外部网络(eth1)。内部网络中的设备应被信任,外部网络则不信任。

配置示例

将内部网卡(例如eth0)分配到home区域:
firewall-cmd --zone=home --add-interface=eth0 --permanent  
firewall-cmd --reload
说明:home区域默认信任内部网络中的其他计算机。
将外部网卡(例如eth1)分配到public区域:
firewall-cmd --zone=public --add-interface=eth1 --permanent 
firewall-cmd --reload
在public区域开放必要的对外服务(例如SSH、Web服务等):
firewall-cmd --zone=public --add-service=ssh --permanent 
 firewall-cmd --zone=public --add-service=http --permanent  
firewall-cmd --reload
(可选)启用IP伪装(NAT),使内部网络设备可以通过该Linux主机访问外部网络:
 firewall-cmd --zone=public --add-masquerade --permanent  
firewall-cmd --reload
说明:这通常用于将Linux主机配置为路由器或网关。

1.4 端口转发(DNAT)

当内部网络有服务需要对外提供,但又不想直接暴露内部服务器时,可以使用端口转发。

场景描述:内部Web服务器(IP:192.168.1.10,端口:8080)需要通过防火墙的公共IP(例如防火墙主机)对外提供HTTP服务(端口:80)。

配置示例

确保防火墙主机已启用IP伪装(NAT):
firewall-cmd --zone=public --add-masquerade --permanent 
firewall-cmd --reload
添加端口转发规则:
firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=192.168.1.10 --permanent 
firewall-cmd --reload
说明:外部访问防火墙主机的80/tcp端口的流量,将被转发到内部IP 192.168.1.10 的8080/tcp端口。

2. 适用于新手用户的FirewallD最佳实践脚本和配置模板

以下是一些通俗易懂的FirewallD最佳实践和配置模板,帮助新手快速上手。

2.1 基本安全配置脚本(适用于大多数单机服务器)

这个脚本将配置一个相对安全的FirewallD环境,只开放SSH和HTTP/HTTPS服务。

bash #!/bin/bash

echo "--- 开始配置 FirewallD ---"

# 1. 确保 FirewallD 服务已安装并运行
echo "检查 FirewallD 服务状态..."
sudo systemctl enable firewalld --now
if systemctl is-active --quiet firewalld; then
    echo "FirewallD 服务已启动并设置为开机自启。"
else
    echo "FirewallD 服务启动失败,请检查系统日志。"
    exit 1
fi

# 2. 设置默认区域为 public (通常是默认,但再次确认)
echo "设置默认区域为 public..."
sudo firewall-cmd --set-default-zone=public
echo "当前默认区域: $(firewall-cmd --get-default-zone)"

# 3. 移除 public 区域中所有当前的服务和端口(确保干净配置)
echo "移除 public 区域中所有当前的服务和端口..."
# 运行时移除
for service in $(sudo firewall-cmd --zone=public --list-services); do
    sudo firewall-cmd --zone=public --remove-service=$service
done
for port in $(sudo firewall-cmd --zone=public --list-ports); do
    sudo firewall-cmd --zone=public --remove-port=$port
done
# 永久移除
for service in $(sudo firewall-cmd --zone=public --list-services --permanent); do
    sudo firewall-cmd --zone=public --remove-service=$service --permanent
done
for port in $(sudo firewall-cmd --zone=public --list-ports --permanent); do
    sudo firewall-cmd --zone=public --remove-port=$port --permanent
done
sudo firewall-cmd --reload # 重新加载以应用永久移除

# 4. 在 public 区域永久开放 SSH 服务
echo "在 public 区域永久开放 SSH 服务 (22/tcp)..."
sudo firewall-cmd --zone=public --add-service=ssh --permanent

# 5. 在 public 区域永久开放 HTTP 和 HTTPS 服务
echo "在 public 区域永久开放 HTTP (80/tcp) 和 HTTPS (443/tcp) 服务..."
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --add-service=https --permanent

# 6. 重新加载 FirewallD 配置以使永久设置生效
echo "重新加载 FirewallD 配置..."
sudo firewall-cmd --reload

# 7. 验证配置
echo "--- 验证 FirewallD 配置 ---"
sudo firewall-cmd --zone=public --list-all

echo "--- FirewallD 配置完成! ---"
echo "请确保您的SSH连接没有中断。如果远程操作,请谨慎。"

使用方法

  1. 将上述内容保存为 setup_firewalld.sh 文件。
  2. 赋予执行权限:chmod +x setup_firewalld.sh
  3. 运行脚本:sudo ./setup_firewalld.sh

2.2 开放自定义端口模板

当你的应用使用非标准端口时,可以使用此模板。

bash #!/bin/bash

# 要开放的端口号和协议 (例如: 8080/tcp, 5000/udp)
PORT_TO_OPEN="8080/tcp"
# 端口所在的区域 (例如: public, home)
ZONE_NAME="public"

echo "--- 开放自定义端口 ${PORT_TO_OPEN} 到 ${ZONE_NAME} 区域 ---"

# 1. 检查端口是否已开放
if sudo firewall-cmd --zone=${ZONE_NAME} --query-port=${PORT_TO_OPEN}; then
    echo "端口 ${PORT_TO_OPEN} 已在 ${ZONE_NAME} 区域开放,无需重复操作。"
else
    # 2. 永久开放端口
    echo "正在永久开放端口 ${PORT_TO_OPEN} 到 ${ZONE_NAME} 区域..."
    sudo firewall-cmd --zone=${ZONE_NAME} --add-port=${PORT_TO_OPEN} --permanent
    echo "端口 ${PORT_TO_OPEN} 已添加到永久配置。"

    # 3. 重新加载 FirewallD 配置
    echo "重新加载 FirewallD 配置以使更改生效..."
    sudo firewall-cmd --reload
    echo "FirewallD 配置已重新加载。"

    # 4. 验证端口是否已开放
    if sudo firewall-cmd --zone=${ZONE_NAME} --query-port=${PORT_TO_OPEN}; then
        echo "成功:端口 ${PORT_TO_OPEN} 已在 ${ZONE_NAME} 区域开放。"
    else
        echo "失败:端口 ${PORT_TO_OPEN} 未能在 ${ZONE_NAME} 区域开放,请检查日志。"
    fi
fi

echo "--- 操作完成 ---"

使用方法

  1. 将上述内容保存为 open_custom_port.sh
  2. 修改 PORT_TO_OPENZONE_NAME 变量为你的实际需求。
  3. 赋予执行权限:chmod +x open_custom_port.sh
  4. 运行脚本:sudo ./open_custom_port.sh

3. Linux新手在使用FirewallD时可能遇到的常见问题和相应的解决方案

常见问题

可能原因

解决方案

firewall-cmd --state 显示 not running

FirewallD 服务未启动或未启用开机自启。

1. 启动服务:sudo systemctl start firewalld。2. 设置开机自启:sudo systemctl enable firewalld。3. 检查服务状态:sudo systemctl status firewalld

ERROR: INVALID_ZONE

指定的区域名称不存在或拼写错误。

使用 firewall-cmd --get-zones 命令查看所有可用区域,确保名称正确。

Warning: NOT_ENABLED: <service_name>

尝试移除一个未启用的服务。

这通常是警告而非错误,操作仍然成功。确认服务是否确实需要移除。

Warning: ZONE_ALREADY_SET: '<interface>' already bound to '<zone>'

网络接口已在其他区域或被NetworkManager管理。

1. 检查 /etc/firewalld/zones/ 下的区域配置文件,确保接口没有被重复定义。2. 如果接口已在某个区域,使用 --change-interface 而不是 --add-interface 来更改其区域。3. 如果是NetworkManager导致,可能需要调整NetworkManager的配置。

firewall-cmd --permanent 命令后规则未生效

--permanent 选项只将规则保存到配置文件,不会立即生效。

执行 sudo firewall-cmd --reload 命令重新加载配置。

SSH 连接中断(远程操作时)

在远程SSH会话中,执行了阻止SSH端口(默认22/tcp)的防火墙规则,或者将接口切换到了一个不开放SSH的区域(如dropblock)。

预防措施:在进行任何可能影响SSH连接的防火墙操作前,始终保持一个备用连接(例如通过控制台、VNC或另一个SSH会话),或者先添加允许SSH的规则并测试。恢复措施:如果连接中断,可能需要通过服务器控制台或重启服务器(如果规则未持久化)来恢复。如果规则已持久化,重启后仍无法连接,则需要通过控制台登录并移除或修改相关规则。小技巧:在测试新规则时,可以先不加 --permanent 选项,如果出现问题,重启FirewallD服务即可恢复到上次的永久配置。

开放端口后服务仍然无法访问

1. 服务本身未运行或监听在错误的端口。2. SELinux或其他安全机制阻止了连接。3. 网络路由或上游防火墙问题。

1. 检查服务状态(例如 sudo systemctl status nginx),确认服务正在监听正确的端口(`sudo netstat -tulnp

无法创建或修改永久规则(权限问题)

未使用 sudo 或当前用户没有足够的权限。

确保所有 firewall-cmd 命令都以 sudo 前缀执行。

firewall-cmd --reload 报错或无响应

FirewallD 服务可能处于异常状态。

尝试重启FirewallD服务:sudo systemctl restart firewalld。如果问题依旧,检查系统日志 (journalctl -xe) 获取详细错误信息。

规则添加后,--list-all 中看不到

1. 规则只添加了运行时配置,未添加永久配置。2. 规则添加到了错误的区域。

1. 确保添加规则时使用了 --permanent 选项,并执行了 sudo firewall-cmd --reload。2. 使用 sudo firewall-cmd --zone=<zone_name> --list-all 检查特定区域的规则。

原文链接:,转发请注明来源!