CentOS7下Firewall的设置与使用

防火墙 firewalld 守护服务引入了一个信任级别的概念来管理与之相关联的连接与接口。它支持 ipv4 与 ipv6,并支持网桥,采用 firewall-cmd (command) 或 firewall-config (gui) 来动态的管理 kernel netfilter 的临时或永久的接口规则,并实时生效而无需重启服务。

[译]CentOS7下Firewall的设置与使用
原文出处:How To Set Up a Firewall Using FirewallD on CentOS 7
原本作者:Justin Ellingwood
译者:wylu

如何在CentOS7上使用FirewallD设置防火墙

简介

Firewalld 是可用于许多 Linux 发行版的防火墙管理解决方案,它充当 Linux 内核提供的 iptables 数据包过滤系统的前端。在本指南中,我们将介绍如何为服务器设置防火墙,并向您展示使用 firewall-cmd 管理工具管理防火墙的基本知识(如果您希望在 CentOS中 使用 iptables,请遵循本指南)。

注意:有可能您正在使用比撰写本文时可用的新版本的 firewalld,或者您的服务器设置与本指南中使用的示例服务器略有不同。因此,本指南中说明的某些命令的行为可能会因您的特定配置而异。

Firewalld中的基本概念

在开始讨论如何实际使用 firewall-cmd 实用程序来管理防火墙配置之前,我们应该熟悉该工具引入的一些基本概念。

Zones

firewalld 守护程序使用称为 "zones" 的实体管理规则组。区域基本上是一组规则,它们决定了允许哪些流量,具体取决于您对计算机所连接的网络的信任程度。为网络接口分配了一个区域,以指示防火墙应允许的行为。

对于可能经常在网络之间移动的计算机(例如笔记本电脑),这种灵活性提供了一种根据环境更改规则的好方法。在公共WiFi网络上运行时,您可能有严格的规则禁止大多数流量,而在连接到家庭网络时允许放宽限制。对于服务器来说,这些区域并不是那么重要,因为网络环境很少更改(如果有的话)。

无论您的网络环境有多动态,熟悉防火墙的每个预定义区域背后的一般概念仍然很有用。按从 最不信任最受信任 的顺序,firewalld 中的预定义区域为:

  • drop:最低级别的信任。所有传入的连接都将被丢弃而不会回复,并且只能进行传出连接。
  • block:与上述类似,但不仅仅是丢弃连接,而是使用 icmp-host-prohibitedicmp6-adm-prohibited 消息拒绝传入的请求。
  • public:代表公共的,不受信任的网络。您不信任其他计算机,但可能会视情况允许选择的传入连接。
  • external:如果您使用防火墙作为网关,则为外部网络。将其配置为伪装NAT,以便您的内部网络保持私有但可访问。
  • internal:外部区域的另一侧,用于网关的内部。这些计算机相当值得信赖,并且可以使用一些其他服务。
  • dmz:用于DMZ中的计算机(将无法访问网络其余部分的隔离计算机)。仅允许某些传入连接。
  • work:用于工作机。信任网络中的大多数计算机。可能还允许其他一些服务。
  • home:家庭环境。通常,这意味着您信任其他大多数计算机,并且将接受其他一些服务。
  • trusted:信任网络中的所有计算机。可用选项中最开放的,应谨慎使用。

要使用防火墙,我们可以创建规则并更改区域的属性,然后将网络接口分配给最合适的区域。

规则永久性

在 firewalld 中,可以将规则指定为 永久规则立即规则。如果添加或修改规则,则默认情况下,将修改当前运行的防火墙的行为。在下次启动时,旧规则将恢复。

大多数 firewall-cmd 操作都可以使用 --permanent 标志来指示应将非临时防火墙作为目标。这将影响在引导时重新加载的规则集。这种分离意味着您可以在活动的防火墙实例中测试规则,然后在出现问题时重新加载。您还可以使用 --permanent 标志随着时间的推移建立一套完整的规则,这些规则将在发出 reload 命令时立即应用。

安装并启用防火墙以在启动时启动

默认情况下,firewalld 是在某些 Linux 发行版上安装的,包括许多 CentOS 7 映像。但是,您可能需要自己安装 firewalld:

1
$ sudo yum install firewalld

安装 firewalld 之后,您可以启用该服务并重新启动服务器。请记住,启用 firewalld 将导致该服务在服务器启动时启动。最佳实践是在配置此行为之前创建防火墙规则并借此机会对其进行测试,以避免潜在的问题。

1
2
$ sudo systemctl enable firewalld
$ sudo reboot

