30.3. PF

Revised and updated by John Ferrell.

自FreeBSD 5.3开始,基础系统便有内置OpenBSD's PF防火墙的移植版本,PF是一套完整、多功能的防火墙,并可选择开启ALTQ(Alternate Queuing)的支持来提供Quality of Service(QoS)机制。

OpenBSD计划有维护一份官方参考文件于PF FAQ,Peter Hansteen有维一份详尽的PF教学于 http://home.nuug.no/~peter/pf/

警告:

阅读 PF FAQ 时,请注意,FreeBSD 的PF版本多年来与上游 OpenBSD 版本有很大不同。并非所有功能在 FreeBSD 上的工作方式与 OpenBSD 相同,反之亦然。

要询问有关设定与执行PF防火墙的问题可至FreeBSD packet filter邮递论坛,在询问问题之前请先查看该邮递论坛的封存数据,因您的问题可能已有解答。

本手册的这一部分主要介绍了与 FreeBSD 相关的 PF使用方法。它演示了如何启用 PFALTQ。它还提供了几个在 FreeBSD 系统上创建规则集的例子。

30.3.1. 开启PF

要使用PF,必须首先加载其内核模块。本节介绍了可以添加到/etc/rc.conf的条目,以启用PF

首先将pf_enable=yes添加到/etc/rc.conf

# sysrc pf_enable=yes

其他选项(在pfctl(8)中描述)可在启动时传递给PF。在/etc/rc.conf中添加或更改此条目,并在两个引号之间指定任何必需的标志(""):

pf_flags=""                     # additional flags for pfctl startup

PF 如果找不到规则集配置文件, 则不会启动。默认情况下, FreeBSD 并没有附带规则集, 也没有 /etc/pf.conf。规则集的例子可以在 /usr/share/examples/pf/ 中找到。如果自定义规则集已经保存在其他地方,请在/etc/rc.conf中添加一行指定文件的绝对路径:

pf_rules="/path/to/pf.conf"

PF 的日志功能由 pflog(4) 提供。在 /etc/rc.conf 中加入 pflog_enable=yes 启用日志功能:

# sysrc pflog_enable=yes

还可以添加以下几行来改变日志文件的默认位置,或者指定在启动时传递给pflog(4)的参数:

pflog_logfile="/var/log/pflog"  # where pflogd should store the logfile
pflog_flags=""                  # additional flags for pflogd startup

最后,如果防火墙后面有LAN,并且需要为LAN上的计算机转发数据包,或者需要NAT,请启用以下选项:

gateway_enable="YES"            # Enable as LAN gateway

文件保存后,使用以下命令启用带日志的 PF

# service pf start
# service pflog start

默认情况下, PF 会从 /etc/pf.conf 中读取其配置规则, 并根据此文件中指定的规则或定义修改、 丢弃或传递数据包。FreeBSD 安装中包括几个示例文件, 这些文件位于 /usr/share/examples/pf/。请参考 PF FAQ 以了解关于 PF规则集的完整内容。

要控制PF,请使用pfctl表 30.1 “有用的pfctl选项”总结了这个命令的一些有用的选项。有关所有可用选项的描述,请参阅pfctl(8)

表 30.1. 有用的pfctl选项
命令用途
pfctl -e启用 PF
pfctl -d禁用 PF
pfctl -F all -f /etc/pf.conf刷新所有NAT、筛选器、状态和表规则,然后重新加载/etc/pf.conf
pfctl -s [ rules | nat | states ]列出 filter 规则,NAT 规则, 或状态表。
pfctl -vnf /etc/pf.conf检查/etc/pf.conf是否存在错误,但不要加载规则集。

提示:

security/sudo对于运行像pfctl这样需要高阶权限的命令非常有用。它可以从 Ports Collection 中安装。

要监视通过PF防火墙的流量,请考虑安装sysutils/pftop。安装后,可以运行pftop,以类似于top(1)的格式查看当前流量状态。

30.3.2. PF规则集

Contributed by Peter N. M. Hansteen.

本节演示了如何创建一个自定义的规则集。本节从最简单的规则集开始,用几个例子来演示PF的实际应用。

最简单的规则集是针对一台不运行任何服务并且需要访问一个网络(可能是Internet)的计算机。要创建此最小规则集,请编辑 /etc/pf.conf ,像这样:

block in all
pass out all keep state

