Linux 运维手册之 firewalld 防火墙管理工具
后知后觉 暂无评论

防火墙(Firewall),也称防护墙,是由Check Point创立者Gil Shwed1993年发明并引入国际互联网(US5606668(A)1993-12-15)。它是一种位于内部网络与外部网络之间的网络安全系统。一项信息安全的防护系统,依照特定的规则,允许或是限制传输的数据通过。

在 Linux 中常用的防火墙有很多,但是常用的防火墙有 iptables 和 firewalld 两种。

Firewalld 是新一代的防火墙管理工具,在 Redhat 7 / CentOS 7 等 Linux 发行版都已经内置,但是旧的发行版依然可以手动安装和使用。

概述

iptables 与 firewalld 都不是真正的防火墙,都只是用来定义防火墙策略的防火墙管理工具而已。

iptables 服务会把配置好的防火墙策略交由内核层面的 netfilter 网络过滤器来处理,而 firewalld 服务则是把配置好的防火墙策略交由底层的 nftables 包过滤框架来处理[1]。换句话说,系统中其实存在多个防火墙管理工具,旨在方便运维人员管理Linux系统中的防火墙策略,只需要配置妥当其中的一个就足够了。虽然这些工具各有优劣,但它们在防火墙策略的配置思路上是保持一致的。只要在这多个防火墙管理工具中任选一款并将其学透,就足以满足日常的工作需求了。

[1] 注意:不同的版本 firewalld 的底层实现可能会不同。

实现原理

原理图-firewalld-structure+nftables

如图所示,不同版本的 firewalld 的实现方式不同,可参见图中的 Backends 部分,为具体的实现方式。

例如:在 CentOS 7 / Redhat 7 中内置的 firewalld 版本为 0.4.4 ,因此底层调用的还是 系统的 iptables ,所以安装的依赖还有 iptables 可用 yum deplist firewalld 查询。

区域

这是 firewalld 中引入的一个用户态抽象层(新概念),在不同的区域中的预制的规则不同。

区域默认规则策略
block拒绝流入的流量,除非与流出的流量相关
dmz拒绝流入的流量,除非与流出的流量相关;而如果流量与ssh服务相关,则允许流量
drop拒绝流入的流量,除非与流出的流量相关
external拒绝流入的流量,除非与流出的流量相关;而如果流量与ssh服务相关,则允许流量
home拒绝流入的流量,除非与流出的流量相关;而如果流量与ssh、mdns、ipp-client、amba-client与dhcpv6-client服务相关,则允许流量
internal等同于home区域
public拒绝流入的流量,除非与流出的流量相关;而如果流量与ssh、dhcpv6-client服务相关,则允许流量
trusted允许所有的数据包流入与流出
work拒绝流入的流量,除非与流出的流量数相关;而如果流量与ssh、ipp-client与dhcpv6-client服务相关,则允许流量

可以把不同网卡绑定到不同的区域,用于实现不同网卡的智能管控。默认 firewalld 会加载为 public 区域,此区域内置的规则默认只允许 SSH 与 DHCP 服务,若向其他区域内添加了规则则会同时生效多个区域内的规则。

管理

firewalld 的控制有两种方式,firewall-config(图形界面)firewall-cmd(命令行模式),在最小化安装(minimal)模式中只能使用命令行模式进行管理。

小贴士:可以使用 yum groups install 'GNOME Desktop' 安装图形界面,然后执行 yum install firewall-config 即可。

本文关于图形界面操作的步骤不再复述(操作简单),本文着重说明命令行模式的操作方式。

启动 firewalld

虽然 firewalld 的 0.4.4 依然调用 iptables ,但是服务依然不能共存,只能由 firewalld 进行调用,因此若启动了 iptables 请先关闭再启动 firewalld 。

禁用 iptables 服务

systemctl mask iptables
systemctl mask ip6tables

启动 firewalld 服务

systemctl start firewalld
systemctl enable firewalld
小贴士:在 CentOS 7 之后默认不会启动 iptables 服务,因此无需此步骤。

操作 firewalld

启动守护进程后就可以使用 firewall-cmd 命令进行管理防火墙规则了,防火墙的规则有两种,一种立即生效但是重启服务后就会丢失,另一种不会立即生效但是会将配置写入文件重启服务后会自动加载。

控制指令

控制指令分为两种 - 短参数 -- 长参数,短参数都是基础参数(比如查看软件版本等),配置规则时用不到,都是长参数。

常用的长参数有以下几种,查看完整版请使用 firewall-cmd --help 命令查看。

