9.6. 原始 IP 防火墙 (2.0 内核)

Linux 的第一代 IP 防火墙支持出现在 1.1 系列内核中。它是 Alan Cox 将 BSD ipfw 防火墙支持移植到 Linux 的结果。出现在 2.0 系列内核中的防火墙支持是第二代,由 Jos Vos、Pauline Middelink 和其他人增强。

9.6.1. 使用 ipfwadm

ipfwadm 命令是第二代 Linux IP 防火墙的配置工具。 也许描述 ipfwadm 命令的最简单方法是通过示例。首先,让我们编写前面介绍的示例。

9.6.1.1. 一个简单的示例

假设我们的组织中有一个网络,并且我们正在使用基于 Linux 的防火墙机器将我们的网络连接到 Internet。 此外,假设我们希望该网络的用户能够访问 Internet 上的 Web 服务器,但不允许传递任何其他流量。

我们将设置一个转发规则,以允许源地址在我们网络上且目标套接字为端口 80 的数据报转发出去,并允许相应的回复数据报通过防火墙转发回来。

假设我们的网络具有 24 位网络掩码(C 类)和地址 172.16.1.0。 我们可能使用的规则是
# ipfwadm -F -f
# ipfwadm -F -p deny
# ipfwadm -F -a accept -P tcp -S 172.16.1.0/24 -D 0/0 80
# ipfwadm -F -a accept -P tcp -S 0/0 80 -D 172.16.1.0/24

The-F命令行参数告诉 ipfwadm 这是一个转发规则。 第一个命令指示 ipfwadm “刷新”所有转发规则。 这确保我们在开始添加特定规则之前从已知状态开始工作。

第二个规则设置我们的默认转发策略。 我们告诉内核拒绝或不允许转发 IP 数据报。 设置默认策略非常重要,因为这描述了任何其他规则未专门处理的任何数据报会发生什么情况。 在大多数防火墙配置中,您都希望将默认策略设置为“deny”,如所示,以确保只有您专门允许通过防火墙的流量才能被转发。

第三个和第四个规则是实现我们要求的规则。 第三个命令允许我们的数据报发出,第四个规则允许响应返回。

让我们回顾一下每个参数

-F

这是一个转发规则。

-a accept

附加此规则,并将策略设置为“accept”,这意味着我们将转发与此规则匹配的任何数据报。

-P tcp

此规则适用于 tcp 数据报(与 UDP 或 ICMP 相对)。

-S 172.16.1.0/24

源地址必须具有与网络地址 172.16.1.0 的前 24 位匹配的位。

-D 0/0 80

目标地址必须具有零位与地址 0.0.0.0 匹配的位。 这实际上是“任何事物”的简写符号。 80 是目标端口,在本例中为 WWW。 您也可以使用出现在/etc/services文件中描述端口的任何条目,所以-D 0/0 www也可以正常工作。

ipfwadm 接受您可能不熟悉的形式的网络掩码。/nn表示法是一种描述提供的地址有多少位是有效位或掩码大小的方法。 这些位始终从左到右计数; 表 9-1 中列出了一些常见示例。

表 9-1. 常见网络掩码位值

网络掩码
255.0.0.08
255.255.0.016
255.255.255.024
255.255.255.12825
255.255.255.19226
255.255.255.22427
255.255.255.24028
255.255.255.24829
255.255.255.25230

我们之前提到过,ipfwadm 实现了一个小技巧,可以更轻松地添加这些类型的规则。 这个技巧是一个名为 -b 的选项,它使该命令成为双向规则。

双向标志允许我们将两个规则合并为一个,如下所示
# ipfwadm -F -a accept -P tcp -S 172.16.1.0/24 -D 0/0 80 -b

9.6.1.2. 一个重要的改进

仔细看看我们的规则集。 您是否看到仍然有一种外部人员可以用来击败我们防火墙的攻击方法?

我们的规则集允许所有来自我们网络外部且源端口为 80 的数据报通过。 这将包括那些 SYN 位已设置的数据报! SYN 位是将 TCP 数据报声明为连接请求的内容。 如果外部人员拥有对主机的特权访问权限,他们可以通过我们的防火墙连接到我们的任何主机,前提是他们在他们的端使用端口 80。 这不是我们的本意。

幸运的是,有一个解决此问题的方法。 ipfwadm 命令提供了另一个标志,允许我们构建与 SYN 位已设置的数据报匹配的规则。 让我们更改我们的示例以包含这样的规则
# ipfwadm -F -a deny -P tcp -S 0/0 80 -D 172.16.10.0/24 -y
# ipfwadm -F -a accept -P tcp -S 172.16.1.0/24 -D 0/0 80 -b

The-y标志使规则仅在数据报中设置了 SYN 标志时才匹配。 因此,我们的新规则表示:“拒绝任何来自任何地方且源端口为 80 且 SYN 位已设置的、发往我们网络的 TCP 数据报”,或“拒绝来自使用端口 80 的主机的任何连接请求。”

