Chapter4 - 网络端口安全性
管理 firewalld
Firewalld 概述
firewalld
是 RHEL 7 中用于管理主机级别防火墙的默认方法。firewalld
通过 firewalld.service
, systemd
服务来启动,可使用低级别的 iptables
、ip6tables
和 ebtables
命令管理 Linux 内核netfilter
子系统。
注意
firewalld.service 和 iptables.service 以及ip6tables.service 和ebtables.service 服务彼此冲突。为了防止意外启动其中一个 *tables.service 服务(并擦除流程中任何正在运行的防火墙配置),使用 systemctl 将其屏蔽是一种不错的做法。
[root@server ~]# for SERVICE in iptables ip6tables ebtables;do
> systemctl unmask ${SERVICE}.service
> done
[root@server ~]#
firewalld
将所有传入流量划分成区域,每个区域都具有自己的一套规则。为检查哪个区域用于传入连接,firewalld
使用以下逻辑,第一个匹配的规则胜出:
- 如果传入包的源地址民区域的某个源规则设置相匹配,该包将通过该区域进行路由。
- 如果包的传入接口与区域的过滤器设置匹配,则将使用该区域。
- 否则将使用默认区域。默认区域不是单独的区域,而是指向系统上定义的某个其他区域。
除非被管理员 NetworkManager 配置所覆盖,否则,任何新网络接口的默认区域都将设置为 public
区域。
firewalld
随附了一些预定义区域,每个都有自己的指定用途:
firewalld 区域默认配置
区域名称 | 默认配置 |
---|---|
trusted | 允许所有传入流量 |
home | 除非与传出流量相关,或与 ssh,mdns,ipp-client,samba-client 或 dhcpv6-client 预定义服务匹配,否则拒绝传入流量。 |
internal | 除非与传出流量相关,或与ssh,mdns,ipp-client,samba-client 或 dhcpv6-client 预定义服务匹配,否则拒绝传入流量(一开始与home 区域相同) |
work | 除非与传出流量相关,或与ssh,ipp-client 或 dhcpv6-client 预定义服务匹配,否则拒绝传入流量。 |
public | 除非与传出流量相关,或与ssh, dhcpv6-client 预定义服务匹配,否则拒绝传入流量。新添加的网络接口的默认区域。 |
external | 除非与传出流量相关,或与ssh 预定义服务匹配,否则拒绝传入流量。通过此区域转发的 ipv4 传出流量将进行伪装,以使其看起来像是来自传出网络接口的ipv4 地址 |
dmz | 除非与传出流量相关,或与 ssh 预定义服务匹配,否则拒绝传入流量。 |
block | 除非与传出流量相关,否则拒绝所有传入流量。 |
drop | 除非与传出流量相关,否则丢弃所有传入流量(甚至不产生包含ICMP 错误的响应)。 |
管理firewalld
可以通过三种方式来管理 firewalld :
- 使用命令行工具
firewall-cmd
. - 使用图形工具
firewall-config
- 使用
/etc/firewalld/
的配置文件。
在大部分情况下,不建议直接编辑配置文件,但是在使用配置管理工具时,以这种方法复制配置会很有用。
使用 firewall-cmd 配置防火墙设置
firewall-cmd
作为主 firewalld 软件包的一部分安装。 firewall-cmd
可以执行 firewall-config
能够执行的相同操作。
下表列出一些常用 firewall-cmd
命令及其说明。请注意,除非另有指定,否则几乎所有命令都作用于运行时配置,当指定 –permanent
选项时除外。列出的许多命令都采用 –zone=<ZONE>
选项来确定所影响的区域。如果在这些命令中省略 –zone ,则将使用默认区域。
配置防火墙时,管理员通常会应用对 –permanent
配置的所有更改,然后使用 firewall-cmd –reload
来激活这些更改。测试新的并且可能有危险的规则时,管理员可以能完策略 –permanent
选项来选择使用运行时配置。在这些情况下,可以使用额外选项以在一定时间后自动删除某个规则,从而防止管理员意外锁定某个系统: –timeout=<TIMEINSECONDS>
firewall-cmd 命令 | 说明 |
---|---|
–get-default-zone | 查询当前默认区域 |
–set-default-zone=<ZONE> | 设置默认区域。此命令会同时更改运行时配置和永久配置。 |
–get-zones | 列出所有可用区域 |
–get-services | 列出所有可用服务 |
–get-acitve-zones | 列出当前正在使用的所有区域(具有关联的接口或源)及其接口和源信息。 |
–add-source=<CIDR> [–zone=<ZONE> ] | 将来自 IP 地址或网络/子网掩码 <CIDR> 的所有流量路由到指定区域。如果未提供 –zone= 选项,则将使用默认区域。 |
–remove-source=<CIDR> [–zone=<ZONE> ] | 从指定区域中删除用于路由来自 IP 地址或网络 /子网掩码 <CIDR> 的所有流量的规则。如果未提供 –zone= 选项,则将使用默认区域。 |
–add-interface=<INTERFACE> [–zone=<ZONE> ] | 将来自 <INTERFACE> 的所有流量路由到指定区域。如果未提供 –zone= 选项,则将使用默认区域。 |
–change-interface=<INTERFACE> [–zone=<ZONE> ] | 将接口与 <ZONE> 而其当前区域关联。如果未提供 –zone= 选项,则将使用默认区域。 |
–list-all [–zone=<ZONE> ] | 列出 <ZONE> 的所有已配置接口、源、服务和端口。如果未提供 –zone= 选项,则将使用默认区域。 |
–list-all-zones | 检索所有区域的所有信息(接口、源、端口、服务等等) |
–add-service=<SERVICE> | 允许到 <SERVICE> 的流量。如果未提供 –zone= 选项,则将使用默认区域。 |
–add-port=<PORT/PROTOCOL> | 允许到<PORT/PROTOCOL>端口的流量。如果未提供 –zone= 选项,则将使用默认区域。 |
–remove-service=<SERVICE> | 从允许列表中删除 <SERVICE> 。如果未提供 –zone= 选项,则将使用默认区域。 |
–remove-port=<PORT/PROTOCOL> | 从区域的允许列表中删除 <PORT/PROTOCOL>端口。如果未提供 –zone= 选项,则将使用默认区域。 |
–reload | 丢弃运行时配置并应用持久配置。 |
firewall-cmd示例
下例显示默认区域设置为 dmz
,来自 192.168.0.0/24 网络的所有流量都被分配给 internal
区域,而internal
区域上打开了用于mysql 的网络端口。
[root@server ~]# firewall-cmd --set-default-zone=dmz
success
[root@server ~]# firewall-cmd --permanent --zone=internal --add-source=192.168.0.0/24
success
[root@server ~]# firewall-cmd --permanent --zone=internal --add-port=3306/tcp
success
[root@server ~]# firewall-cmd --permanent --zone=internal --add-service=mysql
success
[root@server ~]# firewall-cmd --reload
success
[root@server ~]#
firewall 配置文件
firewall 配置文件存储在两个位置: /etc/firewalld
和 /usr/lib/firewalld
。如果相同名称的配置文件同时存储在两个位置中,则将使用 /etc/firewalld/
中的版本。这允许管理员覆盖默认区域和设置,而不必担心其更改被软件包更新所擦除。
管理富规则
富规则概念
除了firewalld 提供的常规区域和服务语法之外,管理员还有另外两种选项来添加防火墙规:直接规则和富规则 。
直接规则
直接规则允许管理员将手动编码的 {ip,ip6,eb}tables
规则插入到firewalld 管理的区域中。尽管这些规则很强大,并且暴露的内核 netfilter
子系统功能不会通过其他手段暴露,但可能难以管理。直接规则 所提供的灵活性也低于标准规则和富规则。对于已经熟悉了 {ip,ip6,eb}tables 的管理员,可以使用firewall-cmd(1)
和 firealld.direct(5)
man page
中的文档。
除非将直接规则显式插入到由 firewalld 管理的区域,否则将首先解析直接规,然后才解析任何 firewalld 规则 。
添加一些直接规则以将某个 ip 范列入黑名单简短示例:
[root@server ~]# firewall-cmd --direct --permanent --add-chain ipv4 raw blacklist
success
[root@server ~]# firewall-cmd --direct --permanent --add-rule ipv4 raw PREROUTING 0 -s 192.168.0.0/24 -j blacklist
success
[root@server ~]# firewall-cmd --direct --permanent --add-rule ipv4 raw blacklist 0 -m limit --limit 1/min -j LOG --log-prefix "blacklisted"
success
[root@server ~]# firewall-cmd --direct --permanent --add-rule ipv4 raw blacklist 1 -j DROP
success
[root@server ~]# firewall-cmd --direct #常用参数
usage: see firewall-cmd man page
firewall-cmd: error: ambiguous option:
--add could match
--add-rule, --add-module, --add-masquerade, --add-destination, --add-lockdown-whitelist-context,
--add-lockdown-whitelist-uid, --add-icmp-block-inversion, --add-lockdown-whitelist-user,
--add-service, --add-source, --add-source-port, --add-lockdown-whitelist-command, --add-rich-rule,
--add-protocol, --add-passthrough, --add-icmp-block, --add-interface, --add-forward-port, --add-entry,
--add-chain, --add-port, --add-entries-from-file
富规则
firewalld 富规则为管理员提供了一种表达性语言,通过这种语言可表达 firewalld 的基本语法中示涵盖的自定义防火墙规则 ;例如,仅允许从单个IP地址(而非通过某个区域路由的所有IP地址)连接到服务。
富规则可用于表达基本的允许/拒绝规则,但是也可以用于配置记录(面向syslog 和 auditd )以及端口转发、伪装和速率限制。
可能通过以下块来表达富规则的基本语法:
rule
[source]
[destination]
service|port|protocol|icmp-block|masquerade|forward-port
[log]
[audit]
[accept|reject|drop]
规则的几乎每个单一元素都能够以 option=value
形式来采用附加参数。
注意
有关富规则 的完整可用语法,请查阅 firewalld.richlanguage(5) man page
规则排序
一旦向某个区域(一般是指防火墙)中添加多个规则 ,规则的排序便会在很大程度上影响防火墙的行为。
对于所有区域,区域内规则的基本排序是相同的。
- 为该区域设置的任何商品转发和伪装规则。
- 为该区域设置的任何记录规则
- 为该区域设置的任何允许规则
- 为该区域的任何拒绝规则
在所有情况下,第一个匹配项都将胜出。如果区域中的任何规则与包 均不匹配,那么通常会拒绝该,但是区域可能具有不同默认值;例如,可信区域将接受任何不匹配的包。此外,在匹配某个记录规则后,将继续正常处理包。
直接规则是个例外。对于大部分直接规则,将首先进行解析,然后再由firewalld 进行任何其他处理,但是直接规则语法允许管理员在任何区域中的任何位置插入任何规则 。
测试和调试
为了便于测试和调试,几乎所有规则 都可以与超时一起添加到运行时配置。当包含超时的规则添加到防火墙时,计时器便针对该规则开始倒计时。一旦规则的计时器砍到零秒,便从运行时配置中删除该规则。
在使用远程防火墙时,使用超时会是一种极其有用的工具,特别是在调试更复杂的规则集时。如果规则有效,则管理员可以再次添加该规则,但使用 –permanent 选项(或者至少不包含超时)。如果规则没有按预期运行,甚至可能将管理员锁定而使其无法进入系统,那么规则将被自动删除,以允许管理员继续其工作。
通过在启用规则的 firewll-cmd 的结尾添加选项 –timeout=<TIMEINSECONDS>
,即可向运行时规则中添加超时。
使用富规则
firewall-cmd 有四个选项可用于处理富规则。所有的这些选项都可以与常规的–permanent
或 –zone=<ZONE>
选项结合使用。
选项 | 说明 |
---|---|
–add-rich-rule='<RULE> ' | 向指定区域中添加 <RULE> ,如果未指定区域,则向默认区域中添加。 |
–remove-rich-rule='<RULE> ' | 从指定区域中删除 <RULE> ,如果未指定区域,则从默认区域中删除 |
–query-rich-rule='<RULE> ' | 查询 <RULE> 是否已添加到控线区域,如果未指定区域,则为默认区域。如果规则存在,则返回0,否则返回1 |
–list-rich-rules | 输出指定区域的所有富规则,如果未指定区域,则为默认区域。 |
任何已配置的富规则还将显示在 firewall-cmd –list-all
和 firewall-cmd –list-all-zones
的输出中。
富规则示例
富规则的一些示例包括:
[root@server ~]# firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.0.11/32 reject'
success
拒绝来自 classroom 区域中ip 地址为 192.168.0.11 的所有流量
将 source 或 destination 与address 选项配合使用时, rule的 family=
选项必须设置为 ipv4 或者 ipv6 。
[root@server ~]# firewall-cmd --permanent --add-rich-rule='rule service name=ftp limit value=2/m accept'
success
在默认区域中,允许每分钟对ftp 有再次新连接。
[root@server ~]# firewall-cmd --permanent --add-rich-rule='rule protocol value=esp drop'
success
丢弃来自默认区域中任何位置的所有传入 IPsec esp
协议包。
注意
reject
与drop
之间的区别在于, reject
将发送回一个 ICMP
包,详细描述连接被拒绝以及原因drop
只是丢弃包,不进行任何其他操作。通常,管理员希望对于友好和中立网络使用reject,而仅对恶意网络使用 drop 。
[root@server ~]# firewall-cmd --permanent --zone=vnc --add-rich-rule='rule family=ipv4 source address=192.168.1.0/24 port port=7900-7905 protocol=tcp accept '
success
在 192.168.1.0/24 子网的 VNC 区域中,接受端口 7900直到7905(含)上的所有 TCP 包。
使用富规则进行记录
调试或监控防火墙时,记录接受或已拒绝连接很有用。firewalld 可以通过两种方法来实现些目的:记录到 syslog
,或将消息发送到由 auditd 管理的内核 audit 子系统。
在这两种情况下,记录可能会受到速率限制。速率限制确保系统日志文件填充消息的速率不会使系统无法跟上或者填充其所有磁盘空间。
使用富规则记录到syslog
的基本语法为:
log [prefix="<PREFIX TEXT >"|level=<LOGLEVEL >|][limit value="<rate/duration>"]
其中 <LOGLEVEL>
是 emerg,alert,cirt,error,warning,notice,info,or debug。
<DURATION>
可以是 ==s(秒),m(分),h(时),d(天)==之一。例如 limit value=3/m
会将日志消息限制为每分钟最多3条。
用于记录到审计子系统的基本语法为:
audit [limit value="<RATE/DURATION>"]
速率限制的配置方式为与 syslog
记录相同。
记录示例:
使用富规则进行记录的某些示例:
[root@server ~]# firewall-cmd --permanent --zone=work --add-rich-rule='rule service name="ssh" log prefix="ssh" limit value="3/m" level="notice" accept'
接受从work 区域到 ssh 的新连接,以 notice 级别且每分钟最多三条消息的方式将新连接记录到 syslog 。
[root@server ~]# firewall-cmd --add-rich-rule='rule family=ipv6 source address="2001:db8::/64" service name="dns" audit limit value="1/h" reject' --timeout=300
success
在接下来五分钟内,将拒绝从默认区域中子网2001:db8::/64
到 dns 的新ipv6 连接,并且拒绝的连接将记录到 audit 系统,且每小时最多一条消息。
伪装和端口转发
网络地址转换(NAT)
firewalld 支持两种类型的网络地址转换 (NAT):伪装和端口转发。可以在基本级别使用常规 firewall-cmd 规则来同时配置这两者,更高级别的转发配置可以使用富规则来完成。这两种形式的 NAT 会在发送包之前修改包的某些方面,如源或目标。
伪装
通过伪装,系统会将并非直接寻址的包转发到指定接收地方,同时将通过的包的源地址更改为其自己的公共IP地址,防火墙对这些传入的包应答时,会将目标地址修改为原始主机的地址并发送包。这通常在网络边缘上使用,以便为内部网络提供 Internet 访问 ,伪装是一种形式的网络地址转换(NAT)。
重要
伪装只能与IPv4 一起使用,不能与 ipv6 一起使用。

