33.5. IPFILTER(IPF) ===================== IPFILTER(也称为 IPF)是一个跨平台的开源防火墙,已被移植到多个操作系统,包括 FreeBSD,NetBSD,OpenBSD 和 Solaris™。 IPFILTER 是一种内核端防火墙和 NAT 机制,可以由用户空间程序控制和监视。可以使用 ipf 设置或删除防火墙规则,可以使用 ipnat 设置或删除 NAT 规则,可以使用 ipfstat 打印 IPFILTER 内核部分的运行时统计信息,ipmon 可用于将 IPMILTER 操作记录到系统日志文件中。 IPF 最初是使用“最后一个匹配的规则成功”的规则处理逻辑编写的,并且仅使用无状态规则。自那时以来,IPF 得到了加强,以包括 ``quick`` 和 ``keep state`` 选项。 IPF 常见问题解答位于 http://www.phildev.net/ipf/index.html\ 。IPFilter 邮件列表的可搜索存档位于 http://marc.info/?l=ipfilter\ 。 手册的这一部分重点介绍 IPF,因为它与 FreeBSD 有关。它提供了包含 ``quick`` 和 ``keep state`` 选项的规则示例。 33.5.1.启用 IPF --------------- IPF 作为内核可加载模块包含在 FreeBSD 基本系统中,这意味着不需要通过定制内核来启用 IPF。 对于喜欢将 IPF 支持静态编译为定制内核的用户,请参阅\ `配置 FreeBSD 内核 `__ 中的说明。以下内核选项可用: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session options IPFILTER options IPFILTER_LOG options IPFILTER_LOOKUP options IPFILTER_DEFAULT_BLOCK 其中 ``options IPFILTER`` 启用对 IPFILTER 的支持,\ ``options IPFILTER_LOG`` 启用 IPF 日志,对每个有 ``log`` 关键字的规则使用 **ipl** 包日志伪设备,\ ``IPFILTER_LOOKUP`` 启用 IP 池,以加快 IP 查找,\ ``options IPFILTER_DEFAULT_BLOCK`` 改变默认行为,使任何不匹配防火墙 ``pass`` 规则的数据包被阻止。 要配置系统在启动时启用 IPF,请在 **/etc/rc.conf** 中添加以下条目。这些条目也将启用日志和 ``default pass all``\ 。要想在不编译定制内核的情况下将默认策略改为 ``block all``\ ,记得在规则集的末尾添加一个 ``block all`` 规则。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session ipfilter_enable="YES" # Start ipf firewall ipfilter_rules="/etc/ipf.rules" # loads rules definition text file ipv6_ipfilter_rules="/etc/ipf6.rules" # loads rules definition text file for IPv6 ipmon_enable="YES" # Start IP monitor log ipmon_flags="-Ds" # D = start as daemon # s = log to syslog # v = log tcp window, ack, seq # n = map IP & port to names 如果需要 NAT 功能,还要添加以下行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session gateway_enable="YES" # Enable as LAN gateway ipnat_enable="YES" # Start ipnat function ipnat_rules="/etc/ipnat.rules" # rules definition file for ipnat 然后,立即开启 IPF: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # service ipfilter start 要加载防火墙规则,请使用 ``ipf`` 指定规则集文件的名称。以下命令可用于替换当前正在运行的防火墙规则: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # ipf -Fa -f /etc/ipf.rules 其中 ``-Fa`` 刷新所有内部规则表,\ ``-f`` 指定包含要加载的规则的文件。 这提供了对自定义规则集进行更改并使用规则的新副本更新正在运行的防火墙的功能,而无需重新启动系统。此方法便于测试新规则,因为该过程可以根据需要执行多次。 有关此命令可用的其他标志的详细信息,请参阅 `ipf(8) `__\ 。 33.5.2. IPF 规则语法 -------------------- 本节描述了用于创建有状态规则的 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``* 本节介绍其中每个关键字及其选项。它不是每个可能选项的详尽列表。有关创建 IPF 规则时可以使用的规则语法的完整介绍,以及使用每个关键字的示例,请参阅 `ipf(5) `__\ 。 - **ACTION** action 关键字指示如果数据包与该规则匹配,则如何处理该数据包。每个规则 *都必须* 有一个操作。可识别以下操作: ``block``\ :丢弃数据包。 ``pass``\ :允许数据包。 ``log``\ :生成日志记录。 ``count``\ :计算数据包和字节数,这些数据包和字节数可以指示规则的使用频率。 ``auth``\ :将数据包排入队列,以供另一个程序进一步处理。 ``call``\ :提供对 IPF 内置函数的访问,这些函数允许执行更复杂的操作。 ``decapsulate``\ :删除所有标头以处理数据包的内容。 - **DIRECTION** 接下来,每个规则必须使用以下关键字之一显式声明流量方向: ``in``\ :规则应用于入站数据包。 ``out``\ :规则应用于出站数据包。 ``all``\ :规则适用于任一方向。 如果系统有多个接口,则可以将接口与方向一起指定。一个例子是 ``in on fxp0``\ 。 - **OPTIONS** 选项是可选的。但是,如果指定了多个选项,则必须按此处显示的顺序使用它们。 ``log``\ :执行指定的 ACTION 时,数据包标头的内容将被写入 `ipl(4) `__ 数据包日志伪设备。 ``quick``\ :如果数据包与此规则匹配,则会发生规则指定的 ACTION,并且不会对此数据包进行任何后续规则的进一步处理。 ``on``\ :后跟 `ifconfig(8) `__ 显示的接口名称。仅当数据包在指定方向上通过指定接口时,该规则才会匹配。当使用 ``log`` 关键字时,以下限定符可以按此顺序使用: ``body``\ :表示数据包内容的前 128 个字节将记录在标头之后。 ``first``\ :如果 ``log`` 关键字与 ``keep state`` 选项一起使用,则建议使用此选项,以便只记录触发数据包,而不是每个匹配有状态连接的数据包。其他选项可用于指定错误返回消息。 有关更多详细信息,请参阅 `ipf(5) `__\ 。 - **PROTO_TYPE** 协议类型是可选的。然而,如果规则需要指定一个 SRC_PORT 或 DST_PORT,它是必须的,因为它定义了协议的类型。当指定协议类型时,使用 ``proto`` 关键字,后面跟上 \*\ */etc/protocols\** 中的协议编号或名称。协议名称的例子包括 ``tcp``\ 、\ ``udp`` 或 ``icmp``\ 。如果指定了 PROTO_TYPE,但没有指定 SRC_PORT 或 DST_PORT,该协议的所有端口号都将与该规则相匹配。 **SRC_ADDR** ``from`` 关键字是必需的,后跟一个表示数据包源的关键字。源可以是主机名、IP 地址后跟 CIDR 掩码、地址池或 ``all`` 关键字。有关示例,请参阅 `ipf(5) `__\ 。 没有办法匹配 IP 地址的范围,这些 IP 地址不能使用虚线数字形式/掩码长度表示法轻松表达自己。二进制包或 ports `net-mgmt/ipcalc `__ 可用于简化 CIDR 掩码的计算。其他信息可在实用程序的网页上找到:\ http://jodies.de/ipcalc\ 。 - **SRC_PORT** 源的端口号是可选的。然而,如果使用它,它需要在规则中首先定义 PROTO_TYPE。端口号前面还必须有 proto 关键字。 支持一些不同的比较运算符:=(等于),!=(不等于),<(小于),>(大于),⇐(小于或等于),和>=(大于或等于)。 要指定端口范围,将两个端口号放在 <>(小于和大于)、><(大于和小于)或: (大于或等于和小于或等于)。 - **DST_ADDR** ``to`` 关键字是必需的,后跟一个表示数据包目标的关键字。与 SRC_ADDR 类似,它可以是主机名、IP 地址,后跟 CIDR 掩码、地址池或关键字 ``all``\ 。 - **DST_PORT** 与 SRC_PORT 类似,目标的端口号是可选的。但是,如果使用它,则需要首先在规则中定义 PROTO_TYPE。端口号前面还必须有关键字 ``proto``\ 。 - **TCP_FLAG|ICMP_TYPE** 如果 tcp 被指定为 PROTO_TYPE,标志可以被指定为字母,每个字母代表一个可能的 TCP 标志,用于确定连接的状态。可能的值是:S(SYN)、A(ACK)、P(PSH)、F(FIN)、U(URG)、R(RST)、C(CWN)和 E(ECN)。 如果 ``icmp`` 被指定为 PROTO_TYPE,可以指定要匹配的 ICMP 类型。关于允许的类型请参考 `ipf(5) `__\ 。 **STATE** 如果一个 ``pass`` 规则包含 ``keep state``\ ,IPF 将向其动态状态表添加一个条目,并允许与连接匹配的后续数据包。IPF 可以跟踪 TCP、UDP 和 ICMP 会话的状态。任何 IPF 可以确定是活动会话的一部分的数据包,即使它是不同的协议,也会被允许。 在 IPF 中,首先根据动态状态表检查预定通过连接到公共互联网的接口出去的数据包。如果该数据包与构成活动会话的下一个预期数据包相匹配,它就会退出防火墙,并在动态状态表中更新会话会话流的状态。不属于已经激活的会话的数据包将根据出站规则集进行检查。从连接到公共互联网的接口进来的数据包首先根据动态状态表进行检查。如果数据包与构成活动会话的下一个预期数据包相匹配,它就退出防火墙,并在动态状态表中更新会话对话流的状态。不属于已经活动的会话的数据包将根据入站规则集进行检查。 在 ``keep state`` 之后可以添加几个关键字。如果使用,这些关键字会设置各种控制有状态过滤的选项,比如设置连接限制或连接期限。请参考 `ipf(5) `__ 获取可用选项列表及其描述。 33.5.3.示例规则集 ----------------- 本节演示如何创建一个示例规则集,该规则集仅允许服务匹配 ``pass`` 规则并阻止所有其他规则。 FreeBSD 使用环回接口(\ **lo0**\ )和 IP 地址 ``127.0.0.1`` 进行内部通信。防火墙规则集必须包含允许自由移动这些内部使用的数据包的规则: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # no restrictions on loopback interface pass in quick on lo0 all pass out quick on lo0 all 连接到互联网的公共接口用于授权和控制所有出站和入站连接的访问。如果将一个或多个接口连接到专用网络,则这些内部接口可能需要规则来允许源自 LAN 的数据包在内部网络之间流动或流向连接到互联网的接口。规则集应分为三个主要部分:任何受信任的内部接口、通过公共接口的出站连接和通过公共接口的入站连接。 以下两个规则允许所有流量通过名为 **xl0** 的受信任 LAN 接口: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # no restrictions on inside LAN interface for private network pass out quick on xl0 all pass in quick on xl0 all 公共接口的出站和入站部分的规则应将最常匹配的规则放在不太匹配的规则之前,该部分中的最后一个规则阻止并记录该接口和方向的所有数据包。 这组规则定义名为 **dc0** 的公共接口的出站部分。这些规则保持状态,并确定内部系统授权用于互联网访问的特定服务。所有规则都使用 ``quick``\ ,并指定适当的端口号和(在适用的情况下)目的地址。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # interface facing Internet (outbound) # Matches session start requests originating from or behind the # firewall, destined for the Internet. # Allow outbound access to public DNS servers. # Replace x.x.x.x with address listed in /etc/resolv.conf. # Repeat for each DNS server. pass out quick on dc0 proto tcp from any to x.x.x.x port = 53 flags S keep state pass out quick on dc0 proto udp from any to x.x.x.x port = 53 keep state # Allow access to ISP's specified DHCP server for cable or DSL networks. # Use the first rule, then check log for the IP address of DHCP server. # Then, uncomment the second rule, replace z.z.z.z with the IP address, # and comment out the first rule pass out log quick on dc0 proto udp from any to any port = 67 keep state #pass out quick on dc0 proto udp from any to z.z.z.z port = 67 keep state # Allow HTTP and HTTPS pass out quick on dc0 proto tcp from any to any port = 80 flags S keep state pass out quick on dc0 proto tcp from any to any port = 443 flags S keep state # Allow email pass out quick on dc0 proto tcp from any to any port = 110 flags S keep state pass out quick on dc0 proto tcp from any to any port = 25 flags S keep state # Allow NTP pass out quick on dc0 proto tcp from any to any port = 37 flags S keep state # Allow FTP pass out quick on dc0 proto tcp from any to any port = 21 flags S keep state # Allow SSH pass out quick on dc0 proto tcp from any to any port = 22 flags S keep state # Allow ping pass out quick on dc0 proto icmp from any to any icmp-type 8 keep state # Block and log everything else block out log first quick on dc0 all 公共接口的入站部分中的规则示例首先阻止所有不需要的数据包。这将减少最后一个规则记录的数据包数。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # interface facing Internet (inbound) # Block all inbound traffic from non-routable or reserved address spaces block in quick on dc0 from 192.168.0.0/16 to any #RFC 1918 private IP block in quick on dc0 from 172.16.0.0/12 to any #RFC 1918 private IP block in quick on dc0 from 10.0.0.0/8 to any #RFC 1918 private IP block in quick on dc0 from 127.0.0.0/8 to any #loopback block in quick on dc0 from 0.0.0.0/8 to any #loopback block in quick on dc0 from 169.254.0.0/16 to any #DHCP auto-config block in quick on dc0 from 192.0.2.0/24 to any #reserved for docs block in quick on dc0 from 204.152.64.0/23 to any #Sun cluster interconnect block in quick on dc0 from 224.0.0.0/3 to any #Class D & E multicast # Block fragments and too short tcp packets block in quick on dc0 all with frags block in quick on dc0 proto tcp all with short # block source routed packets block in quick on dc0 all with opt lsrr block in quick on dc0 all with opt ssrr # Block OS fingerprint attempts and log first occurrence block in log first quick on dc0 proto tcp from any to any flags FUP # Block anything with special options block in quick on dc0 all with ipopts # Block public pings and ident block in quick on dc0 proto icmp all icmp-type 8 block in quick on dc0 proto tcp from any to any port = 113 # Block incoming Netbios services block in log first quick on dc0 proto tcp/udp from any to any port = 137 block in log first quick on dc0 proto tcp/udp from any to any port = 138 block in log first quick on dc0 proto tcp/udp from any to any port = 139 block in log first quick on dc0 proto tcp/udp from any to any port = 81 每当带有 ``log first`` 选项的规则上记录消息时,请运行 ``ipfstat -hio`` 以评估规则匹配的次数。大量匹配可能表示系统受到攻击。 入站部分中的其余规则定义了允许从互联网启动哪些连接。最后一个规则拒绝本节中前面规则未显式允许的所有连接。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # Allow traffic in from ISP's DHCP server. Replace z.z.z.z with # the same IP address used in the outbound section. pass in quick on dc0 proto udp from z.z.z.z to any port = 68 keep state # Allow public connections to specified internal web server pass in quick on dc0 proto tcp from any to x.x.x.x port = 80 flags S keep state # Block and log only first occurrence of all remaining traffic. block in log first quick on dc0 all 33.5.4.配置 NAT --------------- 要启用 NAT,请将这些语句添加到 **/etc/rc.conf** 并指定包含 NAT 规则的文件的名称: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session gateway_enable="YES" ipnat_enable="YES" ipnat_rules="/etc/ipnat.rules" NAT 规则非常灵活,可以完成许多不同的事情,以满足商业和家庭用户的需求。此处提供的规则语法已得到简化,以演示常见用法。有关完整的规则语法说明,请参阅 `ipnat(5) `__\ 。 NAT 规则的基本语法如下,其中启动 ``map`` 规则,\ *IF* 应替换为外部接口的名称: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session map IF LAN_IP_RANGE -> PUBLIC_ADDRESS *LAN_IP_RANGE* 是内部客户端使用的 IP 地址范围。通常,它是一个专用地址范围,例如 ``192.168.1.0/24``\ 。\ *PUBLIC_ADDRESS* 可以是静态外部 IP 地址,也可以是表示分配给 *IF* 的 IP 地址的关键字 ``0/32``\ 。 在 IPF 中,当数据包从具有公共目标的 LAN 到达防火墙时,它首先通过防火墙规则集的出站规则。然后,数据包被传递到 NAT 规则集,该规则集从上往下读取,第一个匹配的规则成功。IPF 根据数据包的接口名称和源 IP 地址测试每个 NAT 规则。当数据包的接口名称与 NAT 规则匹配时,将检查数据包在专用 LAN 中的源 IP 地址,以查看它是否在 *LAN_IP_RANGE* 中指定的 IP 地址范围内。在匹配时,数据包的源 IP 地址将使用 *PUBLIC_ADDRESS* 指定的公共 IP 地址重写。IPF 在其内部 NAT 表中发布一个条目,以便当数据包从互联网返回时,可以将其映射回其原始专用 IP 地址,然后再传递到防火墙规则进行进一步处理。 对于具有大量内部系统或多个子网的网络,将每个专用 IP 地址汇集到单个公共 IP 地址的过程将成为资源问题。有两种方法可以解决此问题。 第一种方法是分配要用作源端口的端口范围。通过添加 ``portmap`` 关键字,可以将 NAT 定向到只使用指定范围内的源端口: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:60000 另外,使用 ``auto`` 关键字告诉 NAT 来确定可用的端口: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp auto 第二种方法是使用公共地址池。当有太多的 LAN 地址无法放入单个公共地址并且有一个公共 IP 地址块可用时,这很有用。这些公共地址可用作池,NAT 从池中选择 IP 地址,因为数据包的地址在输出时被映射。 可以使用网络掩码或 CIDR 表示法指定公共 IP 地址的范围。这两个规则是等效的: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session map dc0 192.168.1.0/24 -> 204.134.75.0/255.255.255.0 map dc0 192.168.1.0/24 -> 204.134.75.0/24 一个常见的做法是,将一个可公开访问的网络服务器或邮件服务器隔离到一个内部网段。来自这些服务器的流量仍然要经过 NAT,但需要进行端口重定向,将入站流量引导到正确的服务器。例如,要把一个使用内部地址 ``10.0.10.25`` 的 Web 服务器映射到它的公共 IP 地址 ``20.20.20.5``\ ,使用这个规则。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session rdr dc0 20.20.20.5/32 port 80 -> 10.0.10.25 port 80 如果它是唯一的 Web 服务器,则此规则也可以工作,因为它将所有外部 HTTP 请求重定向到 ``10.0.10.25``\ : .. raw:: latex \diilbookstyleinputcell .. code:: shell-session rdr dc0 0.0.0.0/0 port 80 -> 10.0.10.25 port 80 IPF 有一个内置的 FTP 代理,可以与 NAT 一起使用。它监视主动或被动 FTP 连接请求的所有出站流量,并动态创建包含 FTP 数据通道使用的端口号的临时筛选器规则。这样就无需为 FTP 连接打开大范围的高阶端口。 在此示例中,第一个规则调用来自内部 LAN 的出站 FTP 流量的代理。第二条规则将 FTP 流量从防火墙传递到互联网,第三条规则处理来自内部 LAN 的所有非 FTP 流量: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session map dc0 10.0.10.0/29 -> 0/32 proxy port 21 ftp/tcp map dc0 0.0.0.0/0 -> 0/32 proxy port 21 ftp/tcp map dc0 10.0.10.0/29 -> 0/32 FTP ``map`` 规则位于 NAT 规则之前,因此当数据包与 FTP 规则匹配时,FTP 代理会创建临时筛选规则,以允许 FTP 会话数据包通过并进行 NAT。所有不是 FTP 的 LAN 数据包将不匹配 FTP 规则,但如果它们与第三个规则匹配,则将进行 NAT。 如果没有 FTP 代理,则需要以下防火墙规则。请注意,如果没有代理,则需要允许上述 ``1024`` 所有端口: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # Allow out LAN PC client FTP to public Internet # Active and passive modes pass out quick on rl0 proto tcp from any to any port = 21 flags S keep state # Allow out passive mode data channel high order port numbers pass out quick on rl0 proto tcp from any to any port > 1024 flags S keep state # Active mode let data channel in from FTP server pass in quick on rl0 proto tcp from any to any port = 20 flags S keep state 每当包含 NAT 规则的文件被编辑时,运行带有 ``-CF`` 的 ``ipnat`` 来删除当前的 NAT 规则并刷新动态翻译表的内容。包括 ``-f`` 并指定要加载的 NAT 规则集的名称。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # ipnat -CF -f /etc/ipnat.rules 要显示 NAT 统计信息: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # ipnat -s 列出 NAT 表的当前映射: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # ipnat -l 打开详细模式并显示与规则处理以及活动规则和表条目相关的信息: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # ipnat -v 33.5.5.查看 IPF 统计数据 ------------------------ IPF 包括 `ipfstat(8) `__\ ,它可用于检索和显示统计信息,这些统计信息是在数据包通过防火墙时与规则匹配时收集的。统计信息是自上次启动防火墙以来或自上次使用 ``ipf -Z`` 重置为零以来累积的。 默认 ``ipfstat`` 输出如下所示: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session input packets: blocked 99286 passed 1255609 nomatch 14686 counted 0 output packets: blocked 4200 passed 1284345 nomatch 14687 counted 0 input packets logged: blocked 99286 passed 0 output packets logged: blocked 0 passed 0 packets logged: input 0 output 0 log failures: input 3898 output 0 fragment state(in): kept 0 lost 0 fragment state(out): kept 0 lost 0 packet state(in): kept 169364 lost 0 packet state(out): kept 431395 lost 0 ICMP replies: 0 TCP RSTs sent: 0 Result cache hits(in): 1215208 (out): 1098963 IN Pullups succeeded: 2 failed: 0 OUT Pullups succeeded: 0 failed: 0 Fastroute successes: 0 failures: 0 TCP cksum fails(in): 0 (out): 0 Packet log flags set: (0) 有几个选项是可用的。当提供 ``-i``\ (入站)或 ``-o``\ (出站)时,该命令将检索并显示当前已安装并由内核使用的适当的过滤规则列表。要想看到规则的编号,请加入 ``-n``\ 。例如,\ ``ipfstat -on`` 显示了带有规则编号的出站规则表。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session @1 pass out on xl0 from any to any @2 block out on dc0 from any to any @3 pass out quick on dc0 proto tcp/udp from any to any keep state 包括 ``-h`` 每个规则前面加上规则匹配次数的计数。例如,\ ``ipfstat -oh`` 显示出站内部规则表,并在每个规则前面加上其使用计数: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session 2451423 pass out on xl0 from any to any 354727 block out on dc0 from any to any 430918 pass out quick on dc0 proto tcp/udp from any to any keep state 要以类似于 `top(1) `__ 的格式显示状态表,请使用 ``ipfstat -t``\ 。当防火墙受到攻击时,此选项提供了识别和查看攻击数据包的功能。可选的子标志提供了选择要实时监视的目标或源 IP、端口或协议的功能。有关详细信息,请参阅 `ipfstat(8) `__\ 。 33.5.6. IPF 日志记录 -------------------- IPF 提供了 ``ipmon``\ ,可用于以人类可读的格式写入防火墙的日志记录信息。它要求首先使用\ `配置 FreeBSD `__ 内核中的说明将\ ``options IPFILTER_LOG`` 添加到定制内核中。 这个命令通常在守护模式下运行,以便提供一个连续的系统日志文件,从而可以审查过去事件的日志。由于 FreeBSD 有一个内置的 `syslogd(8) `__ 工具来自动旋转系统日志,默认的 **rc.conf** ``ipmon_flags`` 语句使用 ``-Ds`` .. raw:: latex \diilbookstyleinputcell .. code:: shell-session ipmon_flags="-Ds" # D = start as daemon # s = log to syslog # v = log tcp window, ack, seq # n = map IP & port to names 日志记录提供了在事后查看信息的功能,例如丢弃了哪些数据包、它们来自哪些地址以及它们要去哪里。此信息在跟踪攻击者时很有用。 一旦在 **rc.conf** 中启用了日志记录工具并以 ``service ipmon start`` 启动,IPF 将仅记录包含 ``log`` 关键字的规则。防火墙管理员决定应记录规则集中的哪些规则,通常只记录拒绝规则。习惯上将关键字 ``log`` 包含在规则集的最后一个规则中。这样就可以查看与规则集中的任何规则都不匹配的所有数据包。 默认情况下,\ ``ipmon -Ds`` 模式用 ``local0`` 作日志记录工具。以下日志记录级别可用于进一步隔离记录的数据: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session LOG_INFO - packets logged using the "log" keyword as the action rather than pass or block. LOG_NOTICE - packets logged which are also passed LOG_WARNING - packets logged which are also blocked LOG_ERR - packets which have been logged and which can be considered short due to an incomplete header 要将 IPF 设置为将所有数据记录到 **/var/log/ipfilter.log**\ ,请首先创建空文件: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # touch /var/log/ipfilter.log 然后,将所有要记录的消息写入指定的文件,请将以下语句添加到 **/etc/syslog.conf**\ : .. raw:: latex \diilbookstyleinputcell .. code:: shell-session local0.* /var/log/ipfilter.log 要激活更改并指示 `syslogd(8) `__ 读取修改后的 **/etc/syslog.conf**\ ,请运行 ``service syslogd reload``\ 。 不要忘记编辑 **/etc/newsyslog.conf** 来轮换新的日志文件。 ``ipmon`` 生成的消息由以空格分隔的数据字段组成。所有消息共有的字段包括: 1. 数据包接收日期。 2. 数据包接收时间。其格式为 HH:MM:SS.F,表示小时、分钟、秒和几分之一秒。 3. 处理数据包的接口的名称。 4. 格式为 ``@0:17`` 的规则的组和规则编号。 5. 操作: ``p`` 对于已通过、\ ``b`` 对于阻止、\ ``S`` 对于短数据包 ``n`` 与任何规则都不匹配以及 ``L`` 对于日志规则。 6. 写为三个字段的地址:源地址和端口(以逗号分隔)、→ 符号以及目标地址和端口。例如:\ ``209.53.17.22,80 → 198.73.220.17,1722``\ 。 7. ``PR`` 后跟协议名称或编号:例如,\ ``PR tcp``\ 。 8. ``len`` 后跟标头长度和数据包的总长度:例如,\ ``len 20 40`` 如果数据包是 TCP 数据包,则将有一个以连字符开头的附加字段,后跟与设置的任何标志相对应的字母。请参考 `ipf(5) `__ 获取字母及其标志的列表。 如果数据包是 ICMP 数据包,则末尾将有两个字段:第一个字段始终为“icmp”,下一个是 ICMP 消息和子消息类型,由斜杠分隔。例如:\ ``icmp 3/3`` 对于端口无法访问的消息。