防火墙是一种用于监视和过滤传入和传出网络流量的技术。它通过定义一组安全规则来确定是允许还是阻止特定流量。正确配置防火墙是整个系统安全的最重要方面之一。防火墙可以及时发现和处理系统存在的安全风险,并保护数据传输的安全。
FirewallD 是 nftables 或 iptables 数据过滤系统的前端,可以帮助用户更容易地管理 iptables 规则,但它并不是 iptables 的替代品。虽然 iptables 命令仍可用于 FirewallD,但建议使用 FirewallD 时仅使用 FirewallD 命令。
通过本文,我们将向您介绍如何在 CentOS 8 上配置和管理防火墙,以及其基本的配置步骤。
环境配置
本教程基于一台运行 CentOS 8 的服务器,以及服务器上具有 sudo 权限的非 root 用户身份。
firewalld 的基本概念
在开始介绍如何实际使用 firewall-cmd
来管理和配置 Firewalld 之前,我们先了解一些 Firewalld 的基本概念。
区域(Zones)
Firewalld 所定义的区域(Zones)是一组规则集,根据所在网络信任级别的不同,规定应该允许哪些流量和拒绝哪些流量。不同的区域有不同的规则和安全要求,根据区域所定义的规则来管理和控制流量。同时,不同的网络接口被分配不同的区域,来指示防火墙应该允许哪些行为。
我们可以根据网络环境的不同设置或更改任何规则。对于公共网络,我们可以为防火墙配置较为严格的规则。而对于家庭网络,则不需要设置那么严格的规则。不管怎么样,熟悉 firewalld
的每个预定义区域背后的基本概念都是有必要的。
Firewalld
中的预定义区域从最不信任到最信任的顺序排列:
- drop:安全级别最低的区域。允许所有传出流量,禁止所有传入流量。
- block:几乎与 drop 区域相同,但会收到通知。
- public:表示公共的、不受信任的网络。除选定的传入连接被允许外,其余的传入请求会被拒绝。
- external:如果使用防火墙作为网关,则它用于网关的外部网络。它被配置为 NAT 伪装,可用于为 路由器启用了伪装功能的外部网络。
- internal:外部区域的另一侧,用于网关的内部部分。网络上的计算机通常是受信任的,只允许特定的传入连接。
- dmz:通常被称为隔离区或非军事区。对内部网络的访问权限有限,仅允许某些传入连接。
- work : 用于工作机器。网络中的大多数计算机是被信任的。可能会允许更多的服务。
- home:家庭环境。这通常意味着信任大多数计算机,并且会接受更多的服务。
- trusted:信任网络中的所有机器。最开放的选项,应谨慎使用。
要使用防火墙,我们可以创建规则并更改区域的属性,然后将我们的网络接口分配给最合适的区域。
永久性规则(Rule Permanence)和运行时规则(Runtime)
在 firewalld 中,有两种类型的规则集,分别为永久性规则(Rule Permanence)和运行时规则(Runtime)。
运行时规则指的是,当我们添加或更改规则集时,如果它仅对当下的防火墙有效,一旦重新加载 firewalld 服务或系统重启,配置的规则就会失效。
永久性规则指的是,只有在重新启动系统或重新加载 firewalld 服务后,才会使添加或更改的规则生效。
默认情况下,当使用 firewall-cmd
更改 Firewalld 配置时,这些更改将应用于运行时规则。要将规则添加到永久性规则中,需要在命令中附加 –permanent 选项。
要在两个配置集中应用更改,可以使用以下两种方法之一:
选择一:运行命令并更改运行时配置使其永久化:
sudo firewall-cmd <options>
sudo firewall-cmd --runtime-to-permanent
选择二:在命令中附加 –permanent 选项并重新加载 firewalld 进程:
sudo firewall-cmd --permanent <options>
sudo firewall-cmd --reload
这种运行时与永久配置的分离,可用于在活动防火墙中对规则进行测试,一旦出现问题只要重新加载就可以恢复原样了。
安装和启用 firewalld
在 CentOS 8 上,firewalld 已默认安装并启用。如果由于某种原因您的系统上没有安装,执行下面的命令安装 firewalld:
sudo dnf install firewalld
安装完成后,可以启用 firewalld 服务并重新启动服务器。启用了 firewalld 服务后,在下次系统启动时它会自动启动。
sudo systemctl enable firewalld
sudo systemctl start firewalld
在服务器重新启动后,防火墙应该已经被启动,服务器的网络接口应该被分配给配置的区域,并且与该区域关联的规则都将应用于关联的接口。
可以通过执行以下命令来验证 firewalld 服务是否正在运行:
sudo firewall-cmd --state
Output
running
这表明我们的防火墙已启动并默认配置运行。
熟悉当前的防火墙规则
在开始修改之前,我们应该熟悉一下 firewalld 提供的默认环境和规则。
了解默认配置
我们可以通过执行以下命令,来查看当前选择哪个区域作为默认区域:
firewall-cmd --get-default-zone
Output
public
由于我们没有向 firewalld 发出任何配置命令,并且接口也没有绑定到其他区域,因此 public 区域将是当前唯一的活动区域(控制我们接口流量的区域)。可以通过执行以下命令来验证:
firewall-cmd --get-active-zones
Output
public
interfaces: eth0 eth1
在这里,我们可以看到示例服务器有两个由防火墙控制的网络接口(eth0
和 eth1
)。它们目前都为公共区域定义的规则进行管理。
我们如何才能知道哪些规则与公共区域相关联呢?可以通过执行以下命令查询默认区域的配置:
sudo firewall-cmd --list-all
Output
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0 eth1
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
从输出中可以看出,public 区域既是默认区域又是活动区域,并且 eth0
和 eth1
接口与该区域相关联。但是,我们还可以看到,该区域允许 DHCP 客户端(用于 IP 地址分配)、SSH(用于远程管理)和 Cockpit(基于 Web 的控制台)的流量。
了解备选区域
在对默认和活动区域的配置有了基本的了解后。我们也可以进一步了解其他区域的信息。
要获取可用区域的列表,请执行下面的命令:
firewall-cmd --get-zones
Output
block dmz drop external home internal public trusted work
可以通过在 –list-all 命令中包含 --zone=
参数来查看与区域关联的配置:
sudo firewall-cmd --zone=home --list-all
Output
home
target: default
icmp-block-inversion: no
interfaces:
sources:
services: cockpit dhcpv6-client mdns samba-client ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
使用 --list-all-zones
可以输出所有区域,为了便于查看可以执行下面的命令:
sudo firewall-cmd --list-all-zones | less
接下来我们将了解如何将区域分配给网络接口。
为接口选择区域
默认情况下,在启动防火墙时,所有接口都被分配给默认区域。我们可以为不同的区域创建特定的规则集,并为它们分配不同的接口。
更改接口的区域
要更改网络接口的区域,可以使用 firewall-cmd 命令,将区域名称添加到 –zone 选项,将网络接口名称添加到 –change-interface 选项:
例如,我们可以通过键入以下命令将 eth0
接口分配给 Home 区域:
sudo firewall-cmd --zone=home --change-interface=eth0
Output
success
注意:当将接口分配给新区域时,你也在定义哪些服务可以运行。例如,这里我们将接口分配给 SSH 可用的 Home 区域。这意味着我们的 SSH 连接不应该断开。其他区域默认情况下不会启用 SSH,将接口分配到这些区域可能会导致 SSH 的连接断开,从而使您无法重新连接服务器。
我们可以通过再次检查活动区域来验证更改是否成功:
firewall-cmd --get-active-zones
Output
home
interfaces: eth0
public
interfaces: eth1
调整默认区域
如果您的所有接口都可以分配给某个区域进行处理,那么可以将该区域指定为默认区域。
可以使用 –set-default-zone= 参数更改默认区域。这回立即更改使用默认区域的所有接口:
sudo firewall-cmd --set-default-zone=home
Output
success
为应用程序设置规则
我们可以为应用程序配置防火墙并设置规则,下面来介绍一下如何将服务添加到区域。
将服务添加到您的区域
最直接的方法是将您需要的服务或端口添加到正在使用的区域。可以使用 –get-services 选项获取可用服务定义的列表:
firewall-cmd --get-services
Output
RH-Satellite-6 amanda-client amanda-k5-client amqp amqps apcupsd audit bacula bacula-client bb bgp bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc bittorrent-lsd ceph ceph-mon cfengine cockpit condor-collector ctdb dhcp dhcpv6 dhcpv6-client distcc dns dns-over-tls docker-registry docker-swarm dropbox-lansync elasticsearch etcd-client etcd-server finger freeipa-4 freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master git grafana gre high-availability http https imap imaps ipp ipp-client ipsec irc ircs iscsi-target isns jenkins kadmin kdeconnect kerberos kibana klogin kpasswd kprop kshell ldap ldaps libvirt libvirt-tls lightning-network llmnr managesieve matrix mdns memcache minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nfs nfs3 nmea-0183 nrpe ntp nut openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole plex pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy prometheus proxy-dhcp ptp pulseaudio puppetmaster quassel radius rdp redis redis-sentinel rpc-bind rsh rsyncd rtsp salt-master samba samba-client samba-dc sane sip sips slp smtp smtp-submission smtps snmp snmptrap spideroak-lansync spotify-sync squid ssdp ssh steam-streaming svdrp svn syncthing syncthing-gui synergy syslog syslog-tls telnet tentacle tftp tftp-client tile38 tinc tor-socks transmission-client upnp-client vdsm vnc-server wbem-http wbem-https wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server
注意:您可以通过查看 /usr/lib/firewalld/services
目录中,每个服务的关联的 .xml 文件来获取更多详细信息。例如,SSH 服务的定义如下:
/usr/lib/firewalld/services/ssh.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>SSH</short>
<description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
<port protocol="tcp" port="22"/>
</service>
您可以使用 --add-service=
参数为区域启用服务。该操作将针对默认区域或 --zone=
参数指定的区域。默认情况下,这只会调整当前的防火墙会话。可以通过包含 --permanent
选项进行永久防火墙配置。
例如,如果我们正在运行一个为常规 HTTP 流量提供服务的 Web 服务器,可以通过执行以下命令,暂时允许该流量用于公共区域中的接口:
sudo firewall-cmd --zone=public --add-service=http
如果您想修改默认区域,可以省略 –zone= 标志。我们可以使用 --list-all
或者 --list-services
来验证操作是否成功:
sudo firewall-cmd --zone=public --list-services
Output
cockpit dhcpv6-client http ssh
如果测试一切正常,可能需要修改永久防火墙规则,以便服务在重新启动后仍然可用。我们可以通过重新执行并添加--permanent
参数来使之前的更改永久化:
sudo firewall-cmd --zone=public --add-service=http --permanent
Output
success
或者,可以使用 --runtime-to-permanent
选项,将当前运行的防火墙配置保存到永久配置:
sudo firewall-cmd --runtime-to-permanent
这里需要注意的是,对正在运行的防火墙的所有更改都将永久生效。
无论选择哪种方法,您都可以通过在 --list-services
操作中添加 --permanent
选项来验证它是否成功。
sudo firewall-cmd --zone=public --list-services --permanent
Output
cockpit dhcpv6-client http ssh
现在,您的 public 区域将允许 80 端口上的 HTTP Web 流量。如果 Web 服务器已配置为使用 SSL/TLS,您还需要添加 https
服务。可以通过执行下面的命令将其添加到运行时规则集和永久规则集:
sudo firewall-cmd --zone=public --add-service=https
sudo firewall-cmd --zone=public --add-service=https --permanent
没有合适的服务怎么办?
firewalld 中包含了许多最常见的应用服务。但是,在某些情况下,这些服务可能不符合您的要求。在这种情况下,您有两种选择。
为区域开放一个端口
添加对特定应用程序的支持的最简单方法,是打开它在区域中使用的端口。这是通过指定端口或端口范围以及端口的关联协议(TCP 或 UDP)来完成的。
例如,如果应用程序在端口 5000 上运行并使用 TCP,我们可以使用 –add-port= 参数将其临时添加到公共区域。协议可以指定为 tcp
或 udp
:
sudo firewall-cmd --zone=public --add-port=5000/tcp
Output
success
我们可以使用 –list-ports 操作验证更改是否成功:
sudo firewall-cmd --zone=public --list-ports
Output
5000/tcp
还可以通过用破折号来指定端口的顺序范围。例如,如果我们的应用程序使用 UDP 端口 4990 到 4999,我们可以通过执行以下命令在 public 区域上打开它们:
sudo firewall-cmd --zone=public --add-port=4990-4999/udp
测试成功后,我们将配置添加到防火墙的永久规则集中。使用 sudo firewall-cmd –runtime-to-permanent 命令执行此操作,或附加 --permanent
选项重新运行命令:
sudo firewall-cmd --zone=public --permanent --add-port=5000/tcp
sudo firewall-cmd --zone=public --permanent --add-port=4990-4999/udp
sudo firewall-cmd --zone=public --permanent --list-ports
Output
success
success
5000/tcp 4990-4999/udp
定义服务
为区域打开端口是一个简单的解决方案,但可能很难跟踪每个端口的用途。如果您停用了服务器上的某个服务,可能很难记住其对应的端口是哪个。为了避免这种情况,我们可以定义一个新的服务。
服务是端口及与其关联的名称和描述的集合。使用服务比端口更容易管理,但需要一些前期工作。最简单的方法是将现有脚本(在 /usr/lib/firewalld/services 中查找)复制到 /etc/firewalld/services
目录。
例如,我们可以将 SSH 服务定义文件,复制到 example 服务定义文件中。在下面的示例中,example 就是新定义的服务名称:
sudo cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/example.xml
现在,调整 example.xml 服务定义文件。使用您喜欢的文本编辑器中打开它:
sudo vi /etc/firewalld/services/example.xml
首先,该文件包含复制的 SSH 定义:
/etc/firewalld/services/example.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>SSH</short>
<description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
<port protocol="tcp" port="22"/>
</service>
实际上这个定义的大部分是元数据。您需要更改<short>
标签中服务的名称,这是服务的可读名称。还应该添加描述,以便在需要审核服务时获得更多信息。这里要做的唯一真正影响服务功能的配置,就是定义端口,可以在其中标识要打开的端口号和协议。<port/>
可以指定多个标签。
对于 example 服务,假设我们需要为 TCP 开放 7777 端口,为 UDP 开放 8888 端口。我们可以像这样修改:
/etc/firewalld/services/example.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>Example Service</short>
<description>This is just an example service. It probably shouldn't be used on a real system.</description>
<port protocol="tcp" port="7777"/>
<port protocol="udp" port="8888"/>
</service>
保存并关闭文件。
重新加载防火墙以访问新的 example 服务:
sudo firewall-cmd --reload
现在可以看到它位于可用服务列表中:
firewall-cmd --get-services
Output
RH-Satellite-6 amanda-client amanda-k5-client amqp amqps apcupsd audit bacula bacula-client bb bgp bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc bittorrent-lsd ceph ceph-mon cfengine cockpit condor-collector ctdb dhcp dhcpv6 dhcpv6-client distcc dns dns-over-tls docker-registry docker-swarm dropbox-lansync elasticsearch etcd-client etcd-server example finger freeipa-4 freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master git grafana gre high-availability http https imap imaps ipp ipp-client ipsec irc ircs iscsi-target isns jenkins kadmin kdeconnect kerberos kibana klogin kpasswd kprop kshell ldap ldaps libvirt libvirt-tls lightning-network llmnr managesieve matrix mdns memcache minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nfs nfs3 nmea-0183 nrpe ntp nut openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole plex pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy prometheus proxy-dhcp ptp pulseaudio puppetmaster quassel radius rdp redis redis-sentinel rpc-bind rsh rsyncd rtsp salt-master samba samba-client samba-dc sane sip sips slp smtp smtp-submission smtps snmp snmptrap spideroak-lansync spotify-sync squid ssdp ssh steam-streaming svdrp svn syncthing syncthing-gui synergy syslog syslog-tls telnet tentacle tftp tftp-client tile38 tinc tor-socks transmission-client upnp-client vdsm vnc-server wbem-http wbem-https wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server
现在就可以像之前一样在区域中使用此服务了。
创建自定义区域
虽然预定义的区域对大多数用户来说已经足够了,但是 Firewalld 还允许您创建自己的区域。
例如,您可能想为 Web 服务器创建一个名为 publicweb 的区域。然后为专用网络上提供的 DNS 服务配置另一个 “privateDNS” 区域。
添加区域时,必须将其添加到永久防火墙配置中。然后,重新加载以将配置载入正在运行的会话中。例如,我们可以通过执行下面的命令来创建上述的两个区域:
sudo firewall-cmd --permanent --new-zone=publicweb
sudo firewall-cmd --permanent --new-zone=privateDNS
通过执行以下命令来验证更改是否存在于永久配置中:
sudo firewall-cmd --permanent --get-zones
Output
block dmz drop external home internal privateDNS public publicweb trusted work
如前所述,这些在防火墙的运行时规则集中尚不可用:
firewall-cmd --get-zones
Output
block dmz drop external home internal public trusted work
重新加载防火墙以应用配置:
sudo firewall-cmd --reload
firewall-cmd --get-zones
Output
block dmz drop external home internal privateDNS public publicweb trusted work
现在,便可以开始为创建的区域分配适当的服务和端口。最好先添加到运行时规则,测试后再将这些更改保存到永久配置中。例如,对于 publicweb 区域,为其添加 SSH、HTTP 和 HTTPS 服务:
sudo firewall-cmd --zone=publicweb --add-service=ssh
sudo firewall-cmd --zone=publicweb --add-service=http
sudo firewall-cmd --zone=publicweb --add-service=https
sudo firewall-cmd --zone=publicweb --list-all
Output
publicweb
target: default
icmp-block-inversion: no
interfaces:
sources:
services: http https ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
同样,将 DNS 服务添加到 privateDNS 区域:
sudo firewall-cmd --zone=privateDNS --add-service=dns
sudo firewall-cmd --zone=privateDNS --list-all
Output
privateDNS
target: default
icmp-block-inversion: no
interfaces:
sources:
services: dns
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
然后将网络接口分配给这些新区域来测试它们:
sudo firewall-cmd --zone=publicweb --change-interface=eth0
sudo firewall-cmd --zone=privateDNS --change-interface=eth1
如果测试没有问题,再将这些规则添加到永久配置中。可以通过附加 –permanent 标志再次运行所有命令来做到这一点。但是执行下面的命令,可以直接将更改添加到永久配置中:
sudo firewall-cmd --runtime-to-permanent
将更改添加到永久规则集后,重新加载防火墙以测试更改是否仍然存在:
sudo firewall-cmd --reload
验证是否分配了正确的区域:
firewall-cmd --get-active-zones
Output
privateDNS
interfaces: eth1
publicweb
interfaces: eth0
验证两个区域是否可以使用相应的服务:
sudo firewall-cmd --zone=publicweb --list-services
Output
http https ssh
sudo firewall-cmd --zone=privateDNS --list-services
Output
dns
经过上面的操作,就已成功创建了自定义区域。如果想要将自定义区域设置为默认区域,可以执行下面的命令:
sudo firewall-cmd --set-default-zone=publicweb
总结
经过本文的介绍,您应该已经对 firewalld 有了更进一步的了解。
作者:牛奇网,本站文章均为辛苦原创,在此严正声明,本站内容严禁采集转载,面斥不雅请好自为之,本文网址:https://www.niuqi360.com/linux/how-to-configure-and-manage-firewall-on-centos-8/