为什么我们将这个特殊规则放在主规则之前? IP 防火墙规则的运行方式是,第一个匹配项是使用的规则。 两个规则都将匹配我们要阻止的数据报,因此我们必须确保将deny规则放在accept规则之前。

9.6.1.3. 列出我们的规则

输入我们的规则后,我们要求 ipfwadm 使用以下命令为我们列出它们
# ipfwadm -F -l
此命令将列出所有已配置的转发规则。 输出应如下所示
# ipfwadm -F -l
IP firewall forward rules, default policy: accept
type  prot source               destination          ports
deny  tcp  anywhere             172.16.10.0/24       www -> any
acc   tcp  172.16.1.0/24        anywhere             any -> www
ipfwadm 命令将尝试使用/etc/services中的条目将端口号转换为服务名称(如果那里存在条目)。

默认输出缺少一些重要的细节。 在默认列表输出中,我们看不到-y参数的效果。 如果您也指定了 -e (扩展输出) 参数,则 ipfwadm 命令能够生成更详细的列表输出。 我们不会在此处显示完整输出,因为它对于页面来说太宽了,但它包含一个-e(扩展输出) 参数。 我们不会在此处显示完整输出,因为它对于页面来说太宽了,但它包含一个opt(选项) 列,其中显示了-y控制 SYN 数据包的选项

# ipfwadm -F -l -e
P firewall forward rules, default policy: accept
 pkts bytes type  prot opt  tosa tosx ifname  ifaddress   source        ...   
    0     0 deny  tcp  --y- 0xFF 0x00 any     any         anywhere      ...       
    0     0 acc   tcp  b--- 0xFF 0x00 any     any         172.16.1.0/24 ...

9.6.2. 更复杂的示例

前面的示例很简单。 并非所有网络服务都像 WWW 服务那样易于配置; 实际上,典型的防火墙配置会复杂得多。 让我们看另一个常见的示例,这次是 FTP。 我们希望我们的内部网络用户能够登录到 Internet 上的 FTP 服务器以读取和写入文件。 但我们不希望 Internet 上的人员能够登录到我们的 FTP 服务器。

我们知道 FTP 使用两个 TCP 端口:端口 20 (ftp-data) 和端口 21 (ftp),所以
# ipfwadm -a deny -P tcp -S 0/0 20 -D 172.16.1.0/24 -y
# ipfwadm -a accept -P tcp -S 172.16.1.0/24 -D 0/0 20 -b
#
# ipfwadm -a deny -P tcp -S 0/0 21 -D 172.16.1.0/24 -y
# ipfwadm -a accept -P tcp -S 172.16.1.0/24 -D 0/0 21 -b
对吗? 嗯,不一定。 FTP 服务器可以在两种不同的模式下运行:被动模式和主动模式。[1] 在被动模式下,FTP 服务器侦听来自客户端的连接。 在主动模式下,服务器实际上会建立与客户端的连接。 主动模式通常是默认模式。 图 9-3 说明了这些差异。

图 9-3. FTP 服务器模式

许多 FTP 服务器在主动模式下运行时,从端口 20 建立数据连接,这为我们简化了一些事情,但不幸的是并非所有服务器都这样做。[2]

但这会如何影响我们? 看一下我们端口 20(FTP 数据端口)的规则。 我们现在的规则假设连接将由我们的客户端建立到服务器。 如果我们使用被动模式,这将有效。 但是,我们很难配置一个令人满意的规则来允许 FTP 主动模式,因为我们可能无法提前知道将使用哪些端口。 如果我们打开防火墙以允许任何端口上的传入连接,那么我们将使我们的网络暴露于所有接受连接的服务的攻击之下。

最安全的解决困境的方法是坚持要求我们的用户以被动模式运行。 大多数 FTP 服务器和许多 FTP 客户端都将以这种方式运行。 流行的 ncftp 客户端也支持被动模式,但可能需要进行少量配置更改才能使其默认为被动模式。 许多万维网浏览器(如 Netscape 浏览器)也支持被动模式 FTP,因此应该不难找到合适的软件来使用。 或者,您可以完全避免此问题,方法是使用 FTP 代理服务器,该服务器接受来自内部网络的连接并建立与外部网络的连接。

在构建防火墙时,您可能会发现许多此类问题。 您应始终仔细考虑服务实际如何运行,以确保您已为其设置了适当的规则集。 真正的防火墙配置可能非常复杂。

9.6.3. ipfwadm 参数摘要

ipfwadm 具有许多与 IP 防火墙配置相关的不同参数。 一般语法是
ipfwadm category command parameters [options]

让我们看看其中的每一个。

9.6.3.1. 类别

必须提供以下类别中的一个且仅一个。 类别告诉防火墙您正在配置哪种类型的防火墙规则