第一个规则默认拒绝所有传入的流量。第二个规则允许该系统创建的连接传出,同时保留这些连接的状态信息。这个状态信息允许这些连接的回传流量,并且只应在可以信任的机器上使用。该规则集可以装载的有:

# pfctl -e ; pfctl -f /etc/pf.conf

除了保持状态外,PF还提供了lists(列表)和lists(宏),可以在创建规则时使用。宏可以包括列表,需要在使用前定义。作为例子,在规则集的顶部插入这些行:

tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"
udp_services = "{ domain }"

PF能理解/etc/services中列出的端口名和端口号。这个例子创建了两个宏。第一个是七个 TCP 端口名的列表,第二个是一个 UDP 端口名。一旦定义好了,宏可以在规则中使用。在这个例子中,除了这个系统为七个指定的TCP服务和一个指定的UDP服务发起的连接外,所有的流量都将被拦截:

tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"
udp_services = "{ domain }"
block all
pass out proto tcp to any port $tcp_services keep state
pass proto udp to any port $udp_services keep state

尽管UDP被认为是一个无状态协议,但PF能够跟踪一些状态信息。例如,当传递一个UDP请求,询问名称服务器关于域名的请求时,PF会观察响应,并将其传递回来。

每当对规则集进行编辑时,都必须加载新规则,以使这些规则生效:

# pfctl -f /etc/pf.conf

若无语法错误,pfctl 在重新加载规则时不会有任何输出。规则在加载前可使用以下方法测试:

# pfctl -nf /etc/pf.conf

包含-n会导致规则只被解释,而不被加载。这为纠正错误提供了机会。任何时候,最后加载的有效规则集都将被执行,直到PF被禁用或加载新的规则集。

提示:

pfctl规则集验中添加-v,就可以完全按照加载规则的方式显示解析过的规则。这在调试规则时非常有用。

30.3.2.1. 使用NAT的简单通信闸

本节演示了如何在 FreeBSD 上配置运行PF 作为网关。该网关需要至少两个网络接口, 每个接口都连接到一个独立的网络。在这个例子中, xl1 连接到 Internet, 而 xl0 连接到内部网络。

首先,启用网关允许计算机将其在一个接口上收到的网络流量转发到另一个接口。这个 sysctl 设置将转发IPv4数据包:

# sysctl net.inet.ip.forwarding=1

要转发IPv6流量,请使用:

# sysctl net.inet6.ip6.forwarding=1

要在系统启动时启用这些设置,请使用sysrc(8)将其添加到/etc/rc.conf中:

# sysrc gateway_enable=yes
# sysrc ipv6_gateway_enable=yes

使用ifconfig验证这两个接口是否都已启动并正在运行。

接下来,创建PF规则,允许流量通过网关。虽然下面的规则允许有状态的流量从Internet上传递到本地网络的主机上,但to关键字并不能保证从源头到目的地的全过程通过:

pass in on xl1 from xl1:network to xl0:network port $ports keep state

该规则仅允许流量传递到内部接口上的网关。为了让数据包走得更远,需要匹配规则:

pass out on xl0 from xl1:network to xl0:network port $ports keep state

虽然这两个规则会起作用,但很少需要这么具体的规则。对于一个忙碌的网络管理员来说,可读的规则集是一个比较安全的规则集。本节的其余部分将演示如何保持规则的可读性。例如,这两条规则可以用一条规则来代替:

pass from xl1:network to any port $ports keep state

interface:network标记可以用宏来代替,这样可以使规则集更易读。例如,$localnet宏可以定义为直接连接到内部接口的网络($xl1:network)。另外,$localnet的定义可以改为IP地址/子网掩码符号来表示一个网络,例如192.168.100.1/24表示私有地址的子网。

如果需要,$localnet甚至可以定义为网络列表。无论具体需求如何,在典型的通过规则中可以使用合理的$localnet定义,如下所示:

pass from $localnet to any port $ports keep state

下面的示例规则集允许内部网络上的机器发起流量。它首先定义了两个宏来表示内部和外部的3COM接口。

注意:

对于拨号用户,外部接口将使用tun0。对于ADSL连接,特别是那些使用PPP over Ethernet(PPPoE)的用户,正确的外部接口是tun0,而不是物理以太网接口。

ext_if = "xl0"	# macro for external interface - use tun0 for PPPoE
int_if = "xl1"	# macro for internal interface
localnet = $int_if:network
# ext_if IP address could be dynamic, hence ($ext_if)
nat on $ext_if from $localnet to any -> ($ext_if)
block all
pass from { lo0, $localnet } to any keep state

