第36章:firewalld 防火墙(CentOS/RHEL)

第三十六章:firewalld 防火墙(CentOS/RHEL)

CentOS/RHEL(以及 Fedora、OpenSUSE 等)默认使用 firewalld 作为防火墙管理工具。和Ubuntu的UFW不同,firewalld是红帽系Linux的标配。

firewalld的核心概念是"区域"(Zone)——每个网络接口可以属于一个区域,每个区域有不同的信任级别和规则。firewalld还支持"服务"(Service)和"端口"(Port)的灵活配置,比直接写iptables规则要友好得多。

本章配套视频:CentOS服务器到手,先把firewalld配置好,别等被黑了才想起来。

36.1 firewalld 简介:动态防火墙

firewalld(Dynamic Firewall Manager)是红帽Linux的默认防火墙管理系统,从RHEL 7开始取代了iptables的静态配置方式。

36.1.1 基于 iptables

和UFW一样,firewalld底层也是iptables/netfilter。它通过D-Bus接口与iptables交互,提供了更灵活的配置方式。

graph TB
    A["firewalld命令行<br/>firewall-cmd"]
    B["firewalld配置<br/>XML文件"]
    C["D-Bus接口"]
    D["iptables规则"]
    E["netfilter内核模块"]
    A --> C --> D --> E
    B --> C
    style A fill:#ccffcc
    style D fill:#ffcccc
    style E fill:#ff9999

36.1.2 zone 概念

firewalld引入了"区域"(Zone)的概念。Zone是一组预定义的规则集,代表不同的信任级别。

每个网卡可以分配到一个Zone,firewalld根据网卡所属Zone来决定应用哪些规则。Zone是firewalld的核心,几乎所有的配置都围绕着Zone展开。

graph TB
    A["firewalld Zone"] --> B["drop"]
    A --> C["block"]
    A --> D["public"]
    A --> E["external"]
    A --> F["internal"]
    A --> G["trusted"]
    
    B["drop:最低信任<br/>丢弃所有入站连接<br/>出站可以"]
    C["block:拒绝<br/>拒绝所有入站连接<br/>返回ICMP错误"]
    D["public:公共<br/>不信任任何主机<br/>只允许选定的入站连接"]
    E["external:外部<br/>用于NAT/路由<br/>只有SSH和指定服务"]
    F["internal:内部<br/>内部网络<br/>允许大部分入站"]
    G["trusted:完全信任<br/>允许所有连接<br/>最危险也最方便"]
    
    style B fill:#ff6666
    style C fill:#ff9999
    style D fill:#ffe0cc
    style E fill:#ffffcc
    style F fill:#ccffcc
    style G fill:#99ff99

36.2 firewall-cmd 命令

firewalld的管理命令是firewall-cmd。和UFW类似,它也提供了运行时配置和永久配置两种模式。

1
2
3
4
5
# 查看firewalld版本
firewall-cmd --version

# 查看当前状态
firewall-cmd --state
1
running

重要区别:firewalld区分"运行时配置"(Runtime)和"永久配置"(Permanent)。运行时配置立即生效但重启后丢失,永久配置需要reload才生效。生产环境务必使用--permanent参数

⚠️ 血泪教训:很多新手配置完防火墙,重启服务器后发现规则没了,SSH连不上——就是因为没加--permanent!配置完记得测试:sudo firewall-cmd --reload

36.3 zone 概念

firewalld内置了多个预设Zone,每个Zone有不同的默认规则。

36.3.1 drop:最低信任

drop区域是"最不信任"的区域,丢弃所有入站数据包,不回复任何响应。

1
2
# 查看drop区域的规则
firewall-cmd --zone=drop --list-all
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
drop (active)
  target: DROP
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
  • target: DROP:默认动作是丢弃所有入站
  • interfaces: eth0:eth0网卡属于这个zone
  • services::没有放行任何服务

36.3.2 block:拒绝

block区域和drop类似,但会返回ICMP错误(如icmp-host-prohibited)。

