跳转到内容

Firewalld 进阶

Firewalld 是 RHEL/CentOS 系列的默认防火墙管理工具。本文将深入介绍 Rich Rules、Direct Rules、自定义区域、端口转发、IP 伪装、ipset 等进阶功能,帮助你构建精细化的网络安全策略。

Rich Rules 提供了比简单的 --add-port/--add-service 更强大、更灵活的规则定义能力,可以基于源地址、目标地址、端口等条件进行精细控制。

rule
[family="ipv4|ipv6"]
[source address="地址[/掩码]" [invert="true"]]
[destination address="地址[/掩码]" [invert="true"]]
[service name="服务名" | port port="端口" protocol="tcp|udp" |
protocol value="协议" | icmp-block name="类型" | masquerade |
forward-port port="端口" protocol="tcp|udp" to-port="端口" [to-addr="地址"]]
[log [prefix="前缀"] [level="级别"] [limit value="频率"]]
[audit]
[accept|reject|drop]
Terminal window
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="3306" protocol="tcp" accept'
Terminal window
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.50" drop'
Terminal window
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'

拒绝特定 IP 访问 HTTP 并记录日志

Section titled “拒绝特定 IP 访问 HTTP 并记录日志”
Terminal window
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" service name="http" log prefix="HTTP-BLOCKED: " level="warning" limit value="5/m" reject'
Terminal window
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port port="8080-8090" protocol="tcp" accept'
Terminal window
# 查看当前区域的 Rich Rules
sudo firewall-cmd --list-rich-rules
# 删除 Rich Rule
sudo firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="10.0.0.50" drop'
# 使配置生效
sudo firewall-cmd --reload

Direct Rules 允许你直接向 iptables/nftables 后端插入规则,适用于 Rich Rules 无法满足的复杂场景。

Terminal window
sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 <iptables规则参数>
Terminal window
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPT
Terminal window
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 99 -j LOG --log-prefix "DROPPED: " --log-level 4
Terminal window
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -m mac --mac-source AA:BB:CC:DD:EE:FF -j DROP
Terminal window
# 查看所有 Direct Rules
sudo firewall-cmd --direct --get-all-rules
# 删除 Direct Rule
sudo firewall-cmd --permanent --direct --remove-rule ipv4 filter INPUT 0 -m mac --mac-source AA:BB:CC:DD:EE:FF -j DROP
sudo firewall-cmd --reload

Firewalld 内置了 public、trusted、dmz 等区域,但你也可以创建自定义区域来满足特殊需求。

Terminal window
# 创建名为 webservers 的区域
sudo firewall-cmd --permanent --new-zone=webservers
sudo firewall-cmd --reload
Terminal window
# 设置区域描述
sudo firewall-cmd --permanent --zone=webservers --set-description="Web Server Zone"
# 添加允许的服务
sudo firewall-cmd --permanent --zone=webservers --add-service=http
sudo firewall-cmd --permanent --zone=webservers --add-service=https
sudo firewall-cmd --permanent --zone=webservers --add-port=8080/tcp
# 将网络接口绑定到自定义区域
sudo firewall-cmd --permanent --zone=webservers --change-interface=eth1
# 将源地址绑定到区域
sudo firewall-cmd --permanent --zone=webservers --add-source=10.0.1.0/24
sudo firewall-cmd --reload
Terminal window
# 查看所有区域
sudo firewall-cmd --get-zones
# 查看特定区域的详细配置
sudo firewall-cmd --zone=webservers --list-all
# 查看所有活动区域
sudo firewall-cmd --get-active-zones
# 查看默认区域
sudo firewall-cmd --get-default-zone
Terminal window
sudo firewall-cmd --permanent --delete-zone=webservers
sudo firewall-cmd --reload

端口转发可以将到达某个端口的流量重定向到另一个端口或另一台主机。

将本机的 80 端口转发到 8080 端口:

Terminal window
sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
sudo firewall-cmd --reload

将本机 80 端口的流量转发到另一台主机的 8080 端口:

Terminal window
# 需要先启用 masquerade
sudo firewall-cmd --permanent --add-masquerade
# 添加端口转发规则
sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=192.168.1.100
sudo firewall-cmd --reload
Terminal window
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" forward-port port="443" protocol="tcp" to-port="8443" to-addr="192.168.1.100"'
sudo firewall-cmd --reload
Terminal window
sudo firewall-cmd --list-forward-ports
Terminal window
sudo firewall-cmd --permanent --remove-forward-port=port=80:proto=tcp:toport=8080
sudo firewall-cmd --reload

Masquerading(IP 伪装)是一种特殊的 SNAT(源地址转换),通常用于让内网机器通过防火墙主机访问外网。

Terminal window
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --reload
Terminal window
sudo firewall-cmd --query-masquerade
Terminal window
sudo firewall-cmd --permanent --zone=internal --add-masquerade
sudo firewall-cmd --reload

使用 Rich Rules 限制 Masquerade 范围

Section titled “使用 Rich Rules 限制 Masquerade 范围”

只对特定源网段启用 NAT:

Terminal window
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" masquerade'
sudo firewall-cmd --reload

Masquerade 和端口转发都需要内核的 IP 转发功能:

Terminal window
# 临时启用
sudo sysctl -w net.ipv4.ip_forward=1
# 永久启用
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/ip_forward.conf
sudo sysctl -p /etc/sysctl.d/ip_forward.conf

IPSet 允许你定义 IP 地址集合,然后在防火墙规则中引用,适用于需要管理大量 IP 的场景。

Terminal window
# 创建 IPv4 地址集合
sudo firewall-cmd --permanent --new-ipset=blacklist --type=hash:ip
# 创建支持网段的集合
sudo firewall-cmd --permanent --new-ipset=trusted_nets --type=hash:net
Terminal window
sudo firewall-cmd --permanent --ipset=blacklist --add-entry=203.0.113.50
sudo firewall-cmd --permanent --ipset=blacklist --add-entry=198.51.100.0/24
sudo firewall-cmd --permanent --ipset=trusted_nets --add-entry=10.0.0.0/8
sudo firewall-cmd --reload

创建 IP 列表文件:

Terminal window
cat <<EOF > /tmp/blacklist.txt
203.0.113.10
203.0.113.20
198.51.100.0/24
EOF

导入到 IPSet:

Terminal window
sudo firewall-cmd --permanent --ipset=blacklist --add-entries-from-file=/tmp/blacklist.txt
sudo firewall-cmd --reload
Terminal window
# 封禁黑名单中所有 IP
sudo firewall-cmd --permanent --add-rich-rule='rule source ipset="blacklist" drop'
# 允许白名单中的 IP 访问 SSH
sudo firewall-cmd --permanent --add-rich-rule='rule source ipset="trusted_nets" service name="ssh" accept'
sudo firewall-cmd --reload
Terminal window
# 查看所有 IPSet
sudo firewall-cmd --get-ipsets
# 查看 IPSet 内容
sudo firewall-cmd --ipset=blacklist --get-entries
# 移除条目
sudo firewall-cmd --permanent --ipset=blacklist --remove-entry=203.0.113.50
# 删除 IPSet
sudo firewall-cmd --permanent --delete-ipset=blacklist
sudo firewall-cmd --reload

防火墙日志对于安全审计和故障排查至关重要。

Terminal window
# 记录被拒绝的 SSH 连接
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="ssh" log prefix="SSH-ACCESS: " level="notice" limit value="3/m" accept'
# 记录被丢弃的流量
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" log prefix="FW-DROP: " level="warning" limit value="10/m" drop'
sudo firewall-cmd --reload
级别说明
emerg紧急
alert警报
crit严重
error错误
warning警告
notice通知
info信息
debug调试

limit value 防止日志泛滥导致磁盘写满:

频率格式说明
1/s每秒 1 条
5/m每分钟 5 条
10/h每小时 10 条
100/d每天 100 条
Terminal window
# 通过 journalctl 查看
sudo journalctl -k | grep "FW-DROP"
# 通过 dmesg 查看
sudo dmesg | grep "SSH-ACCESS"
# 查看 messages 日志
sudo grep "FW-DROP" /var/log/messages

Firewalld 可以全局记录所有被拒绝的连接:

Terminal window
# 查看当前设置
sudo firewall-cmd --get-log-denied
# 启用(可选值:all, unicast, broadcast, multicast, off)
sudo firewall-cmd --set-log-denied=all

完整实战:构建 Web 服务器防火墙策略

Section titled “完整实战:构建 Web 服务器防火墙策略”

以下示例为一台 Web 服务器配置完整的防火墙策略,包含自定义区域、IPSet 白名单、端口转发和日志记录。

  1. 创建管理 IPSet:

    Terminal window
    sudo firewall-cmd --permanent --new-ipset=admin_ips --type=hash:ip
    sudo firewall-cmd --permanent --ipset=admin_ips --add-entry=192.168.1.10
    sudo firewall-cmd --permanent --ipset=admin_ips --add-entry=192.168.1.11
  2. 配置基本的 public 区域规则:

    Terminal window
    # 允许 HTTP 和 HTTPS
    sudo firewall-cmd --permanent --add-service=http
    sudo firewall-cmd --permanent --add-service=https
    # 移除默认的 SSH 服务(后面用 Rich Rule 限制)
    sudo firewall-cmd --permanent --remove-service=ssh
  3. 添加 Rich Rules:

    Terminal window
    # 仅允许管理员 IP 通过 SSH
    sudo firewall-cmd --permanent --add-rich-rule='rule source ipset="admin_ips" service name="ssh" accept'
    # 记录并丢弃其他 SSH 尝试
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="ssh" log prefix="SSH-DENIED: " level="warning" limit value="3/m" drop'
    # 记录 HTTP 访问(采样)
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="http" log prefix="HTTP: " level="info" limit value="1/m" accept'
  4. 配置端口转发(HTTP 转发到后端应用):

    Terminal window
    sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
  5. 应用并验证:

    Terminal window
    sudo firewall-cmd --reload
    sudo firewall-cmd --list-all
    sudo firewall-cmd --list-rich-rules

通过灵活运用 Rich Rules、IPSet、端口转发和日志功能,可以构建出精细化的防火墙安全策略,在保障业务正常运行的同时有效防御网络威胁。