此规则集引入了nat规则,该规则用于处理网络地址从内部网络中的不可路由地址到分配给外部接口的IP地址。动态分配外部接口的IP地址时,将包含 nat 规则最后一部分($ext_if)周围的括号。它可确保即使外部IP地址发生更改,网络流量也会不会中断。

请注意,这个规则集可能允许更多的流量从网络中传出。可以创建这样的宏:

client_out = "{ ftp-data, ftp, ssh, domain, pop3, auth, nntp, http, \
    https, cvspserver, 2628, 5999, 8000, 8080 }"

在 pass 规则中使用:

pass inet proto tcp from $localnet to any port $client_out \
    flags S/SA keep state

可能需要部分允许规则。下面这条规则在额外接口上允许SSH流量传输:

pass in inet proto tcp to $ext_if port ssh

这个宏的允许内部客户端的DNSNTP请求:

udp_services = "{ domain, ntp }"
pass quick inet proto { tcp, udp } to any port $udp_services keep state

注意这个规则中的quick关键字。由于规则集由多个规则组成,所以理解规则集中规则之间的关系很重要。规则是按照编写规则的顺序从上到下进行评估的。对于每一个被PF评价的数据包或连接,规则集中最后一个匹配的规则就是被应用的规则。但是,当一个数据包与包含quick关键字的规则相匹配时,规则处理就会停止,并根据该规则处理该数据包。这在需要对一般规则进行例外处理时非常有用。

30.3.2.2. 建立FTP Proxy

由于FTP协议的性质,配置有效的FTP规则可能会有问题。FTP比防火墙早了几十年,设计上不安全。最常见的反对使用FTP的观点包括:

  • 密码明文传输。

  • 本协议至少需要两个不同的 TCP 端口,用于控制和传输数据。

  • 会话(session)创建后,数据使用随机端口传输。

所有这些点都提出了安全挑战,甚至在考虑到客户端或服务器软件中的任何潜在安全弱点之前也是如此。更为安全的文件传输方式,例如sftp(1)scp(1),它们都具有认证和通过加密连接传输数据的功能。

对于那些需要 FTP的情况, PF 提供了将 FTP 流量重定向到一个名为 ftp-proxy(8)的代理程序, 它包含在 FreeBSD 的基础系统中。代理的作用是在规则集中使用一组锚点动态插入和删除规则,以正确处理FTP流量。

将此行加入/etc/rc.conf来启用FTP 代理:

ftpproxy_enable="YES"

执行service ftp-proxy start启动代理。

对于一个基本配置,需要在/etc/pf.conf中添加三个元素。首先,代理将用于插入它为FTP会话生成的规则锚点:

nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"

其次,需要通过规则允许FTP流量通过代理。

第三,重定向和NAT规则需要的过滤规则之前定义。在nat规则后加入rdr规则:

rdr pass on $int_if proto tcp from any to any port ftp -> 127.0.0.1 port 8021

最后,让重定向的流量通过:

pass out proto tcp from $proxy to any port ftp

$proxy 扩展到代理守护程序绑定到的地址。

保存/etc/pf.conf,加载新的规则,并从客户端验证FTP连接是否正常:

# pfctl -f /etc/pf.conf

这个例子涵盖了一个基本的设置,其中本地网络中的客户端需要联系其他地方的FTP服务器。这个基本的配置应该可以很好地适用于大多数FTP客户端和服务器的组合。如ftp-proxy(8)所示,通过在ftpproxy_flags=行中添加选项,可以以各种方式改变代理的行为。一些客户机或服务器可能有特定的怪癖,必须在配置中进行适配,或者可能需要以特定的方式集成代理,例如将 FTP 流量分配给特定的队列中。

关于运行由PFftp-proxy(8)保护的FTP服务器的方法。以反向模式配置一个单独的ftp-proxy,使用-R,在一个单独的端口上配置一个独立的ftp-proxy,并有自己的重定向通过规则。

30.3.2.3. 管理ICMP

许多用于调试或故障排除的工具都依赖于互联网控制信息协议(TCP/IP),该协议(ICMP)是专为调试而设计的。

ICMP协议在主机和网关之间发送和接收控制消息,主要是向发送方提供关于任何异常或困难情况的反馈。路由器使用ICMP来协商数据包大小和其他传输参数,这个过程通常被称为路径MTU发现

