每当 Linux 在网络环境中被使用时,您都可以使用内核函数来操作网络数据包,以在内部和外部网络区域之间保持分离。Linux netfilter 框架提供了建立有效防火墙的手段,以隔离不同的网络。使用 iptables(用于定义规则集的通用表结构)可以精确控制允许通过网络接口的数据包。可以使用 firewalld 及其图形界面 firewall-config 来设置此类数据包过滤器。
openSUSE Leap 15.0 引入 firewalld 作为新的默认软件防火墙,取代 SuSEfirewall2。本章提供了配置 firewalld 的指导,并为从旧版 openSUSE Leap 版本升级的用户提供了从 SuSEfirewall2 迁移的指导。
本节讨论了数据包过滤的底层细节。组件 netfilter 和 iptables 负责网络数据包的过滤和操作以及网络地址转换 (NAT)。过滤标准和与之关联的任何操作都存储在链中,这些链必须由各个网络数据包在到达时逐一匹配。链存储在表中。 iptables 命令允许您更改这些表和规则集。
Linux 内核维护三个表,每个表对应于数据包过滤器功能的特定类别
此表包含大部分过滤规则,因为它实现了更严格意义上的 数据包过滤 机制,例如确定是否允许通过数据包 (ACCEPT) 或丢弃数据包 (DROP)。
此表定义了数据包源地址和目标地址的任何更改。使用这些功能还可以实现 伪装,这是 NAT 的一种特殊情况,用于将专用网络与 Internet 连接起来。
此表中的规则可以操纵存储在 IP 标头中的值(例如服务类型)。
这些表包含几个预定义的链来匹配数据包
此链应用于所有传入的数据包。
此链应用于目的地为系统内部进程的数据包。
此链应用于通过系统路由的数据包。
此链应用于源自系统本身的数据包。
此链应用于所有传出数据包。
图 23.1,“iptables:数据包的可能路径” 说明了网络数据包在给定系统上可能经过的路径。为简单起见,该图将表显示为链的一部分,但实际上这些链包含在表本身中。
在最简单的情况下,目的地为系统的传入数据包到达 eth0 接口。该数据包首先引用 mangle 表的 PREROUTING 链,然后引用 nat 表的 PREROUTING 链。接下来的步骤,关于数据包的路由,确定数据包的实际目标是系统本身的进程。在通过 mangle 和 filter 表的 INPUT 链后,如果 filter 表的规则允许,数据包最终到达其目标。
伪装是 Linux 特有的 NAT (网络地址转换) 形式,可用于将小型局域网与 Internet 连接起来。局域网主机使用来自专用范围的 IP 地址(请参阅 “参考”手册,第 13 章“基本网络”,第 13.1.2 节“子网掩码和路由”),而在 Internet 上使用官方 IP 地址。为了能够连接到 Internet,局域网主机的专用地址将被转换为官方地址。这在路由器上完成,充当局域网和 Internet 之间的网关。基本原理很简单:路由器有多个网络接口,通常是网卡和单独的 Internet 接口。后者将路由器与外部世界连接起来,而其他接口则将其与局域网主机连接起来。当这些主机连接到路由器的网卡(例如 eth0)时,它们可以将任何未目的地为局域网的数据包发送到默认网关或路由器。
在配置网络时,请确保所有本地主机的广播地址和子网掩码相同。否则,数据包将无法正确路由。
如前所述,当局域网主机之一发送目的地为 Internet 地址的数据包时,它会发送到默认路由器。但是,在路由器可以转发此类数据包之前,必须对其进行配置。出于安全原因,默认安装中未启用此功能。要启用它,请在文件 /etc/sysctl.conf 中添加行 net.ipv4.ip_forward = 1。或者,可以通过 YaST 执行此操作,例如通过调用 yast routing ip-forwarding on。
连接的目标主机可以看到您的路由器,但不知道数据包的来源是您内部网络中的主机。这就是为什么这种技术被称为伪装。由于地址转换,路由器是任何回复数据包的第一个目的地。路由器必须识别这些传入的数据包并转换其目标地址,以便可以将数据包转发到局域网中的正确主机。
由于依赖于伪装表路由传入流量,因此无法从外部建立到内部主机的连接。对于此类连接,表中将没有条目。此外,任何已建立的连接都有分配给它在表中的状态条目,因此该条目不能被另一个连接使用。
因此,您可能会在使用某些应用程序协议(例如 ICQ、cucme、IRC (DCC、CTCP) 和 FTP (PORT 模式))时遇到一些问题。Web 浏览器、标准 FTP 程序以及许多其他程序使用 PASV 模式。这种被动模式不太有问题,因为它与数据包过滤和伪装有关。
防火墙 可能是最广泛使用的术语,用于描述控制网络之间数据流的机制。严格来说,本节中描述的机制称为 数据包过滤器。数据包过滤器根据某些标准(例如协议、端口和 IP 地址)调节数据流。这允许您阻止根据其地址不应该到达您网络的那些数据包。例如,要允许公用访问您的 Web 服务器,请显式打开相应的端口。但是,数据包过滤器不会扫描具有合法地址的数据包的内容,例如定向到您的 Web 服务器的数据包。例如,如果传入的数据包旨在破坏您 Web 服务器上的 CGI 程序,则数据包过滤器仍然会允许它们通过。
一种更有效但更复杂的机制是组合几种类型的系统,例如与应用程序网关或代理交互的数据包过滤器。在这种情况下,数据包过滤器拒绝任何定向到禁用端口的数据包。定向到应用程序网关的数据包被接受。此网关或代理假装是服务器的实际客户端。从协议级别来看,这样的代理可以被认为是用于应用程序的伪装主机。Squid 是一个 HTTP 和 FTP 代理服务器,就是一个例子。要使用 Squid,必须配置浏览器通过代理进行通信。请求的任何 HTTP 页面或 FTP 文件都从代理缓存提供,未在缓存中找到的对象由代理从 Internet 检索。
以下部分重点介绍随 openSUSE Leap 提供的包过滤器。有关数据包过滤和防火墙的更多信息,请阅读 防火墙 HOWTO。
firewalld 取代 SuSEfirewall2
openSUSE Leap 15.0 引入 firewalld 作为新的默认软件防火墙,取代 SuSEfirewall2。如果您是从早于 openSUSE Leap 15.0 的版本升级,SuSEfirewall2 将保持不变,您必须手动升级到 firewalld(请参阅 第 23.5 节,“从 SuSEfirewall2 迁移”)。
firewalld 是一个守护程序,用于维护系统的 iptables 规则,并提供一个 D-Bus 接口来操作它们。它附带一个命令行实用程序 firewall-cmd 和一个图形用户界面 firewall-config,用于与之交互。由于 firewalld 在后台运行并提供定义良好的接口,因此允许其他应用程序请求更改 iptables 规则,例如设置虚拟机网络。
firewalld 实施不同的安全区域。存在几个预定义的区域,例如 internal 和 public。管理员可以根据需要定义其他自定义区域。每个区域都包含自己的 iptables 规则集。每个网络接口都恰好是其中一个区域的成员。还可以根据源地址将单个连接分配给一个区域。
每个区域代表一定程度的信任。例如,public 区域不可信,因为此网络中的其他计算机不受您的控制(适用于 Internet 或无线热点连接)。另一方面,internal 区域用于受 控制 的网络,例如家庭或公司网络。通过以这种方式使用区域,主机可以以定义的方式为受信任的网络和不受信任的网络提供不同类型服务。
有关 firewalld 中预定义区域及其含义的更多信息,请参阅其手册 https://www.firewalld.org/documentation/zone/predefined-zones.html。
网络接口的初始状态是不分配到任何区域。在这种情况下,网络接口将隐式地由默认区域处理,可以通过调用 firewall-cmd --get-default-zone 来确定默认区域。如果未另行配置,则默认区域为 public 区域。
firewalld 数据包过滤模型允许任何传出连接通过。传出连接是由本地主机主动建立的连接。由远程主机建立的传入连接将被阻止,除非在相关区域中允许该服务。因此,具有传入流量的每个接口都必须放置在合适的区域,以允许所需的服务的访问。为每个区域定义您需要的服务或协议。
firewalld 的一个重要概念是区分两种单独的配置:运行时 和 永久 配置。运行时配置表示当前活动规则,而永久配置表示保存的规则,这些规则将在重新启动 firewalld 时应用。这允许添加临时规则,这些规则将在重新启动 firewalld 后丢弃,或者能够试验新规则,同时能够恢复到原始状态。在更改配置时,需要注意您正在编辑哪个配置。如何在 第 23.4.1.2 节,“运行时与永久配置” 中讨论了这一点。
要使用图形用户界面 firewall-config 执行 firewalld 配置,请参阅其 文档。在以下部分中,我们将研究如何使用命令行 firewall-cmd 执行典型的 firewalld 配置任务。
firewalld 默认会被安装并启用。它是一个常规的 systemd 服务,可以通过 systemctl 或 YaST 服务管理器进行配置。
安装后,YaST 会自动启动 firewalld 并将所有接口保留在默认的 public 区域。如果系统上配置并激活了服务器应用程序,YaST 可以通过服务器配置模块中的 或 选项调整防火墙规则。一些服务器模块对话框包含一个 按钮,用于激活其他服务和端口。
默认情况下,所有 firewall-cmd 命令都作用于运行时配置。您可以通过添加 --permanent 参数将大多数操作应用于永久配置 仅。这样做会将更改影响到永久配置,并且不会立即在运行时配置中生效。目前没有一种方法可以在单个调用中将规则添加到运行时和永久配置。要实现此目的,您可以将所有必要的更改应用于运行时配置,并在一切正常工作后,发出以下命令
#firewall-cmd --runtime-to-permanent
这将把所有当前的运行时规则写入永久配置。以这种方式,您或其它程序可能对防火墙所做的任何临时修改都将变为永久。如果您对此不确定,也可以采取相反的方法以确保安全:将新规则添加到永久配置并重新加载 firewalld 以使其生效。
一些配置项,例如默认区域,由运行时和永久配置共享。更改它们会立即反映在两种配置中。
要将运行时配置恢复为永久配置,从而丢弃任何临时更改,可以通过 firewalld 命令行界面或 systemd 实现两种可能性
#firewall-cmd --reload
#systemctl reload firewalld
为了简洁起见,以下章节中的示例将始终作用于运行时配置(如果适用)。相应地调整它们以使其永久生效。
您可以像这样列出当前分配到某个区域的所有网络接口
#firewall-cmd --zone=public --list-interfaceseth0
类似地,您可以查询特定接口分配到的区域
#firewall-cmd --get-zone-of-interface=eth0public
以下命令行将接口分配到区域。使用 --add-interface 的变体只有在 eth0 尚未分配到另一个区域时才有效。使用 --change-interface 的变体始终有效,必要时会从其当前区域删除 eth0
#firewall-cmd --zone=internal --add-interface=eth0#firewall-cmd --zone=internal --change-interface=eth0
任何没有显式 --zone 参数的操作都将隐式作用于默认区域。可以使用以下命令获取和设置默认区域分配
#firewall-cmd --get-default-zonedmz#firewall-cmd --set-default-zone=public
任何未显式分配到区域的网络接口都将自动属于默认区域。更改默认区域会立即将所有这些网络接口重新分配给永久和运行时配置。您不应将受信任的区域(如 internal)用作默认区域,以避免意外暴露于威胁。例如,热插拔网络接口(如 USB 以太网接口)在那种情况下会自动成为受信任区域的一部分。
未显式属于任何区域的接口不会出现在区域接口列表中。目前没有命令可以列出未分配的接口。因此,在正常操作期间最好避免未分配的网络接口。
firewalld 具有 服务 的概念。服务由端口和协议的定义组成。这些定义在给定网络服务的上下文中(例如 Web 或邮件服务器协议)在逻辑上属于一起。可以使用以下命令获取有关预定义服务及其详细信息的更多信息
#firewall-cmd --get-services[...] dhcp dhcpv6 dhcpv6-client dns docker-registry [...]#firewall-cmd --info-service dhcpdhcp ports: 67/udp protocols: source-ports: modules: destination:
可以使用这些服务定义来轻松地使关联的网络功能在区域中可访问。例如,以下命令行在内部区域打开 HTTP Web 服务器端口
#firewall-cmd --add-service=http --zone=internal
使用 --remove-service 对应的命令执行服务的移除。您还可以使用 --new-service 子命令定义自定义服务。有关如何操作的更多详细信息,请参阅 https://www.firewalld.org/documentation/howto/add-a-service.html。
如果您只想按编号打开单个端口,可以使用以下方法。这将打开内部区域中的 TCP 端口 8000
#firewall-cmd --add-port=8000/tcp --zone=internal
使用 --remove-port 对应的命令进行移除。
firewalld 支持一个 --timeout 参数,该参数允许您在有限的时间段内打开服务或端口。这对于快速测试以及确保不会忘记关闭服务或端口非常有用。要允许 internal 区域中的 imap 服务 5 分钟,您将调用
#firewall-cmd --add-service=imap --zone=internal --timeout=5m
firewalld 提供了一个 锁定模式,该模式在激活时可防止更改防火墙规则。由于应用程序可以通过 D-Bus 接口自动更改防火墙规则,并且根据 PolicyKit 规则,普通用户可能也能做到同样,因此在某些情况下防止更改可能很有帮助。有关此信息,请参阅 https://fedoraproject.org/wiki/Features/FirewalldLockdown。
重要的是要理解,锁定模式功能不提供真正的安全性,而只是防止意外或良性的更改防火墙的尝试。如 https://seclists.org/oss-sec/2017/q3/139 所指出的,当前在 firewalld 中实现的锁定模式无法提供针对恶意意图的安全保障。
firewalld 声称对主机 netfilter 规则拥有独占控制权。您不应使用其他工具(如 iptables)修改防火墙规则。这样做可能会使 firewalld 感到困惑并破坏安全或功能。
如果您需要添加未涵盖在 firewalld 功能中的自定义防火墙规则,则有两种方法可以做到。要直接传递原始 iptables 语法,您可以使用 --direct 选项。它将表、链和优先级作为初始参数,并将其余命令行传递给 iptables。以下示例为转发筛选表添加连接跟踪规则
#firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i eth0 -o eth1 \ -p tcp --dport 80 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
此外,firewalld 实现了所谓的 丰富规则,这是一种用于以更简单的方式指定 iptables 规则的扩展语法。您可以在 https://www.firewalld.org/documentation/man-pages/firewalld.richlanguage.html 找到语法规范。以下示例会丢弃来自特定源地址的所有 IPv4 数据包
#firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" \ source address="192.168.2.4" drop'
firewalld 并非设计为功能齐全的路由器。典型的家庭路由器设置的基本功能是可用的。对于企业生产路由器,您不应使用 firewalld,而应使用专用的路由器和防火墙设备。以下只是关于如何在 firewalld 中利用路由的一些提示
首先,需要启用 IP 转发,如 第 23.2 节,“伪装基础知识” 中所述。
要启用 IPv4 伪装,例如在 internal 区域中,请发出以下命令。
#firewall-cmd --zone=internal --add-masquerade
firewalld 还可以启用端口转发。以下命令将本地 TCP 连接上的端口 80 转发到另一个主机
#firewall-cmd --zone=public \ --add-forward-port=port=80:proto=tcp:toport=80:toaddr=192.168.1.10
某些网络服务不会侦听预定义的端口号。相反,它们基于 portmapper 或 rpcbind 协议运行。从这里开始,我们将使用术语 rpcbind。当其中一项服务启动时,它会选择一个随机本地端口并与 rpcbind 通信以使端口号已知。rpcbind 本身正在侦听一个众所周知的端口。远程系统然后可以查询 rpcbind 以了解它知道的网络服务及其侦听的端口。如今,很少有程序使用这种方法。流行的示例是网络信息服务 (NIS;ypserv 和 ypbind) 和网络文件系统 (NFS) 版本 3。
较新的 NFSv4 需要单个众所周知的 TCP 端口 2049。对于协议版本 4.0,可能需要将内核参数 fs.nfs.nfs_callback_tcpport 设置为静态端口(请参阅 示例 23.1,“nfs 内核模块在 /etc/modprobe.d/60-nfs.conf 中的回调端口配置”)。从协议版本 4.1 开始,此设置也变得不必要了。
rpcbind 协议的动态特性使得使受防火墙保护的受影响的服务可访问变得困难。firewalld 本身不支持这些服务。有关手动配置,请参阅 第 23.4.2.1 节,“配置静态端口”。或者,openSUSE Leap 提供了一个辅助脚本。有关详细信息,请参阅 第 23.4.2.2 节,“使用 firewall-rpcbind-helper 配置静态端口”。
一种可能性是配置所有相关网络服务以使用固定的端口号。完成此操作后,可以将固定的端口在 firewalld 中打开,一切都应该正常工作。使用的实际端口号由您自行决定,但不应与分配给其他服务的任何众所周知的端口号冲突。请参阅 表 23.1,“静态端口配置的重要 sysconfig 变量”,了解 NIS 和 NFSv3 服务的可用配置项列表。根据您的实际 NIS 或 NFS 配置,并非所有这些端口都可能需要您的设置。
|
文件路径 |
变量名称 |
示例值 |
|---|---|---|
/etc/sysconfig/nfs
| MOUNTD_PORT | 21001 |
| STATD_PORT | 21002 | |
| LOCKD_TCPPORT | 21003 | |
| LOCKD_UDPPORT | 21003 | |
| RQUOTAD_PORT | 21004 | |
/etc/sysconfig/ypbind
| YPBIND_OPTIONS | -p 24500 |
/etc/sysconfig/ypserv
| YPXFRD_ARGS | -p 24501 |
| YPSERV_ARGS | -p 24502 | |
| YPPASSWDD_ARGS | --port 24503 |
您需要重新启动受这些静态端口配置影响的任何相关服务才能使更改生效。您可以使用命令 rpcinfo -p 查看当前分配的 rpcbind 端口。成功后,静态配置的端口应该会显示在那里。
除了用于在用户空间中运行的网络服务的端口配置之外,还有一些端口是 Linux 内核在处理 NFS 时直接使用的。其中一个端口是 nfs_callback_tcpport。它仅适用于 NFS 协议版本低于 4.1 的情况。有一个名为 fs.nfs.nfs_callback_tcpport 的 sysctl 用于配置此端口。此 sysctl 节点仅在 NFS 挂载处于活动状态时动态出现。因此,最好通过内核模块参数配置端口。可以通过创建如下所示的文件来实现:示例 23.1,“nfs 内核模块在 /etc/modprobe.d/60-nfs.conf 中的回调端口配置”。
/etc/modprobe.d/60-nfs.conf 中的回调端口配置 #options nfs callback_tcpport=21005
要使此更改生效,最简单的方法是重新启动机器。否则,需要停止所有 NFS 服务并重新加载 nfs 内核模块。要验证活动的 NFS 回调端口,请检查 cat /sys/module/nfs/parameters/callback_tcpport 的输出。
为了便于处理现在静态配置的 RPC 端口,创建一个新的 firewalld 服务定义很有用。此服务定义将所有相关端口分组在一起,例如,使其易于在特定区域中访问。在 示例 23.2,“为 NFS 定义新的 firewalld RPC 服务的命令” 中,这是为 NFS 端口配置的,如附带示例中所配置的那样。
firewalld RPC 服务的命令 ##firewall-cmd --permanent --new-service=nfs-rpc#firewall-cmd --permanent --service=nfs-rpc --set-description="NFS related, statically configured RPC ports"# add UDP and TCP ports for the given sequence#for port in 21001 21002 21003 21004; do firewall-cmd --permanent --service=nfs-rpc --add-port ${port}/udp --add-port ${port}/tcp done# the callback port is TCP only#firewall-cmd --permanent --service=nfs-rpc --add-port 21005/tcp# show the complete definition of the new custom service#firewall-cmd --info-service=nfs-rpc --permanent -vnfs-rpc summary: description: NFS and related, statically configured RPC ports ports: 4711/tcp 21001/udp 21001/tcp 21002/udp 21002/tcp 21003/udp 21003/tcp 21004/udp 21004/tcp protocols: source-ports: modules: destination: # reload firewalld to make the new service definition available#firewall-cmd --reload# the new service definition can now be used to open the ports for example in the internal zone#firewall-cmd --add-service=nfs-rpc --zone=internal
firewalld 配置请参阅 AutoYaST 指南的《防火墙配置》部分,了解如何为 AutoYaST 创建 firewalld 配置。
从 任何低于 15.0 的 openSUSE Leap 版本 升级到 openSUSE Leap 15.6 时,SuSEfirewall2 不会更改并保持活动状态。没有自动迁移,因此必须手动迁移到 firewalld。 firewalld 包含一个辅助迁移脚本 susefirewall2-to-firewalld。根据 SuSEfirewall2 配置的复杂程度,该脚本可能会执行完美的迁移,或者可能会失败。最有可能的是,它会部分成功,您需要查看新的 firewalld 配置并进行调整。
生成的配置使 firewalld 的行为在某种程度上类似于 SuSEfirewall2。为了充分利用 firewalld 的功能,您可以选择创建一个新的配置,而不是尝试迁移旧配置。安全地运行 susefirewall2-to-firewalld 脚本而无需任何选项,因为它不会对您的系统进行任何永久更改。但是,如果您正在远程管理系统,您可能会被锁定。
安装并运行 susefirewall2-to-firewalld
#zypper in susefirewall2-to-firewalld#susefirewall2-to-firewalld INFO: Reading the /etc/sysconfig/SuSEfirewall2 file INFO: Ensuring all firewall services are in a well-known state. INFO: This will start/stop/restart firewall services and it's likely INFO: to cause network disruption. INFO: If you do not wish for this to happen, please stop the script now! 5...4...3...2...1...Lets do it! INFO: Stopping firewalld INFO: Restarting SuSEfirewall2_init INFO: Restarting SuSEfirewall2 INFO: DIRECT: Adding direct rule="ipv4 -t filter -A INPUT -p udp -m udp --dport 5353 -m pkttype --pkt-type multicast -j ACCEPT" [...] INFO: Enabling direct rule=ipv6 -t filter -A INPUT -p udp -m udp --dport 546 -j ACCEPT INFO: Enabling direct rule=ipv6 -t filter -A INPUT -p udp -m udp --dport 5353 -m pkttype --pkt-type multicast -j ACCEPT INFO: Enable logging for denied packets INFO: ########################################################## INFO: INFO: The dry-run has been completed. Please check the above output to ensure INFO: that everything looks good. INFO: INFO: ########################################################### INFO: Stopping firewalld INFO: Restarting SuSEfirewall2_init INFO: Restarting SuSEfirewall2
这将产生大量的输出,您可能希望将其重定向到文件以便于查看
# susefirewall2-to-firewalld | tee newfirewallrules.txt该脚本支持以下选项
-c提交更改。该脚本会对系统进行更改,因此请确保您仅在真正满意拟议的更改时才使用此选项。这 将 重置您当前的 firewalld 配置,因此请确保您进行备份!
-d超级嘈杂。使用它来提交错误报告,但请小心屏蔽敏感信息。
-h此消息。
-q无输出。错误也不会打印!
-v详细模式。它将打印警告和其他信息性消息。
有关 firewalld 包的最新的信息和其他文档可以在 /usr/share/doc/packages/firewalld 中找到。netfilter 和 iptables 项目的主页 https://www.netfilter.org 提供了大量关于 iptables 的文档,有多种语言。