33.5.IPFILTER(IPF)
最后更新于
这有帮助吗?
最后更新于
这有帮助吗?
IPFILTER,即 IPF,是一款跨平台的开源防火墙,已移植到多个操作系统,包括 FreeBSD、NetBSD、OpenBSD 和 Solaris™。
IPFILTER 是一个内核级防火墙和 NAT 机制,可以通过用户空间程序进行控制和监控。防火墙规则可以通过 ipf
设置或删除,NAT 规则可以通过 ipnat
设置或删除,IPFILTER 内核部分的运行时统计信息可以通过 ipfstat
打印,而 ipmon
可用于将 IPFILTER 操作记录到系统日志文件中。
IPF 最初使用了“最后匹配规则优先”的规则处理逻辑,并且仅使用无状态规则。从那时起,IPF 已增强为包括 quick
和 keep state
选项。
IPF 的常见问题解答可参考 。IPFilter 邮件列表的可搜索存档可在 获取。
本章节的重点是与 FreeBSD 相关的 IPF。它提供了包含 quick
和 keep state
选项的规则示例。
IPF 已包含在 FreeBSD 基本安装中,作为一个内核加载模块,这意味着不需要自定义内核即可启用 IPF。
对于那些希望将 IPF 支持静态编译到自定义内核中的用户,请参阅 中的说明。以下是可用的内核选项:
其中,options IPFILTER
启用 IPFILTER 支持,options IPFILTER_LOG
启用 IPF 日志记录,通过 ipl 包日志伪设备记录每个包含 log
关键字的规则,IPFILTER_LOOKUP
启用 IP 池以加速 IP 查找,options IPFILTER_DEFAULT_BLOCK
更改默认行为,使得任何不匹配防火墙 pass
规则的包都会被阻止。
要配置系统在启动时启用 IPF,请在 /etc/rc.conf 中添加以下条目。这些条目还将启用日志记录并设置 default pass all
。要将默认策略更改为 block all
,而不编译自定义内核,请记得在规则集的末尾添加 block all
规则。
如果需要 NAT 功能,还应添加以下行:
然后,要立即启动 IPF:
要加载防火墙规则,使用 ipf
指定规则集文件的名称。可以使用以下命令替换当前正在运行的防火墙规则:
其中,-Fa
会刷新所有内部规则表,-f
指定要加载的规则文件。
这使得能够对自定义规则集进行更改,并通过更新规则的最新副本来更新正在运行的防火墙,而无需重启系统。这种方法对于测试新规则非常方便,可以执行任意多次。
本节描述了用于创建有状态规则的 IPF 规则语法。在创建规则时,请记住,除非规则中包含 quick
关键字,否则每条规则都是按顺序读取的,最后匹配的规则 会被应用。这意味着,即使第一个匹配数据包的规则是 pass
,如果之后有匹配的规则是 block
,该数据包也会被丢弃。可以在 /usr/share/examples/ipfilter 中找到示例规则集。
在创建规则时,#
字符用于标记注释的开始,并可以出现在规则的末尾,以解释该规则的功能,或者单独位于一行。任何空白行都会被忽略。
规则中使用的关键字必须按特定顺序书写,从左到右。有些关键字是必需的,而其他则是可选的。某些关键字有子选项,这些子选项本身可能也是关键字,并且还包括更多子选项。关键字的顺序如下,其中大写字母表示变量,小写字母表示必须出现在后面的变量之前:
ACTION DIRECTION OPTIONS proto PROTO_TYPE from SRC_ADDR SRC_PORT to DST_ADDR DST_PORT TCP_FLAG|ICMP_TYPE keep state STATE
ACTION
关键字指示如果数据包匹配该规则,应该对数据包执行什么操作。每条规则必须有一个操作。以下是已识别的操作:
block
:丢弃数据包。
pass
:允许数据包。
log
:生成一条日志记录。
count
:统计数据包和字节数,这可以指示规则使用的频率。
auth
:将数据包排队,交由另一个程序进一步处理。
call
:访问 IPF 内置的功能,以执行更复杂的操作。
decapsulate
:去除任何头部,以处理数据包的内容。
接下来,每条规则必须明确指定流量的方向,使用以下关键字之一:
in
:规则应用于传入的数据包。
out
:规则应用于传出的数据包。
all
:规则适用于任一方向。
如果系统有多个接口,可以在方向后指定接口名。例如 in on fxp0
。
OPTIONS
是可选的。但是,如果指定了多个选项,它们必须按这里显示的顺序使用。
quick
:如果数据包匹配此规则,则执行规则指定的操作,并且不再处理任何后续规则。
使用 log
关键字时,可以按顺序使用以下修饰符:
body
:表示数据包内容的前 128 字节将在头部之后记录。
first
:如果 log
关键字与 keep state
选项一起使用,则建议使用此选项,以便仅记录触发数据包,而不是每个匹配的有状态连接数据包。
PROTO_TYPE
是可选的。然而,如果规则需要指定 SRC_PORT
或 DST_PORT
,则它是必需的,因为它定义了协议类型。在指定协议类型时,使用 proto
关键字后跟协议号或 /etc/protocols 中的协议名称。示例协议名称包括 tcp
、udp
或 icmp
。如果指定了 PROTO_TYPE
,但没有指定 SRC_PORT
或 DST_PORT
,则该规则将匹配该协议的所有端口号。
SRC_PORT
是可选的。然而,如果使用了它,则需要先定义 PROTO_TYPE
。端口号必须以 proto
关键字为前缀。
支持多种比较运算符:=
(等于)、!=
(不等于)、<
(小于)、>
(大于)、⇐
(小于或等于)和 >=
(大于或等于)。
要指定端口范围,请将两个端口号放在 < >
(小于和大于)、><
(大于和小于)或 :
(大于或等于,且小于或等于)之间。
to
关键字是必需的,后面跟着表示数据包目的地的关键字。与 SRC_ADDR
类似,它可以是主机名、带有 CIDR 掩码的 IP 地址、地址池或 all
关键字。
与 SRC_PORT
类似,DST_PORT
是可选的。然而,如果使用了它,则需要先定义 PROTO_TYPE
。端口号也必须以 proto
关键字为前缀。
如果 tcp
被指定为 PROTO_TYPE
,则可以指定标志,标志是表示连接状态的 TCP 标志的字母。可能的值有:S
(SYN)、A
(ACK)、P
(PSH)、F
(FIN)、U
(URG)、R
(RST)、C
(CWN)和 E
(ECN)。
如果 pass
规则包含 keep state
,IPF 将在其动态状态表中添加一条记录,并允许后续匹配该连接的数据包。IPF 可以跟踪 TCP、UDP 和 ICMP 会话的状态。任何 IPF 确定属于已激活会话的数据包,即使它属于不同的协议,也会被允许。
在 IPF 中,数据包要通过连接到公共互联网的接口时,首先会与动态状态表进行检查。如果数据包匹配组成活动会话的下一个预期数据包,它将通过防火墙并更新该会话的状态。那些不属于已有活动会话的数据包将与出站规则集进行匹配。从连接到公共互联网的接口传入的数据包首先会与动态状态表进行检查。如果数据包匹配组成活动会话的下一个预期数据包,它将通过防火墙并更新该会话的状态。那些不属于已有活动会话的数据包将与入站规则集进行匹配。
本节演示如何创建一个示例规则集,该规则集仅允许与 pass
规则匹配的服务,并阻止所有其他服务。
FreeBSD 使用回环接口(lo0)和 IP 地址 127.0.0.1
进行内部通信。防火墙规则集必须包含允许这些内部使用的包自由流动的规则:
连接到互联网的公共接口用于授权和控制所有出站和入站连接的访问。如果一个或多个接口连接到私人网络,则这些内部接口可能需要规则来允许从局域网起始的包在内部网络之间流动或流向连接到互联网的接口。规则集应分为三个主要部分:任何受信任的内部接口、通过公共接口的出站连接和通过公共接口的入站连接。
这两条规则允许所有流量通过一个名为 xl0 的受信任局域网接口:
公共接口的出站和入站部分的规则应将最常匹配的规则放在前面,将不常匹配的规则放在后面,最后一条规则用于阻止和记录该接口和方向的所有包。
以下规则集定义了公共接口 dc0 的出站部分。这些规则保持状态并标识内部系统被授权访问公共互联网的特定服务。所有规则都使用 quick
并指定适当的端口号,并在适用时指定目标地址。
此示例展示了公共接口入站部分的规则集,它首先阻止所有不需要的包。这样可以减少最后一条规则记录的包的数量。
每当使用 log first
选项的规则生成日志消息时,运行 ipfstat -hio
来评估该规则被匹配的次数。大量的匹配可能表明系统正遭受攻击。
入站部分的其余规则定义了哪些连接可以从互联网发起。最后一条规则拒绝所有未被前述规则明确允许的连接。
要启用 NAT,向 /etc/rc.conf 文件中添加以下语句,并指定包含 NAT 规则的文件名:
NAT 规则的基本语法如下,其中 map
开始规则,IF 应替换为外部接口的名称:
LAN_IP_RANGE 是内部客户端使用的 IP 地址范围,通常是类似 192.168.1.0/24
的私有地址范围。PUBLIC_ADDRESS 可以是静态外部 IP 地址,也可以是关键字 0/32
,表示分配给 IF 的 IP 地址。
在 IPF 中,当一个包从 LAN 到达防火墙并且目标是公共地址时,包首先会经过防火墙规则集的出站规则。然后,包会传递到 NAT 规则集,该规则集从上到下读取,匹配的第一个规则会生效。IPF 会根据包的接口名称和源 IP 地址测试每个 NAT 规则。当包的接口名称与 NAT 规则匹配时,包的源 IP 地址(位于私有 LAN 中)会与 LAN_IP_RANGE 中指定的 IP 地址范围进行匹配。匹配后,包的源 IP 地址会被重写为 PUBLIC_ADDRESS 中指定的公共 IP 地址。IPF 会在其内部 NAT 表中记录一条条目,以便当包从互联网返回时,可以将其映射回原始的私有 IP 地址,然后将包传递到防火墙规则进行进一步处理。
对于拥有大量内部系统或多个子网的网络,将每个私有 IP 地址转换为单个公共 IP 地址会成为资源问题。为了解决这个问题,可以使用两种方法。
第一种方法是为源端口分配一个端口范围。通过添加 portmap
关键字,NAT 可以被引导只使用指定范围内的源端口:
另外,可以使用 auto
关键字,这会告诉 NAT 自行决定可以使用的端口:
第二种方法是使用一个公共地址池。当 LAN 地址太多而无法适配单个公共地址时,这种方法非常有用。如果有一块公共 IP 地址池可用,可以将这些公共 IP 地址用作 NAT 选择的 IP 地址池,在数据包外发时进行地址映射。
公共 IP 地址范围可以使用子网掩码或 CIDR 表示法来指定。以下两条规则是等效的:
一种常见的做法是将一个公开可访问的 Web 服务器或邮件服务器隔离到内部网络段。这些服务器的流量仍然需要经过 NAT,但需要端口重定向,将入站流量引导到正确的服务器。例如,将内部地址为 10.0.10.25
的 Web 服务器映射到其公共 IP 地址 20.20.20.5
,可以使用以下规则:
如果这是唯一的 Web 服务器,这条规则也能工作,因为它将所有外部的 HTTP 请求重定向到 10.0.10.25
:
IPF 内置了一个 FTP 代理,可以与 NAT 一起使用。它监视所有出站流量的主动或被动 FTP 连接请求,并动态创建临时过滤规则,包含 FTP 数据通道使用的端口号。这消除了为 FTP 连接打开大量高端端口的需要。
在此示例中,第一条规则为来自内部 LAN 的出站 FTP 流量调用代理。第二条规则将 FTP 流量从防火墙传递到互联网,第三条规则处理所有非 FTP 流量:
FTP map
规则应位于 NAT 规则之前,这样当包与 FTP 规则匹配时,FTP 代理会创建临时的过滤规则,让 FTP 会话数据包通过并经过 NAT。所有非 FTP 的 LAN 包不会匹配 FTP 规则,但如果它们匹配第三条规则,将会经过 NAT。
如果没有 FTP 代理,则需要使用以下防火墙规则。请注意,如果没有代理,则需要允许所有高于 1024
的端口:
每次编辑包含 NAT 规则的文件时,运行 ipnat
使用 -CF
选项来删除当前的 NAT 规则并刷新动态转换表的内容。包括 -f
并指定要加载的 NAT 规则文件名:
要显示 NAT 统计信息:
要列出 NAT 表的当前映射:
要开启详细模式并显示与规则处理、活动规则和表条目相关的信息:
默认的 ipfstat
输出如下所示:
提供多个选项。使用 -i
表示入站,-o
表示出站时,命令将检索并显示当前由内核安装并使用的适当过滤规则列表。如果还希望看到规则编号,请添加 -n
。例如,ipfstat -on
会显示带有规则编号的出站规则表:
添加 -h
可以在每条规则前添加规则匹配的次数。例如,ipfstat -oh
会显示出站内部规则表,并在每条规则前加上其使用次数:
日志记录提供了事后查看信息的能力,例如哪些数据包被丢弃,它们来自哪里,以及它们的目的地。此信息在追踪攻击者时非常有用。
待在 rc.conf 中启用日志记录功能,并通过 service ipmon start
启动,IPF 只会记录包含 log
关键字的规则。防火墙管理员决定应该记录规则集中哪些规则,通常只有拒绝规则会被记录。习惯上,将 log
关键字包含在规则集中的最后一条规则中,这样就可以看到所有没有匹配任何规则的数据包。
默认情况下,ipmon -Ds
模式使用 local0
作为日志记录设施。以下日志级别可用于进一步区分记录的数据:
要将 IPF 设置为将所有数据记录到 /var/log/ipfilter.log,首先创建一个空文件:
然后,为了将所有记录的消息写入指定的文件,向 /etc/syslog.conf 中添加以下语句:
不要忘记编辑 /etc/newsyslog.conf 来轮换新日志文件。
由 ipmon
生成的消息由空格分隔的数据字段组成。所有消息的公共字段如下:
数据包接收的日期。
数据包接收的时间,格式为 HH:MM:SS.F,表示小时、分钟、秒和秒的小数部分。
处理数据包的接口名称。
规则组和规则号,格式为 @0:17
。
动作:p
代表通过,b
代表阻止,S
代表短包,n
代表未匹配任何规则,L
代表日志规则。
地址以三个字段表示:源地址和端口由逗号分隔,后跟 → 符号,再加上目标地址和端口。例如:209.53.17.22,80 → 198.73.220.17,1722
。
PR
后跟协议名称或编号。例如:PR tcp
。
len
后跟数据包的头部长度和总长度。例如:len 20 40
。
如果数据包是 ICMP 包,消息的末尾会有两个字段,第一个始终是 "icmp",下一个是 ICMP 消息和子消息类型,用斜杠分隔。例如:icmp 3/3
表示端口不可达消息。
有关此命令其他标志的详细信息,请参阅 。
本节将描述这些关键字及其选项。它不是每个可能选项的详尽列表。有关创建 IPF 规则时可用规则语法的完整描述,请参考 ,并查阅每个关键字使用示例。
log
:执行指定的操作时,数据包头部的内容将写入 包日志伪设备。
on
:后面必须跟着接口名,该接口名是通过 显示的接口名。只有数据包通过指定的接口且符合指定方向时,规则才会匹配。
还可以使用额外的选项来指定错误返回消息。有关详细信息,请参考 。
from
关键字是必需的,后面跟着表示数据包源的关键字。源地址可以是主机名、带有 CIDR 掩码的 IP 地址、地址池或 all
关键字。有关示例,请参考 。
没有办法匹配无法通过点分十进制形式/掩码长度表示的 IP 地址范围。可以使用 软件包和 Ports 来简化 CIDR 掩码的计算。更多信息可在该工具的网页上找到:。
如果 icmp
被指定为 PROTO_TYPE
,则可以指定要匹配的 ICMP 类型。有关可接受类型的详细信息,请参考 。
在 keep state
后可以添加几个关键字。如果使用,它们将设置控制有状态过滤的各种选项,例如设置连接限制或连接年龄。有关可用选项及其描述的详细信息,请参阅 。
NAT 规则非常灵活,可以根据商业和家庭用户的需要实现多种功能。这里展示的规则语法已简化,以演示常见的使用方式。有关完整的规则语法描述,请参阅 。
IPF 包含 命令,可用于检索和显示统计信息,这些统计信息是在数据包经过防火墙时与规则匹配时收集的。统计信息自上次启动防火墙或自上次通过 ipf -Z
将其重置为零以来积累。
要以类似 的格式显示状态表,使用 ipfstat -t
。当防火墙遭受攻击时,此选项提供了识别和查看攻击数据包的能力。可选的子标志提供了实时监控目标或源 IP、Port 或协议的能力。有关详细信息,请参阅 。
IPF 提供了 ipmon
,可用于以人类可读的格式记录防火墙的日志信息。它要求在自定义内核中首先添加 options IPFILTER_LOG
,按照 中的说明进行操作。
此命令通常以守护进程模式运行,以便提供一个持续的系统日志文件,以便查看过去的事件。由于 FreeBSD 内置了 系统,自动轮换系统日志,因此默认的 rc.conf ipmon_flags
语句使用 -Ds
:
要激活更改并指示 读取修改后的 /etc/syslog.conf,运行 service syslogd reload
。
如果数据包是 TCP 包,还会有一个额外的字段,前面带有连字符,后面是与设置的任何标志对应的字母。有关字母和标志的列表,请参阅 。