从防火墙的角度来看,一些ICMP控制报文容易受到已知攻击载体的攻击。同时,让所有的诊断流量无条件通过,使得调试更容易,但也使得其他人更容易提取有关网络的信息。基于这些原因,下面的规则可能不是最佳选择:

pass inet proto icmp from any to any

一种解决方案是,让本地网络的所有ICMP流量通过,同时阻止来自网络外的所有探针:

pass inet proto icmp from $localnet to any keep state
pass inet proto icmp from any to $ext_if keep state

还有一些额外选项,展示了PF的灵活性。例如,拦截所有ICMP报文,可以指定ping(8)traceroute(8)使用的报文。从为该类型的消息定义一个宏开始:

icmp_types = "echoreq"

和使用宏的规则:

pass inet proto icmp all icmp-type $icmp_types keep state

如果需要其他类型的ICMP数据包,请将icmp_types扩展为这些数据包类型的列表。键入more /usr/src/sbin/pfctl/pfctl_parser.c查看PF支持的ICMP报文类型列表。请参考http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml以了解各种消息类型。

由于 Unix 的 traceroute 默认使用 UDP,其他如有需允许 Unix traceroute

# allow out the default range for traceroute(8):
pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 keep state

由于Microsoft Windows系统上的TRACERT.EXE使用ICMP echo 请求消息,因此只需要第一条规则就可以让这些系统进行网络追踪(network traces)。Unix traceroute也可以被指示使用其他协议,如果使用了-I,则会使用ICMP echo请求消息。请查看traceroute(8) 手册页了解详情。

30.3.2.3.1. MTU 路径搜索

Internet 协议(IP)设计为独立于设备,设备独立性的一个后果是,无法始终可靠地预测给定连接的最佳数据包大小。数据包大小的主要约束是最大传输单元MTU),它设置接口的数据包大小的上限。键入ifconfig以查看系统网络接口的MTU值。

TCP/IP使用称为路径MTU发现的过程来确定连接的正确数据包大小。这个过程发送大小不一的数据包,并设置了Do not fragment标志,当达到上限时,期望返回一个ICMP数据包,类型为3,代码为4。类型3表示destination unreachable,代码4是需要碎片化,但设置了do-not-fragment标志的简称。为了允许路径MTU发现,以支持与其他MTU的连接,请在icmp_types宏中添加destination unreachable类型:

icmp_types = "{ echoreq, unreach }"

由于通过规则已经使用该宏,因此无需对其进行修改以支持新的ICMP类型:

pass inet proto icmp all icmp-type $icmp_types keep state

PF允许过滤各种ICMP类型和代码。icmp4(4)icmp6(4)中记载了可能的类型和代码列表。

30.3.2.4. 使用 Tables

有些类型的数据在特定时间内与过滤和重定向相关,但它们的规则定义太长,无法包含在规则集文件中。PF支持使用表,表是定义好的列表,无需重新加载整个规则集就可以进行操作,可以提供快速查找。表的名称总是在< >中括起来,就像这样:

table <clients> { 192.168.2.0/24, !192.168.2.5 }

在此示例中,192.168.2.0/24网络是表的一部分,但地址192.168.2.5除外,该地址使用!运算符排除。也可以从每个项位于单独行上的文件中加载表,如本示例/etc/clients所示:

192.168.2.0/24
!192.168.2.5

要引用该文件,请像这样定义表:

table <clients> persist file "/etc/clients"

表定义完成后,规则可以使用以下方式引用表:

pass inet proto tcp from <clients> to any port $client_out flags S/SA keep state

可以使用pfctl实时操作表的内容。这个例子为表添加了另一个网络:

# pfctl -t clients -T add 192.168.1.0/16

请注意,任何以这种方式进行的更改都将在此时生效,使其成为测试的理想选择,但在断电或重启时将复原。要使更改永久化,请修改规则集中表的定义或编辑该表所引用的文件。可以使用cron(8)作业来维护表的磁盘上的副本,该作业可以使用pfctl -t clients -T show >/etc/clients等命令,定期将表的内容转储到磁盘上。另外,/etc/clients也可以用内存中的表内容来更新:

# pfctl -t clients -T replace -f /etc/clients

30.3.2.5. 使用Overload Tables保护SSH