1
firewall-cmd --zone=block --list-all
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
block (active)
  target: %%REJECT%%
  icmp-block-inversion: no
  interfaces:
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

%%REJECT%% vs DROP:REJECT会返回ICMP拒绝消息,告诉对方"你被拒绝了";DROP则完全无视,就像石沉大海。

36.3.3 public:公共

public区域是firewalld的默认区域,适用于"公共场所"的网卡(如连接互联网的网卡)。

1
firewall-cmd --zone=public --list-all
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: ssh dhcpv6-client
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

默认只放行了sshdhcpv6-client,其他入站连接一律默认拒绝。

36.3.4 external:外部

external区域用于需要NAT/路由功能的场景,比如把服务器当路由器用。

1
firewall-cmd --zone=external --list-all
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
external (active)
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: ssh
  ports:
  protocols:
  masquerade: yes      # 开启NAT伪装!
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

注意masquerade: yes——这是external区域的特殊之处,它会自动开启IP地址伪装(类似家用路由器的NAT功能)。

36.3.5 internal:内部

internal区域适用于内部网络,信任度较高,默认允许大部分入站服务。

1
firewall-cmd --zone=internal --list-all
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
internal (active)
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: ssh mdns samba-client dhcpv6-client
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

默认允许sshmdns(局域网设备发现)、samba-client(Windows文件共享客户端)、dhcpv6-client

36.3.6 trusted:完全信任

trusted区域是最危险的区域——允许所有入站连接。等同于"关掉防火墙"。