根据图4.1 :描述的网络布局,伪装运行方式的示例。
- 位于防火墙后面的一个计算机将包发送到本地网络之外的地址。包的源地址为 10.0.0.100(计算机的地址),目标地址为 2.17.39.214
- 由于目标地址不在本地子网中,包将路由到源计算机上配置的默认网关,在此情况下为 10.0.0.1 ,即防火墙的 ip 地址。
- 防火墙接受包,将源地址更改为 1.2.3.4 (防火墙的外部IP),将对此连接的引用存储在其连接状态表中,然后根据其路由表将包传递到Internet 上路由器。
- 对包的应答从 Internet 返回。路由器在其连接状态表中查找连接。然后将目标地址更改为 10.0.0.100 (原始必送方)并传递包。
- 原始发送方接收对其请求的应答。
配置伪装
要使用常规的 firewall-cmd 命令为区域配置伪装,请使用以下语法:
[root@server ~]# firewall-cmd --permanent --zone=dmz --add-masquerade
success
这将伪装满足以下条件的任何包:从该区域的源(接口及子网)中定义的客户端发送到防火墙,并且未寻址到防火墙自身。
要在更大程度控制要进行伪装的客户端,还可以使用富规则。
[root@server ~]# firewall-cmd --permanent --zone=dmz --add-rich-rule='rule family=ipv4 source address=192.168.0.0/24 masquerade'
success
端口转发
另一种形式的NAT是端口转发。通过端口转发,指向单个端口的流量将转发到相同的计算机上的不同端口,或者转发以不同计算机上的端口。此机制通常用于将某个服务器“隐藏”在另一个计算机后面,或者用于在备用端口上提供对服务的访问权限。
重要
当端口转发配置为将包转发到不同计算机时,从该计算机的任何回复通常将直接从该计算机发送到原始客户端。由于这将在大部分配置上导致无效连接,因此转发到计算机必须通过执行端口转发的防火墙来进行伪装。
常见配置是将端口从防火墙计算机转发到已在防火墙后面伪装的计算机。
根据图 4.1 :描述的网络布局,端口转发的示例。假定位于防火墙后面且IP地址为 10.0.0.100 的计算机在端口 8080/tcp 上运行web 服务器。并且防火墙配置为将其外部接口上传入端口 80/tcp 的流量转发到该计算机上的端口 8080/tcp 。
- 来自Internet 的客户端将包发送到防火墙的外部接口上的端口 80/tcp 。
- 防火墙将此包的目标地址和端口分别更改为 10.0.0.100 和 8080/tcp ,然后转发此包。源地址和端口保持不变。
- 防火墙后面的计算机将响应发送到此包。由于此计算机进行了伪装(并且防火墙配置为默认网关),此包会发送到原始客户端,就如同是来自防火墙上的外部接口。
配置端口转发
要使用常规 firewall-cmd 命令配置端口转发,请使用以下语法:
[root@server ~]# firewall-cmd --permanent --zone=<ZONE> --add-forward-port=port=<PORTNUMBER>:proto=<PROTCOL>[:toport=<PORTNUMBER>][:toaddr=<IP ADDR>]
toport=
和 toaddr=
部分可选,但需要至少指定这两者这一。
例如,对于来自 Public 区域客户端,以下命令会将防火墙上通过端口 513/tcp 传入,连接转发到 ip 地址为 192.168.0.254 的计算机上的端口 132/tcp :
[root@server ~]# firewall-cmd --permanent --zone=public --add-forward-port=port=513:proto=tcp:toport=132:toaddr=192.168.0.254
success
要在更大程序上控制端口转发规则,可以将以下语法与富规则配合使用:
forward-port port=<PORTNUM> protocol=tcp|udp [to-port=<portnum>][to-addr=<address>]
以下示例使用富规则将来自 work 区域中 192.168.0.0/26 且传入到端口80/tcp 的流量转发到防火墙计算机自身上面的端口 8080/tcp 。
[root@server ~]# firewall-cmd --permanent --zone=work --add-rich-rule='rule family=ipv4 source address=192.168.0.0/26 forwoard-port port=80 protocol=tcp to-port=8080'
管理 SElinux 端口标记
SElinux 端口标记
SElinux 不仅仅是进行文件和进程标记。SElinux 策略还严格实施网络流量。SElinux 用来控制网络流量的其中一种方法是标记网络端口;例如,在 targeted 策略中,端口 22/tcp 具有标签 ssh_port_t
与其相关联。
当某个进程希望侦听端口时,SElinux 将检查是否允许与该进程(域)相关联的标签绑定该端口标签。这可以阻止恶意服务控制本应由其他(合法)网络服务使用的端口。
管理 SElinux 端口标记
每当管理员决定非标准端口上运行服务时,SElinux 端口标签都很有可能需要进行更新。在某些情况下,targeted
策略已经通过可以使用的类型标记了端口;例如,由于端口 8008/tcp 通常用于 web 应用程序 ,此端口已经使用 http_port_t
(web 服务器的默认端口类型)进行标记。
侦听端口标签
要获取所有当前端口标签分配的概述,管理员可以使用 semanage
命令的 port
子命令。 -l
选项将以下形式列出所有当前分配:
port_label_t tcp|udp comma,separated,list,of,ports
要仅查看对默认策略的本地更改,管理员可以在此命令中添加 -C
选项。
输出示例:
[root@server ~]# semanage port -l
……
http_cache_port_t tcp 8080, 8118, 8123, 10001-10010
http_cache_port_t udp 3130
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989
……
请注意,一个端口标签可能会出现两次,一次是针对 tcp,一次是针对 udp
注意
还提供卫个图形工具,system-config-selinux ,以供更喜欢使用 GUI 工具的管理员使用,此工具包含在 policycoreutils-gui 软件包中。
管理端口标签
还可以使用 semanage
来分配新端口标签,删除端口标签或修改现有端口的标签。
注意
targeted 策略随附了大量端口类型。在 selinux-policy-devel 软件包的特定于服务的 SElinux man page 中可以找到相关 SELinux 类型、布尔值和端口类型相关的文档(按服务)。
如果您的系统上尚未安装这些 man page
,请遵循以下过程:
[root@server ~]# yum -y install selinux-policy-devel
[root@server ~]# mandb
[root@server ~]# man -k _selinux
删除端口标签
删除自定义端口标签的语法与添加端口标签的语法相同,但不是使用 -a
选项(表示添加),而是使用 -d
选项 (表示删除)。
例如,要删除除端口 71/tcp 与 gophoer_port_t
的绑定
[root@server ~]# semanage port -l | grep gopher
gopher_port_t tcp 70
gopher_port_t udp 70
[root@server ~]# semanage port -a -t gopher_port_t -p tcp 71
[root@server ~]# semanage port -l | grep gopher
gopher_port_t tcp 71, 70
gopher_port_t udp 70
[root@server ~]# semanage port -d -t gopher_port_t -p tcp 71
[root@server ~]# semanage port -l | grep gopher
gopher_port_t tcp 70
gopher_port_t udp 70
修改端口绑定
如果管理员意外为端口分配了错误类型,或者要求已更改,则可以修改与端口相关联的标签。这种流程比删除旧绑定并添加新绑定更高效。修改操作需要 -m 选项。
例如,要将端口 71/tcp 从gopher_port_t
修改为http_port_t
,管理员可以使用以下命令:
[root@server ~]# semanage port -m -t http_port_t -p tcp 71
通过work 区域永久路由来自 172.25.0.0/24 子网的所有流量
[root@server ~]# firewall-cmd --permanent --add-source=172.25.0.0/24 --zone=work