那些在外部接口上运行 SSH 的, 或许在认证日志中看到过像这样的信息:

Sep 26 03:12:34 skapet sshd[25771]: Failed password for root from 200.72.41.31 port 40992 ssh2
Sep 26 03:12:34 skapet sshd[5279]: Failed password for root from 200.72.41.31 port 40992 ssh2
Sep 26 03:12:35 skapet sshd[5279]: Received disconnect from 200.72.41.31: 11: Bye Bye
Sep 26 03:12:44 skapet sshd[29635]: Invalid user admin from 200.72.41.31
Sep 26 03:12:44 skapet sshd[24703]: input_userauth_request: invalid user admin
Sep 26 03:12:44 skapet sshd[24703]: Failed password for invalid user admin from 200.72.41.31 port 41484 ssh2

这表明有人或某些程序试图穷举用户名和密码来进入系统。

如果合法用户需要外部 SSH 访问,修改 SSH的默认访问端口可以提供一些保护。实际上,PF提供了更好的解决方案。 过滤规则可以限制连接主机可以执行的操作,违反者可以被添加到排除地址列表中并限制某些或全部操作。 甚至可以在计算机超出限制时丢弃所有已经建立的连接。

要配置此功能,请在规则的表单元(tables section)中创建表:

table <bruteforce> persist

然后,在规则集的早期,添加规则以阻止暴力访问,同时允许合法访问:

block quick from <bruteforce>
pass inet proto tcp from any to $localnet port $tcp_services \
    flags S/SA keep state \
    (max-src-conn 100, max-src-conn-rate 15/5, \
    overload <bruteforce> flush global)

括号内的部分确定了限制,数字应根据当地的要求进行修改。其内容如下:

max-src-conn 是指一台主机允许同时连接的数量。

max-src-conn-rate是指允许从任何一台主机(15)每秒钟(5)的新连接率。

overload <bruteforce>意味着任何超过这些限制的主机都会被添加到bruteforce表中。该规则集阻止来自bruteforce表中地址的所有流量。

最后,flush global表示,当一个主机达到极限时,该主机的所有(global)连接将被终止(flush)。

注意:

http://home.nuug.no/~peter/hailmary2013/中所述,这些规则将不会阻止慢速暴力破解者。

这个示例规则集主要是作为一个示例。例如,如果一般情况下希望有大量的连接,但希望在涉及到ssh的时候,可以在规则集开头,写入类似规则:

pass quick proto { tcp, udp } from any to any port ssh \
    flags S/SA keep state \
    (max-src-conn 15, max-src-conn-rate 5/3, \
    overload <bruteforce> flush global)

可能不需要阻止所有 Overloader:

值得注意的是,超载机制是一种通用技术,并不完全适用于SSH,完全阻断所有违规者的流量并不总是最佳实践。

例如,过载规则可以用来保护邮件服务或Web服务,而过载表可以在规则中用于将违规者分配到一个队列中,以最小的带宽分配或重定向到一个特定的网页。

随着时间的推移,表会被超载规则填满,表的大小会逐渐增加,占用更多的内存。有时,被屏蔽的IP地址是一个动态分配的地址,此后,该地址被分配给了有合法理由与本地网络中的主机通信的主机。

对于这样的情况,pfctl提供了过期表项的功能。例如,该命令将删除<bruteforce>表中超过86400秒未被引用的条目:

# pfctl -t bruteforce -T expire 86400

security/expiretable也提供了类似的功能,它可以删除在指定时间内未被访问的表项。

安装后,可以运行expiretable来删除<bruteforce>表中超过指定时限的条目。这个例子可以删除所有超过24小时的条目:

/usr/local/sbin/expiretable -v -d -t 24h bruteforce

30.3.2.6. SPAM防护

不要与spamd守护进程混淆,该守护进程与spamassassin捆绑在一起,mail/spamd可以与PF一起配置,以防御外部SPAM。这个spamd使用一组重定向的方式钩住(hook)了PF配置。

垃圾邮件发送者往往会发送大量的信息,SPAM主要是由少数垃圾邮件网络和大量被劫持的机器发送,这两种情况都会被记录到黑名单中。

当收到来自黑名单地址的SMTP连接时,spamd会显示其 banner,并立即切换到单字节回复SMTP流量的模式。这种技术的目的是为了尽可能多地浪费垃圾邮件发送者的时间,它被称为tarpitting。使用一个字节的SMTP回复的具体实现通常被称为stuttering