1
firewall-cmd --zone=trusted --list-all
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
trusted (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces:
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

target: ACCEPT意味着所有入站连接都被接受。

使用场景:trusted区域适合用于管理网卡(如VPN网卡),只允许管理员从特定网卡访问。

36.4 firewall-cmd –list-all:查看所有规则

查看当前zone的所有规则:

1
2
3
4
5
# 查看默认zone的所有规则
firewall-cmd --list-all

# 查看指定zone的规则
firewall-cmd --zone=public --list-all
1
2
# 查看所有zone
firewall-cmd --list-all-zones
1
2
3
4
5
6
7
8
# 查看已放行的服务
firewall-cmd --list-services

# 查看已放行的端口
firewall-cmd --list-ports

# 查看已放行的协议
firewall-cmd --list-protocols

36.5 firewall-cmd –add-port:开放端口

--add-port开放端口:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 临时开放80端口(运行时配置,重启失效)
sudo firewall-cmd --add-port=80/tcp

# 永久开放80端口
sudo firewall-cmd --permanent --add-port=80/tcp

# 开放端口范围
sudo firewall-cmd --permanent --add-port=8000-9000/tcp

# 开放UDP端口
sudo firewall-cmd --permanent --add-port=53/udp

# 查看结果
sudo firewall-cmd --list-ports
1
80/tcp

生产环境必用--permanent:临时配置重启就丢,永久配置才靠谱。

36.6 firewall-cmd –remove-port:关闭端口

1
2
3
4
5
6
7
8
# 永久关闭80端口
sudo firewall-cmd --permanent --remove-port=80/tcp

# 重新加载使配置生效
sudo firewall-cmd --reload

# 验证
sudo firewall-cmd --list-ports

36.7 firewall-cmd –add-service:按服务开放

firewalld内置了很多预定义服务,比直接指定端口更方便:

1
2
# 查看所有可用服务
firewall-cmd --get-services
1
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine condor-contact condor-creator dhcp dhcpv6 dhcpv6-client dns docker-registry dropbox-lansync elasticsearch freeswitch git gre gopher high-availability http https imap imaps ipp ipp-client ipsec iscsi-target jenkins kadmin kerberos kibana klogin kpasswd kshell ldap ldaps libvirt libvirt-clients lightning-network llmnr managesieve matrix mdns minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql mysql nfs nfs3 nmea-2000 portmap postgresql privoxy prometheus proxy-dhcp ptp pulseaudio puppetmaster quassel radius redis redis-sentinel rpc-bind rsh rsyncd rtsp salt-master samba samba-client samba-dc sane sip sips smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh steam-streaming svdrp svn syslog syslog-tls telnet tentp tftp tftp-client tinc tor-socks transmission-daemon-gtk udp-broadcast vdsm vnc-server wbem-http wbem-https wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 永久放行HTTP服务
sudo firewall-cmd --permanent --add-service=http

# 永久放行HTTPS服务
sudo firewall-cmd --permanent --add-service=https

# 同时放行多个服务
sudo firewall-cmd --permanent --add-service={http,https}

# 放行Nginx Full(包含http和https)
sudo firewall-cmd --permanent --add-service=nginx-full

# 关闭服务
sudo firewall-cmd --permanent --remove-service=http
1
2
# 查看已放行的服务
sudo firewall-cmd --list-services
1
ssh dhcpv6-client http https

36.8 firewall-cmd –permanent:永久生效

--permanent参数是firewalld的"持久化开关"。不加这个参数,配置只对当前会话生效,重启后丢失。

1
2
3
4
5
6
7
8
# 错误做法:临时生效,重启后没了
sudo firewall-cmd --add-port=80/tcp

# 正确做法:永久生效
sudo firewall-cmd --permanent --add-port=80/tcp

# reload使永久配置生效
sudo firewall-cmd --reload

实战顺序:先--permanent添加规则,最后--reload一次性使所有永久配置生效。不要每改一条就reload一次,效率太低。

36.9 firewall-cmd –reload:重新加载

--reload重新读取配置文件,使所有--permanent添加的规则生效。

1
2
3
4
5
6
7
8
# 重新加载配置
sudo firewall-cmd --reload

# 查看当前运行时配置(不是永久配置)
sudo firewall-cmd --list-all

# 查看运行时配置的完整信息
sudo firewall-cmd --runtime-to-permanent
1
2
3
4
5
6
# 典型配置流程
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --permanent --remove-service=cockpit
sudo firewall-cmd --reload

36.10 rich-rule 高级规则

rich-rule(富规则)是firewalld的高级规则语法,支持复杂的条件判断和动作。

36.10.1 基于 IP 的规则

按来源IP放行或拒绝:

1
2
3
4
5
6
7
8
# 只允许特定IP访问SSH
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept'

# 禁止特定IP访问所有端口
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.50" drop'

# 允许特定IP段访问80端口
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="80" protocol="tcp" accept'
1
2
# 查看所有富规则
sudo firewall-cmd --list-rich-rules
1
rule family="ipv4" source address="192.168.1.100" service name="ssh" accept

36.10.2 端口转发

firewalld支持端口转发(Port Forwarding),将一个端口的流量转发到另一台机器:

1
2
3
4
5
6
7
8
# 将本机的2222端口转发到另一台机器的22端口
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" forward-port port="2222" protocol="tcp" to-port="22" to-addr="192.168.1.200"'

# reload使配置生效
sudo firewall-cmd --reload

# 查看端口转发规则
sudo firewall-cmd --list-forward-ports
1
port=2222:proto=tcp:toport=22:toaddr=192.168.1.200

应用场景:内网服务器没有公网IP,通过有公网IP的跳板机做端口转发访问内网服务。


本章小结

本章我们掌握了CentOS/RHEL下firewalld防火墙的配置:

  • firewalld简介:红帽系Linux的动态防火墙,核心概念是Zone(区域)
  • Zone类型:drop(丢弃)、block(拒绝)、public(公共)、external(外部/NAT)、internal(内部)、trusted(信任)
  • firewall-cmd:firewalld的命令行管理工具
  • –list-all:查看所有规则
  • –add-port / –remove-port:开放/关闭端口
  • –add-service / –remove-service:按服务名放行/关闭
  • –permanent:使配置永久生效(生产环境必备)
  • –reload:重新加载配置使永久规则生效
  • rich-rule:高级规则,支持按IP放行、端口转发等复杂场景

firewalld的Zone+Service+Rich Rule三层配置,足够应付绝大多数生产环境需求。

最后修改 March 24, 2026: 新增JavaScript教程 (37305c4)