服务器重新启动时,防火墙会随之启动,然后将网络接口放入配置的区域(或退回到配置的默认区域),并且与该区域关联的所有规则都将应用于关联的接口。

我们可以通过键入以下内容来验证该服务正在运行并且可以访问:

1
2
$ sudo firewall-cmd --state
running

这表明我们的防火墙已启动并以默认配置运行。

熟悉当前的防火墙规则

在开始进行修改之前,我们应该熟悉守护程序提供的默认环境和规则。

探索默认值

通过键入以下内容,可以看到当前选择哪个区域作为默认区域:

1
2
$ firewall-cmd --get-default-zone
public

由于我们没有给 firewalld 提供任何偏离默认区域的命令,并且我们的接口都没有配置为绑定到另一个区域,因此该区域(public 区域)也将是唯一的“活动”(active)区域(该区域正在控制我们接口的流量)。我们可以通过输入以下内容进行验证:

1
2
3
$ firewall-cmd --get-active-zones
public
interfaces: eth0 eth1

在这里,我们可以看到示例服务器具有两个受防火墙控制的网络接口( eth0eth1 )。目前,它们都根据为 public 区域定义的规则进行管理。

我们如何知道与 public 区域相关的规则? 我们可以通过输入以下内容来打印默认区域的配置:

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

从输出中可以看出,该区域既是默认区域(default zone)又是活动区域(active zone),并且 eth0eth1 接口与此区域相关联(我们已经从之前的查询中了解了所有这些信息)。但是,我们还可以看到,该区域允许与 DHCP 客户端(用于 IP 地址分配)和 SSH(用于远程管理)相关的正常操作。

探索可选区域

现在,我们对默认区域和活动区域的配置有了一个好主意。我们还可以找到有关其他区域的信息。

要获取可用区域的列表,请输入:

1
2
$ firewall-cmd --get-zones
block dmz drop external home internal public trusted work

通过在 --list-all 命令中指定 --zone 参数,可以看到与指定区域关联的特定配置:

1
2
3
4
5
6
7
8
9
10
$ sudo firewall-cmd --zone=home --list-all
home
interfaces:
sources:
services: dhcpv6-client ipp-client mdns samba-client ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:

您可以使用 --list-all-zones 选项输出所有区域定义。您可能希望将输出通过管道传到 pager 中以便于查看:

1
$ sudo firewall-cmd --list-all-zones | less

为接口选定区域

除非另外配置了网络接口,否则在启动防火墙时,每个接口都将置于默认区域中。

更改接口区域

通过将 --zone 参数与 --change-interface 参数结合使用,可以在会话期间在区域之间转换接口。与所有修改防火墙的命令一样,您将需要使用 sudo。

例如,我们可以通过输入以下命令将 eth0 接口转换为 "home" 区域:

1
2
$ sudo firewall-cmd --zone=home --change-interface=eth0
success

注意:每当将接口转换到新区域时,请注意您可能正在修改将要运行的服务。例如,在这里,我们将移至具有 SSH 可用的 "home" 区域。这意味着我们的连接不应断开。其他一些区域默认情况下未启用 SSH,如果在使用这些区域之一时断开连接,您可能会发现自己无法重新登录。

我们可以通过再次请求活动区域来验证此操作是否成功:

1
2
3
4
5
$ firewall-cmd --get-active-zones
home
interfaces: eth0
public
interfaces: eth1

调整默认区域

您最好用一个区域来处理所有接口,这样选择最佳的默认区域然后将其用于配置可能会更容易。

您可以使用 --set-default-zone 参数更改默认区域。这将立即将所有使用默认值的接口更改为新区域:

1
2
$ sudo firewall-cmd --set-default-zone=home
success

为您的应用程序设置规则

为希望提供的服务定义防火墙例外的基本方法很容易。我们将在此处介绍基本概念。

将服务添加到您的区域

最简单的方法是将所需的服务或端口添加到正在使用的区域。同样,您可以使用 --get-services 选项获取可用服务的列表:

1
2
$ firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine condor-collector ctdb dhcp dhcpv6 dhcpv6-client dns docker-registry dropbox-lansync elasticsearch freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master high-availability http https imap imaps ipp ipp-client ipsec iscsi-target kadmin kerberos kibana klogin kpasswd kshell ldap ldaps libvirt libvirt-tls managesieve mdns mosh mountd ms-wbt mssql mysql nfs nrpe ntp openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster quassel radius rpc-bind rsh rsyncd samba samba-client sane sip sips smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server

注意:您可以通过查看 /usr/lib/firewalld/services 目录中与它们相关的 .xml 文件来获得有关每个服务的更多详细信息。例如,SSH 服务(/usr/lib/firewalld/services/ssh.xml)的定义如下:

1
2
3
4
5
6
<?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 服务器,则可以通过键入以下内容在此会话的 "public" 区域中为接口允许此流量:

1
$ sudo firewall-cmd --zone=public --add-service=http

如果要修改默认区域,可以省略 --zone。我们可以使用 --list-all--list-services 操作来验证操作是否成功:

1
2
$ sudo firewall-cmd --zone=public --list-services
dhcpv6-client http ssh

测试完所有功能后,您可能需要修改永久防火墙规则,以便重新启动后您的服务仍然可用。我们可以通过输入以下内容使 "public" 区域更改永久生效:

1
2
$ sudo firewall-cmd --zone=public --permanent --add-service=http
success

您可以通过在 --list-services 操作中添加 --permanent 标志来验证此操作是否成功。您需要对任何 --permanent 操作使用sudo:

1
2
$ sudo firewall-cmd --zone=public --permanent --list-services
dhcpv6-client http ssh

您的 "public" 区域现在将允许端口 80 上的 HTTP Web 通信。如果您的 Web 服务器配置为使用 SSL/TLS,则还需要添加 https 服务。我们可以通过输入以下内容将其添加到当前会话和永久规则集中:

1
2
$ sudo firewall-cmd --zone=public --add-service=https
$ sudo firewall-cmd --zone=public --permanent --add-service=https

如果没有适当的服务可用怎么办

防火墙安装中包含的防火墙服务代表了您可能希望允许访问的应用程序的许多最常见要求。但是,在某些情况下,这些服务可能无法满足您的要求。

在这种情况下,您有两个选择。

为您的区域打开端口

为您的特定应用程序添加支持的最简单方法是打开它在相应区域中使用的端口。这就像指定端口或端口范围以及需要打开的端口的关联协议一样容易。

例如,如果我们的应用程序在端口 5000 上运行并使用 TCP,则可以使用 --add-port 参数将其添加到此会话的 "public" 区域中。协议可以是 tcp 或 udp:

1
2
$ sudo firewall-cmd --zone=public --add-port=5000/tcp
success

我们可以使用 --list-ports 操作验证此操作是否成功:

1
2
$ sudo firewall-cmd --zone=public --list-ports
5000/tcp

也可以通过用 - 分隔范围内的开始和结束端口来指定顺序的端口范围。例如,如果我们的应用程序使用 UDP 端口 4990 至 4999,则可以通过键入以下内容在 "public" 端口上打开这些端口:

1
$ sudo firewall-cmd --zone=public --add-port=4990-4999/udp

经过测试后,我们可能希望将它们添加到永久防火墙中。您可以通过键入以下内容进行操作:

1
2
3
4
5
6
$ sudo firewall-cmd --zone=public --permanent --add-port=5000/tcp
success
$ sudo firewall-cmd --zone=public --permanent --add-port=4990-4999/udp
success
$ sudo firewall-cmd --zone=public --permanent --list-ports
5000/tcp 4990-4999/udp

定义服务

为您的区域打开端口很容易,但是很难跟踪每个区域的用途。如果您曾经停用服务器上的服务,则可能很难记住仍需要打开哪些端口。为了避免这种情况,可以定义服务。

服务只是带有相关名称和描述的端口的简单集合。使用服务比端口更易于管理,但是需要一些前期工作。最简单的开始方法是将现有脚本(在 /usr/lib/firewalld/services 中找到)复制到 /etc/firewalld/services 目录中,防火墙在该目录中查找非标准定义。

例如,我们可以复制 SSH 服务定义以用于我们的 "example" 服务定义,如下所示。文件名减去 .xml 后缀将指示防火墙服务列表中的服务名称:

1
$ sudo cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/example.xml

现在,您可以调整在复制的文件中找到的定义:

1
$ sudo vi /etc/firewalld/services/example.xml

首先,文件将包含您复制的 SSH 定义:

1
2
3
4
5
6
<?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> 标记内更改服务的简称。这是您的服务的易读名称。您还应该添加描述,以便在需要审核服务时获得更多信息。您需要进行的实际上会影响服务功能的唯一配置可能是端口定义,您可以在其中定义要打开的端口号和协议。可以多次指定。

对于我们的 "example" 服务,假设我们需要为 TCP 打开端口 7777,为 UDP 打开端口 8888。通过按 i 进入 INSERT 模式,我们可以使用以下内容修改现有定义:

1
2
3
4
5
6
7
<?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>

按 ESC,然后输入 :x 保存并关闭文件。

重新加载防火墙以访问新服务:

1
$ sudo firewall-cmd --reload

您可以看到它现在在可用服务列表中:

1
2
$ firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine condor-collector ctdb dhcp dhcpv6 dhcpv6-client dns docker-registry dropbox-lansync elasticsearch example freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master high-availability http https imap imaps ipp ipp-client ipsec iscsi-target kadmin kerberos kibana klogin kpasswd kshell ldap ldaps libvirt libvirt-tls managesieve mdns mosh mountd ms-wbt mssql mysql nfs nrpe ntp openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster quassel radius rpc-bind rsh rsyncd samba samba-client sane sip sips smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server

现在,您可以像往常一样在您的区域中使用此服务。

创建自己的区域

尽管预定义的区域对于大多数用户来说可能绰绰有余,但是定义自己的区域来描述其功能可能会有所帮助。

例如,您可能要为 Web 服务器创建一个名为 "publicweb" 的区域。或者,您可能希望为您在专用网络上提供的 DNS 服务配置另一个区域,您可能需要一个名为 "privateDNS" 的区域。

添加区域时,必须将其添加到永久防火墙配置中。然后,您可以重新加载以将配置带入正在运行的会话。例如,我们可以通过键入以下内容来创建我们上面讨论的两个区域:

1
2
$ sudo firewall-cmd --permanent --new-zone=publicweb
$ sudo firewall-cmd --permanent --new-zone=privateDNS

您可以通过键入以下内容来验证这些内容是否存在于您的永久配置中:

1
2
$ sudo firewall-cmd --permanent --get-zones
block dmz drop external home internal privateDNS public publicweb trusted work

如前所述,这些功能在当前的防火墙实例中尚不可用:

1
2
$ firewall-cmd --get-zones
block dmz drop external home internal public trusted work

重新加载防火墙以使这些新区域进入活动配置:

1
2
3
$ sudo firewall-cmd --reload
$ firewall-cmd --get-zones
block dmz drop external home internal privateDNS public publicweb trusted work

现在,您可以开始为您的区域分配适当的服务和端口。通常,最好先调整活动实例,然后在测试后将这些更改转移到永久配置中。例如,对于 "publicweb" 区域,您可能想要添加 SSH,HTTP 和 HTTPS 服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ 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
publicweb
target: default
icmp-block-inversion: no
interfaces:
sources:
services: ssh http https
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

同样地,我们可以将 DNS 服务添加到我们的 "privateDNS" 区域:

1
2
3
4
5
6
7
8
9
10
11
$ sudo firewall-cmd --zone=privateDNS --add-service=dns
$ sudo firewall-cmd --zone=privateDNS --list-all
privateDNS
interfaces:
sources:
services: dns
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:

然后,我们可以将网络接口更改为这些新区域以对其进行测试:

1
2
$ sudo firewall-cmd --zone=publicweb --change-interface=eth0
$ sudo firewall-cmd --zone=privateDNS --change-interface=eth1

此时,您将有机会测试您的配置。如果这些值对您有用,您将要向永久配置添加相同的规则。您可以通过使用 --permanent 标志重新应用规则来做到这一点:

1
2
3
4
$ sudo firewall-cmd --zone=publicweb --permanent --add-service=ssh
$ sudo firewall-cmd --zone=publicweb --permanent --add-service=http
$ sudo firewall-cmd --zone=publicweb --permanent --add-service=https
$ sudo firewall-cmd --zone=privateDNS --permanent --add-service=dns

在永久应用了这些规则之后,您可以重新启动网络并重新加载防火墙服务:

1
2
$ sudo systemctl restart network
$ sudo systemctl reload firewalld

验证是否分配了正确的区域:

1
2
3
4
5
$ firewall-cmd --get-active-zones
privateDNS
interfaces: eth1
publicweb
interfaces: eth0

并验证相应的服务可用于两个区域:

1
2
3
4
$ sudo firewall-cmd --zone=publicweb --list-services
http https ssh
$ sudo firewall-cmd --zone=privateDNS --list-services
dns

您已经成功设置了自己的区域! 如果要将这些区域之一设为其他接口的默认区域,请记住使用 --set-default-zone 参数配置该行为:

1
$ sudo firewall-cmd --set-default-zone=publicweb

总结

您现在应该对如何在 CentOS 系统上日常使用的防火墙服务进行充分的了解。

Firewalld 服务允许您配置考虑网络环境的可维护规则和规则集。它使您可以通过使用区域在不同的防火墙策略之间无缝过渡,并使管理员能够将端口管理抽象为更友好的服务定义。掌握该系统的使用知识将使您能够利用此工具提供的灵活性和强大功能。