这个例子演示了设置spamd自动更新黑名单的基本步骤。有关更多信息,请参阅与mail/spamd的手册页。

过程 30.1. 配置 spamd
  1. 从 ports 或 pkg 安装mail/spamd。要使用 spamd的 greylisting 功能,必须将 fdescfs(5)挂载在 /dev/fd。在/etc/fstab中添加以下行:

     fdescfs /dev/fd fdescfs rw 0 0

    然后,挂载文件系统:

    # mount fdescfs
  2. 接下来将下列行加入PF规则列表:

    table <spamd> persist
    table <spamd-white> persist
    rdr pass on $ext_if inet proto tcp from <spamd> to \
        { $ext_if, $localnet } port smtp -> 127.0.0.1 port 8025
    rdr pass on $ext_if inet proto tcp from !<spamd-white> to \
        { $ext_if, $localnet } port smtp -> 127.0.0.1 port 8025

    这两个表 <spamd><spamd-white> 至关重要。从<spamd> 而非 <spamd-white> 中列出的地址的SMTP 流量将会被重定向到 8025 端口的 spamd

  3. 下一步是在/usr/local/etc/spamd.conf中配置spamd,并添加rc.conf参数。

    mail/spamd的安装包括一个示例配置文件(/usr/local/etc/spamd.conf.sampleam)和spamd.conf的man page。除了本例中显示的配置选项外,其他的配置选项请参考这些。

    配置文件中的第一行之一不以#注释符号开头,其中包含定义all列表的块,该列表指定要使用的列表:

    all:\
        :traplist:whitelist:

    此条目将添加所需的黑名单,用冒号(:)分隔。要使用白名单来从黑名单中减去(subtract )地址,请在黑名单的名称后面加上白名单的名称立即(immediately)。例如::blacklist:whitelist:

    接下来指定黑名单定义:

    traplist:\
        :black:\
        :msg="SPAM. Your address %A has sent spam within the last 24 hours":\
        :method=http:\
        :file=www.openbsd.org/spamd/traplist.gz

    其中第一行是黑名单的名称,第二行指定列表类型。msg字段包含在SMTP对话中向黑名单发送者显示的信息。method字段指定了spamd-setup如何获取列表数据;支持的方法有httpftp、从挂载的文件系统中的file和通过外部程序的exec。最后,file字段指定了spamd希望接收的文件名称。

    指定的白名单的定义类似,但省略了msg字段,因为不需要消息:

    whitelist:\
        :white:\
        :method=file:\
        :file=/var/mail/whitelist.txt

    小心的选择数据源:

    使用示例spamd.conf中的所有黑名单将屏蔽一大块互联网连接。管理员需要编辑该文件以创建最佳配置,该配置使用合适的数据源,并在必要时使用自定义列表。

    接下来,将此条目添加到/etc/rc.conf中。其他参数将在其手册页中描述:

    spamd_flags="-v" # use "" and see spamd-setup(8) for flags

    完成后,重新加载规则集,通过键入service obspamd start启动spamd,并使用spamd-setup完成配置。最后,创建cron(8)规则,调用spamd-setup,以合理的时间间隔更新表。

在邮件服务器前的典型网关上,主机很快就会在几秒到几分钟内被困住。

PF还支持greylisting,它可以暂时拒绝来自带有45n代码的未知主机的消息。来自greylisting主机的消息,如果在合理的时间内再次尝试,会被允许通过。来自被设置为在 RFC 1123 和 RFC 2821 所设定的限制范围内的发送者的流量会立即被允许通过。

更多关于 greylisting 技术的信息,可以在greylisting.org网站上找到。greylisting 除了简单之外,最神奇的地方在于它仍然有效。垃圾邮件发送者和恶意软件编写者已经很迟钝地适应了这一技术。

配置灰名单的基本过程如下:

过程 30.2. 配置灰名单
  1. 确保fdescfs(5)按照前面步骤1中的步骤挂载。

  2. 将此行加入到/etc/rc.conf,让spamd以灰名单模式运行:

    spamd_grey="YES"  # use spamd greylisting if YES

    更多相关参数请参阅 spamd 的说明文档。

  3. 完成灰名单设置:

    # service obspamd restart
    # service obspamlogd start

在幕后,spamdb数据库工具和spamlogd白名单更新程序执行灰色列表功能的基本功能。spamdb是管理员的主要界面,用于通过/var/db/spamdb数据库的内容管理黑名单,灰名单和白名单。