参数作用
区域相关
--get-default-zone查询默认的区域名称
--set-default-zone=<区域名>设置默认的区域,使其永久生效
--get-active-zones显示当前正在使用的区域与网卡名称
--get-zones显示总共可用的区域
--new-zone=<区域名>新增区域
服务相关
--get-services显示预先定义的服务
--add-service=<服务名>设置默认区域允许该服务的流量
--remove-service=<服务名>设置默认区域不再允许该服务的流量
--query-service=<服务名>查询区域内是否允许此服务 (需要配合 --zone=<区域名>)参数使用
端口相关
--add-port=<端口/协议>设置默认区域允许该端口的流量
--remove-port=<端口/协议>设置默认区域不再允许该端口的流量
Interface网卡相关指令
--add-interface=<网卡名>将源自该网卡的所有流量都导向某个指定区域
--change-interface=<网卡名>将某个网卡与区域进行关联
其他参数
--list-all显示当前区域的网卡配置参数、资源、端口以及服务等信息
--reload重载配置文件,可以使得 --permanent 的指令立即生效
--permanent使得此次操作永久生效(不会立即生效)

多区域配置

默认情况下只会启动一个区域,但是实际上多个区域也可以进行协同合作,可以更加灵活的完成需求,而不必在一个区域内进行操作。

示例需求:只允许 10.0.0.0/24 的流量通过,其他的流量全部拒绝。(白名单机制)

思路:

操作:

firewall-cmd --set-default-zone=drop
firewall-cmd --permanent  --change-interface=eth0 --zone=drop
firewall-cmd --permanent --add-source=10.0.0.0/24 --zone=trusted
firewall-cmd --reload

检查:

# firewall-cmd --get-active-zones
drop
  interfaces: eth0
trusted
  sources: 10.0.0.0/24

服务信任策略

firewalld 内内置了很多服务与进程的标准定义(由 IANA 进行定义端口号用途,详见TCP and UDP port - WikiPedia),默认配置下可以直接添加使用。

例如: SSH 服务默认使用 22 端口、 FTP 服务默认使用 20/21 端口、 HTTP 服务默认使用 80 端口、 HTTPS 服务默认使用 443 端口 等等。

在使用程序默认端口时,直接可以使用 firewalld 的服务功能进行管理。

示例需求:配置 WEB 服务器与负载均衡服务器防火墙,允许 HTTP 和 HTTPS 请求并设置为永久生效。

思路:

操作:

firewall-cmd --add-service=http --add-service=https --permanent
firewall-cmd --reload

检查:

firewall-cmd --list-service
dhcpv6-client ssh https http

内置的规则文件为 XML 格式的文件,存放在路径 /usr/lib/firewalld/services/ 下。

因此可以通过自建规则文件的方式来创建自定义服务,放行特定程序或修改后的程序。

查看一个服务的配置文件,以 HTTP 服务为例。

cat /usr/lib/firewalld/services/http.xml 
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>WWW (HTTP)</short>
  <description>HTTP is the protocol used to serve Web pages. If you plan to make your Web server publicly available, enable this option. This option is not required for viewing pages locally or developing Web pages.</description>
  <port protocol="tcp" port="80"/>
</service>

可以看出来配置文件中定义了程序名,程序描述,程序协议与端口。实际上只需定义名称,协议,端口即可。描述等内容可以省略,但是推荐写全,方便日后查看和修改。

示例需求:将流行的非关系型数据库 MongoDB 制作为服务并进行配置,方便日后操作。

思路:

操作:

(1). 查询 官方文档 可知 MongoDB 使用 27017/TCP - 27019/TCP 端口

(2). 编写配置文件

sudo vim /usr/lib/firewalld/services/mongodb.xml

(3). 写入以下内容

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>MongoDB</short>
  <description>MongoDB is a document database with the scalability and flexibility that you want with the querying and indexing that you need.</description>
  <port protocol="tcp" port="27017"/>
  <port protocol="tcp" port="27018"/>
  <port protocol="tcp" port="27019"/>
</service>

(4). 添加服务

firewall-cmd --add-service=mongodb --permanent
firewall-cmd --reload

检查:

firewall-cmd --list-service
dhcpv6-client ssh mongodb
telnet 10.0.0.10 27017
Trying 10.0.0.10...
Connected to 10.0.0.10.
Escape character is '^]'

总结:

添加的服务名仅仅取决于配置文件名称,与配置文件内的描述无关,因此请使用简洁容易辨认的名称进行命名。

端口信任策略

与服务类似,若不想以服务形式信任,单纯使用端口也可以,虽然操作繁琐,且容易遗忘,但灵活性较高。

示例需求:假设某服务使用 8080/TCP 与 8080/UDP ,现需要配置防火墙规则。

思路:

操作:

firewall-cmd --add-port=8080/udp --add-port=8080/tcp --permanent
firewall-cmd --reload

检查:

firewall-cmd --list-ports
8080/tcp 8080/udp

端口转发策略

端口转发在实际中用途很大,比如实现内网穿透,虚拟机与宿主机通讯等。

命令格式模板

添加:

firewall-cmd --zone=<区域> --add-forward-port=port=<源端口号>:proto=<协议>:toport=<目标端口号>:toaddr=<目标IP地址>

移除:

firewall-cmd --remove-forward-port=port=<源端口号>:proto=<协议>:toport=<目标端口号>:toaddr=<目标IP地址>
示例需求:把访问本机 52022/TCP 端口的流量转发到 22/TCP 端口。

思路:

操作:

firewall-cmd --permanent --zone=public --add-forward-port=port=52022:proto=tcp:toport=22:toaddr=10.0.0.10
firewall-cmd --reload

检查:

firewall-cmd --list-all

总结:

添加命令与删除命令几乎一致,只有首个单词不同,添加规则时必须指定生效区域,删除时区域可以省略。

富规则策略

针对普通规则设置繁琐,服务式规则编写困难且形式单一的问题出现了富规则,配置服务更加灵活,且规则优先级最高,但是命令偏复杂。

可使用 MAN 功能查看详细使用手册

man firewalld.richlanguage

因富规则配置偏复杂,因此本文采用实例进行说明。

实例 1
示例需求:允许来自于 192.168.20.0/16 主机请求 8080-8083 端口, 永久生效。

思路:

操作:

firewall-cmd --zone=public --permanent \
--add-rich-rule='rule family=ipv4 source address=192.168.20.0/16 port port=8080-8083 protocol=tcp accept'
firewall-cmd --reload

检查:

# firewall-cmd --list-all
实例 2
示例需求:拒绝来自 192.168.69.113/32 主机所有的请求, 永久生效。

思路:

操作:

firewall-cmd --zone=public --permanent \
--add-rich-rule='rule family=ipv4 source address=192.168.69.113/32 reject'
firewall-cmd --reload

检查:

firewall-cmd --list-all
实例 3
示例需求:拒绝来自于 192.168.69.0/24 网段的 SSH 连接, 永久生效。

思路:

操作:

firewall-cmd --zone=public --permanent \
--add-rich-rule='rule family=ipv4 source address=192.168.69.0/24 service name=ssh reject'
firewall-cmd --reload

检查:

firewall-cmd --list-all
实例 4
示例需求:临时禁止任意来源连接 SSH 服务,规则在 300 秒后自动失效。

思路:

操作:

firewall-cmd --add-rich-rule='rule family=ipv4 source address=0.0.0.0/24 service name=ssh reject' --timeout=300
实例 5
示例需求:将远程 10.0.0.1/32 主机请求 52022 端口,转发至 22 端口, 永久生效。

思路:

操作:

firewall-cmd --zone=public --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.1/32 forward-port port=52022 protocol=tcp to-port=22'
firewall-cmd --reload

检查:

firewall-cmd --list-all
实例 6
示例需求:将远程 10.0.0.1 主机请求 3306 端口,转发至后端主机 10.0.0.9 的 3306 端口, 永久生效。

思路:

操作:

firewall-cmd --add-masquerade --permanent
firewall-cmd --zone=public --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.1/32 forward-port port=3306 protocol=tcp to-port=3306 to-addr=10.0.0.9'
firewall-cmd --reload

检查:

firewall-cmd --list-all
实例 7
示例需求:允许 192.168.0.0/16 访问 HTTP/HTTPS ,并记录日志, 日志级别为notice,日志前缀为 NEW HTTP,限制每秒最多3个并发, 永久生效。

思路:

操作:

firewall-cmd --zone=public --permanent --add-rich-rule= \
'rule family=ipv4 source address=192.168.0.0/16 service name=http,https log level=notice prefix="New HTTP " limit value="3/s" accept'
firewall-cmd --reload

检查:

firewall-cmd --list-all

地址伪装策略

此举启用区域的伪装功能,私有网络的地址将被隐藏并映射到一个公有IP。这是地址转换的一种形式,常用于路由。由于内核的限制,目前伪装功能仅可用于 IPv4。

firewall-cmd --add-masquerade --permanent
firewall-cmd --reload

使用此功能可将全部内网机器通过任意一台能访问外网的机器实现与外网通讯。


附录

参考链接

本文撰写于一年前,如出现图片失效或有任何问题,请在下方留言。博主看到后将及时修正,谢谢!
禁用 / 当前已拒绝评论,仅可查看「历史评论」。