-I

输入规则

-O

输出规则

-F

转发规则

9.6.3.2. 命令

必须提供以下命令中的至少一个,并且仅适用于与提供的类别相关的那些规则。 命令告诉防火墙要采取的操作。

-a [策略]

附加新规则

-i [策略]

插入新规则

-d [策略]

删除现有规则

-p policy

设置默认策略

-l

列出所有现有规则

-f

刷新所有现有规则

与 IP 防火墙相关的策略及其含义是

accept

允许接收、转发或传输匹配的数据报

deny

阻止接收、转发或传输匹配的数据报

reject

阻止接收、转发或传输匹配的数据报,并向发送数据报的主机发送 ICMP 错误消息

9.6.3.3. 参数

必须提供以下参数中的至少一个。 使用参数指定此规则适用于哪些数据报

-P protocol

可以是 TCP、UDP、ICMP 或 all。 示例

-P tcp

-S address[/mask] [port]

此规则将匹配的源 IP 地址。 如果您不提供网络掩码,则假定网络掩码为“/32”。 您可以选择指定此规则将应用于哪些端口。 您还必须使用上面描述的 -P 参数指定协议才能使其工作。 如果您不指定端口或端口范围,则假定“所有”端口都匹配。 可以按名称指定端口,如果您希望使用它们的-P参数指定协议才能使其工作。 如果您不指定端口或端口范围,则假定“所有”端口都匹配。 可以按名称指定端口,如果您希望使用它们的/etc/services条目。 对于 ICMP 协议,端口字段用于指示 ICMP 数据报类型。 可以描述端口范围; 使用通用语法lowport:highport。 这是一个例子

-S 172.29.16.1/24 ftp:ftp-data

-D address[/mask] [port]

指定此规则将匹配的目标 IP 地址。 目标地址的编码规则与先前描述的源地址相同。 这是一个例子

-D 172.29.16.1/24 smtp

-V address

指定接收数据包的网络接口的地址 (-I ) 或正在发送的网络接口的地址 (-O)。 这使我们能够创建仅适用于我们机器上某些网络接口的规则。 这是一个例子

-V 172.29.16.1

-W name

指定网络接口的名称。 此参数的工作方式与 -V 参数相同,不同之处在于您提供设备名称而不是其地址。 这是一个例子-V参数相同,不同之处在于您提供设备名称而不是其地址。 这是一个例子

-W ppp0

9.6.3.4. 可选参数

这些参数有时非常有用

-b

这用于双向模式。 此标志匹配指定源和目标之间任一方向的流量。 这使您不必创建两个规则:一个用于连接的转发方向,一个用于反向方向。

-o

这使能够将匹配的数据报记录到内核日志中。 与此规则匹配的任何数据报都将记录为内核消息。 这对于使您能够检测未经授权的访问非常有用。

-y

这用于匹配 TCP 连接数据报。 该选项使规则仅匹配尝试建立 TCP 连接的数据报。 只有 SYN 位已设置但 ACK 位未设置的数据报才会匹配。 这对于过滤 TCP 连接尝试非常有用,并且对于其他协议将被忽略。

-k

这用于匹配 TCP 确认数据报。 此选项使规则仅匹配对尝试建立 TCP 连接的数据包的确认。 只有 ACK 位已设置的数据报才会匹配。 这对于过滤 TCP 连接尝试非常有用,并且对于所有其他协议将被忽略。

9.6.3.5. ICMP 数据报类型

每个防火墙配置命令都允许您指定 ICMP 数据报类型。 与 TCP 和 UDP 端口不同,没有方便的配置文件列出数据报类型及其含义。 ICMP 数据报类型在 RFC-1700(分配的号码 RFC)中定义。 ICMP 数据报类型也列在标准 C 库头文件之一中。/usr/include/netinet/ip_icmp.h文件(属于 GNU 标准库包,C 程序员在编写使用 ICMP 协议的网络软件时使用该文件)也定义了 ICMP 数据报类型。 为了您的方便,我们在表 9-2中列出了它们。 iptables 命令界面允许您按名称指定 ICMP 类型,因此我们也列出了它使用的助记符。

表 9-2. ICMP 数据报类型

类型编号iptables 助记符类型描述
0echo-reply回显回复
3destination-unreachable目标不可达
4source-quench源抑制
5redirect重定向
8echo-request回显请求
11time-exceeded超时
12parameter-problem参数问题
13timestamp-request时间戳请求
14timestamp-reply时间戳回复
15none信息请求
16none信息回复
17address-mask-request地址掩码请求
18address-mask-reply地址掩码回复

注释

[1]

FTP 主动模式有点违反直觉地使用 PORT 命令启用。 FTP 被动模式使用 PASV 命令启用。

[2]

ProFTPd 守护程序是一个很好的 FTP 服务器示例,至少在旧版本中不是这样。