30.3.2.7. 网络保健

本章介绍如何正确使用 block-policyscrubantispoof 标签。

block-policy是一个选项,可以在规则集的options部分中设置,该选项在重定向和过滤规则之前。这个选项决定了PF向被规则阻止的主机发送哪些反馈(如果有的话)。该选项有两个可能的值。drop在没有反馈的情况下丢弃被阻止的数据包,而return则返回一个状态代码,例如Connection refused

如果未设置,则默认策略为drop。若要更改block-policy,请指定所需的值:

set block-policy return

PF中,scrub是启用网络数据包正常化的关键字。这个过程会重新组合碎片化的数据包,并丢弃具有无效标志组合的TCP数据包。启用scrub提供了一定程度的保护,以防止基于对数据包碎片的错误处理的某些类型的攻击。有许多选项可供选择,但简单配置即可满足大多数情况:

scrub in all

某些服务,如NFS,需要特定的分片(fragment)处理选项。请参阅https://home.nuug.no/~peter/pf/en/scrub.html了解更多信息。

这个例子重新组合了片段,清除了do not fragment位,并将最大段大小设置为1440字节:

scrub in all fragment reassemble no-df max-mss 1440

antispoof机制主要通过阻断出现在接口上和逻辑上不可能出现的方向的数据包,来防止被欺骗或伪造的IP地址的活动。

这些规则排除了来自世界其他地区和本地的所有欺骗(spoofed)数据包:

antispoof for $ext_if
antispoof for $int_if

30.3.2.8. 处理不可路由(Non-Routable)的位址

即使有一个正确配置的网关来处理网络地址转换,也可能需要弥补别人的错误配置。一个常见的错误配置是让带有不可路由地址的流量出去到互联网上。由于来自不可路由地址的流量会在几种DoS攻击技术中发挥作用,因此考虑明确阻止来自不可路由地址的流量通过外部接口进入网络。

在这个例子中,定义了一个包含不可转发地址的宏,然后在拦截规则中使用。这些地址的流量在网关的外部接口上被悄悄地丢弃。

martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
	      10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
	      0.0.0.0/8, 240.0.0.0/4 }"

block drop in quick on $ext_if from $martians to any
block drop out quick on $ext_if from any to $martians

30.3.3. 开启ALTQ

在 FreeBSD 上,ALTQ可与PF一起使用,以启用 QOS。启用ALTQ后,可以在规则集中自定义流量优先级。

在启用ALTQ之前,请参考altq(4),以确定系统上安装的网卡的驱动程序是否支持该功能。

ALTQ不能作为可加载的内核模块使用。如果系统的接口支持ALTQ,请使用第 8 章 配置 FreeBSD 内核中的说明创建一个自定义内核。以下是可用的内核选项。第一个选项需要启用ALTQ。其他选项中至少需要一个来指定队列调度器算法:

options         ALTQ
options         ALTQ_CBQ        # Class Based Queuing (CBQ)
options         ALTQ_RED        # Random Early Detection (RED)
options         ALTQ_RIO        # RED In/Out
options         ALTQ_HFSC       # Hierarchical Packet Scheduler (HFSC)
options         ALTQ_PRIQ       # Priority Queuing (PRIQ)

可以使用以下调度算法:

CBQ

基于类的队列 (CBQ) 用于将连接的带宽划分为不同的类或队列,以便根据筛选器规则确定流量的优先级。

RED

随机早期检测(RED)通过测量队列的长度,并与队列的最小和最大阈值进行比较,来避免网络拥塞。当队列超过最大值时,所有新的数据包都会被随机丢弃。

RIO

在随机早期检测进出(RIO)模式下,RED保持多个平均队列长度和多个阈值,每个RED都有QOS级别。

HFSC

http://www-2.cs.cmu.edu/~hzhang/HFSC/main.html 中描述了分层公平服务曲线包调度程序(Hierarchical Fair Service Curve Packet Scheduler HFSC)。

PRIQ

优先队列(Priority Queuing,PRIQ)首先允许高优先级队列中的包通过。

更多关于调度算法和规则集使用案例在OpenBSD's web archive可找到。

本文档和其它文档可从这里下载: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读 文档,如不能解决再联系 <questions@FreeBSD.org>.

关于本文档的问题请发信联系 <doc@FreeBSD.org>.