33.3.PF

自 FreeBSD 5.3 以来,OpenBSD 的 PF 防火墙的移植版本已经作为基本系统的一部分包括在内。PF 是一个完整的、功能齐全的防火墙,可选择性地支持 ALTQ(交替排队),提供服务质量(QoS)。

FreeBSD 项目在 PF FAQ 中维护了 PF 的权威参考。Peter Hansteen 在 http://home.nuug.no/~peter/pf/上维护了一份详尽的 PF 教程。

FreeBSD 数据包过滤器邮件列表是一个很好的地方,可以就配置和运行 PF 防火墙提问。在提问之前,请查阅邮件列表存档,因为问题可能已经得到解答。

本手册的这一部分侧重于与 FreeBSD 相关的 PF。它演示了如何启用 PF 和 ALTQ。它还提供了在 FreeBSD 系统上创建规则集的几个示例。

33.3.1. 启用 PF

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

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

# sysrc pf_enable=yes

在启动 PF 时,可以传递在 pfctl(8) 中说明的其他选项。添加或更改 /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)提供。要启用日志支持,请将 pflog_enable=yes 添加到/etc/rc.conf 中:

# sysrc pflog_enable=yes

还可以添加以下行来更改日志文件的默认位置,或者指定启动 pflog(4)时要传递的任何其他标志:

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

最后,如果防火墙后面有一个局域网,并且需要转发局域网上的计算机的数据包,或者需要 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 规则集覆盖,请参阅 PF FAQ。

要控制 PF,请使用 pfctl。有用的 pfctl 选项总结了此命令的一些有用选项。有关所有可用选项的说明,请参阅 pfctl(8):

有用的 pfctl 选项

命令
目的

pfctl -e

启用 PF。

pfctl -d

禁用 PF。

pfctl -F all -f /etc/pf.conf

清除所有 NAT、过滤器、状态和表规则,并重新加载 /etc/pf.conf。

pfctl -s [ rules | nat | states ]

报告过滤规则、NAT 规则或状态表。

pfctl -vnf /etc/pf.conf

检查 /etc/pf.conf 是否有错误,但不要加载规则集。

通过安装 sysutils/pftop 软件包或 port 来监视通过 PF 防火墙的流量。安装完成后,可以运行 pftop 以查看类似于 top(1) 格式的流量运行快照。

33.3.2. PF 规则集

本节演示如何创建自定义规则集。它从最简单的规则集开始,并利用几个示例来演示 PF 的许多功能的实际用法。

最简单的规则集是针对一个不运行任何服务并且需要访问一个网络(可能是互联网)的单个机器。要创建这个最小的规则集,请编辑 /etc/pf.conf,使其如下所示:

block in all
pass out all keep state

第一条规则默认拒绝所有传入流量。第二条规则允许此系统创建的连接通过,同时保留这些连接的状态信息。这些状态信息允许这些连接的返回流量通过,应该仅在可以信任的机器上使用。可以使用以下命令加载规则集:

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

除了保持状态,PF 还提供可以在创建规则时定义的列表和宏。宏可以包含列表,并且需要在使用之前定义。作为示例,在规则集的顶部插入以下行:

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

PF 了解port名称以及port数字,只要这些名称在/etc/services 中列出即可。此示例创建两个宏。第一个是七个 TCP port名称的列表,第二个是一个 UDP port名称。若定义,宏就可以在规则中使用。在此示例中,除了由该系统发起的与七个指定的 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 被禁用,要么加载了新的规则集。

33.3.2.1. 简单的带 NAT 的网关

本节演示如何配置运行 PF 的 FreeBSD 系统作为至少一台其他计算机的网关。网关需要至少两个网络接口,每个接口连接到一个独立的网络。在此示例中,xl0 连接到互联网,xl1 连接到内部网络。

首先,启用网关功能,使机器能够将其在一个接口上接收到的网络流量转发到另一个接口。此 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 规则以允许网关传输流量。虽然以下规则允许来自内部网络主机的有状态流量传输到网关,但 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 接口。

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 地址的网络地址转换。nat 规则 ($ext_if) 的最后一部分周围的括号是在外部接口的 IP 地址动态分配时包含的。它确保即使外部 IP 地址发生变化,网络流量也可以顺利运行,而不会出现严重中断。

请注意,该规则集可能允许更多的流量通过网络而无需。一个合理的设置可以创建这个宏:

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

用于主要访问规则中:

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

这个宏定义和规则允许内部客户端的 DNS 和 NTP:

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

在此规则中注意 quick 关键字。由于规则集包含多个规则,因此理解规则集中规则之间的关系至关重要。规则按照编写顺序从上到下进行评估。对于 PF 评估的每个数据包或连接,规则集中最后匹配的规则将被应用。然而,当数据包匹配包含 quick 关键字的规则时,规则处理将停止,并根据该规则处理数据包。在需要一般规则的例外情况下,这非常有用。

33.3.2.2. 创建 FTP 代理

由于 FTP 协议的性质,配置工作中的 FTP 规则可能会出现问题。FTP 的设计早于防火墙数十年,并且在设计上是不安全的。使用 FTP 的最常见问题包括:

  • 密码是明文传输的。

  • 该协议要求在单独的 ports 上使用至少两个 TCP 连接(控制和数据)。

  • 当建立会话时,数据使用随机选择的 ports 进行通信。

所有这些点都存在安全挑战,甚至在考虑客户端或服务器软件中的任何潜在安全弱点之前。存在更安全的文件传输替代方案,如 sftp(1)或 scp(1),两者均具有身份验证和在加密连接上进行数据传输的功能。

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

要启用 FTP 代理,请将以下行添加到/etc/rc.conf 中:

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 流量分配到特定队列。

关于运行由 PF 和 ftp-proxy(8) 保护的 FTP 服务器的方法,请在反向模式下配置单独的 ftp-proxy,使用 -R,在具有自身重定向传递规则的单独 port 上。

33.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 系统上使用 ICMP 回显请求消息,因此只需要第一条规则来允许从这些系统中获取网络跟踪信息。Unix traceroute 也可以指示使用其他协议,并且如果使用 -I,它将使用 ICMP 回显请求消息。详细信息请查阅 traceroute(8)手册页。

33.3.2.3.1. 路径 MTU 发现

互联网协议设计为设备独立,设备独立的一个结果是,对于给定连接,不能始终可靠地预测最佳数据包大小。数据包大小的主要限制是最大传输单元(MTU),它为接口设置了数据包大小的上限。输入 ifconfig 以查看系统网络接口的 MTU。

TCP/IP 使用一种称为路径 MTU 发现的过程来确定连接的正确数据包大小。该过程发送不同大小的数据包,并设置“不分段”标志,期望当达到上限时收到“类型 3,代码 4”的 ICMP 返回数据包。类型 3 表示“目的地不可达”,代码 4 缩写为“需要分段,但已设置不分段标志”。为了允许路径 MTU 发现以支持到其他 MTU 的连接,请将 destination unreachable 类型加入到 icmp_types 宏中:

icmp_types = "{ echoreq, unreach }"

由于通过规则已经使用了该宏,因此不需要修改以支持新的 ICMP 类型:

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

PF 允许对所有 ICMP 类型和代码的所有变体进行过滤。可用的类型和代码列表在 icmp(4) 和 icmp6(4) 中有记录。

使用表格

一些类型的数据在特定时间对过滤和重定向是相关的,但它们的定义太长,无法包含在规则集文件中。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

注意,通过这种方式进行的任何更改将立即生效,使它们成为测试的理想选择,但在断电或重启后将无法保存。要使更改永久生效,请修改规则集中表的定义或编辑表所引用的文件。可以使用类似于 pfctl -t clients -T show >/etc/clients 的命令维护表的磁盘副本,以便定期将表的内容转储到磁盘上,例如通过 cron(8) 作业。或者,/etc/clients 可以使用内存中的表内容进行更新:

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

33.3.2.5。使用过载表保护 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 使用的默认port可以提供一些保护。然而,PF 提供了一个更加优雅的解决方案。传递规则可以包含连接主机可以做什么的限制,违规者可以被放逐到一个被拒绝一些或全部访问的地址表中。甚至可以删除超出限制的机器的所有现有连接。

要配置这个,请在规则集的表部分创建这个表:

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 表中地址的流量。

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

该示例规则集主要用作示例。例如,如果一般希望有大量连接,但希望在涉及 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)

拦截所有超载者可能并不是必要的。 值得注意的是,过载机制是一种通用技术,不仅适用于 SSH,并不一定总是最佳的选择,全面阻止来自攻击者的所有流量。 例如,过载规则可用于保护邮件服务或 Web 服务,过载表可用于规则中将攻击者分配到带有最小带宽分配的队列或重定向到特定网页。

随着时间推移,表将被过载规则填满,其大小将逐渐增长,占用更多内存。有时,被阻止的 IP 地址是一个动态分配的地址,已被分配给有正当理由与本地网络中的主机通信的主机。

对于这种情况,pfctl 提供了过期表项的功能。例如,此命令将删除 表项,这些表项在 86400 秒内未被引用:

# pfctl -t bruteforce -T expire 86400

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

安装后,可以运行 expiretable 来删除超过指定时间的 表项。此示例将删除所有超过 24 小时的表项:

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

33.3.2.6. 防止垃圾邮件

不要与 spamassassin 捆绑的 spam 守护进程混淆,mail/spamd 可以配置 PF 以提供对垃圾邮件的外部防御。这个 spam 守护进程使用一组重定向钩入 PF 配置。

垃圾邮件发送者倾向于发送大量消息,垃圾邮件主要来自一些垃圾邮件友好的网络和大量被劫持的机器,这两者都很快被报告到封锁名单。

当从黑名单中的地址接收到一个 SMTP 连接时,spamd 会呈现其横幅,并立即切换到一次一个字节地回答 SMTP 流量的模式。这种旨在尽可能浪费垃圾邮件发送者时间的技术称为 tarpitting。使用一字节 SMTP 回复的具体实现通常被称为 stuttering。

该示例演示了设置带有自动更新的黑名单的 spamd 的基本过程。有关更多信息,请参考与 mail/spamd 一起安装的 man 页面。

过程:配置 spamd

  1. 安装 mail/spamd 软件包或port。要使用 spamd 的灰名单功能,必须在/dev/fd 下挂载 fdescfs(5)。向/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

    两个表 和 是必不可少的。来自 中列出的地址的 SMTP 流量,但不在 中列出的地址,将被重定向到监听在port 8025 端口的 spamd 守护程序。

  3. 下一步是在 /usr/local/etc/spamd.conf 中配置 spamd,并添加一些 rc.conf 参数。安装 mail/spamd 包括一个示例配置文件(/usr/local/etc/spamd.conf.sample)和一个 spamd.conf 的 man 手册页。请参考这些内容以获取本示例中未显示的其他配置选项。 配置文件中的第一行不以 # 注释符号开头,包含定义 all 列表的块,该列表指定要使用的列表:

    all:\
        :traplist:allowlist:

    此条目通过冒号分隔的所需块列表( : )进行添加。若要使用允许列表从块列表中减去地址,请在该块列表名称后面立即添加允许列表的名称。例如: :blocklist:allowlist:。

    接下来是指定块列表定义的部分:

    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 字段指定 spam 安装程序获取列表数据的方式;支持的方法有 http,ftp,从挂载文件系统中的 file,以及通过外部程序的 exec。最后,file 字段指定 spam 所期望接收的文件名称。

    指定允许列表的定义类似,但省略了 msg 字段,因为不需要消息:

    allowlist:\
        :white:\
        :method=file:\
        :file=/var/mail/allowlist.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 还支持灰名单,它暂时拒绝来自带有 45n 代码的未知主机的消息。在合理的时间内再次尝试的灰名单主机的消息将被放行。符合 RFC 1123 和 RFC 2821 设置的发件人的流量将立即通过。

有关灰名单技术的更多信息可以在 greylisting.org 网站找到。除了其简单性之外,最令人惊讶的是它仍然有效。垃圾邮件发送者和恶意软件作者一直很慢地适应绕过这种技术。

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

配置灰名单

  1. 确保 fdescfs(5) 挂载方式如上一个步骤 1 中所述的那样。

  2. 要在灰名单模式下运行 spamd,请将此行添加到 /etc/rc.conf:

    spamd_grey="YES"  # use spamd greylisting if YES

    参考 spamd 手册以获取有关其他相关参数的说明。

  3. 完成灰名单设置:

    #  service obspamd restart
    #  service obspamlogd start

在幕后,spamdb 数据库工具和 spamlogd 白名单更新器对于灰名单功能起着重要作用。通过/var/db/spamdb 数据库的内容,spamdb 是管理员管理阻止、灰色和允许列表的主要界面。

33.3.2.7. 网络卫生

本节说明了如何使用 block-policy,scrub 和 antispoof 使规则集的行为变得合理。

block-policy 是可以在规则集的 options 部分设置的选项,该部分位于重定向和过滤规则之前。此选项确定 PF 阻止规则的主机发送哪些反馈(如果有)。该选项有两个可能的值: drop 丢弃阻止的数据包而不发送反馈,return 返回诸如 Connection refused 之类的状态码。

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

set block-policy return

在 PF 中,scrub 是一个启用网络数据包规范化的关键字。此过程重新组装碎片包并丢弃具有无效标志组合的 TCP 包。启用 scrub 提供了一定程度的保护,防止基于错误处理包碎片的某些类型的攻击。提供了许多选项,但最简单的形式适用于大多数配置:

scrub in all

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

此示例重新组装片段,清除“不要分段”位,并将最大段大小设置为 1440 字节。

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

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

这些规则排除来自世界其他地方的伪造流量以及源于本地网络的任何伪造数据包。

antispoof for $ext_if
antispoof for $int_if

33.3.2.8. 处理非可路由地址

即使配置了正确的网关来处理网络地址转换,一个人可能还需要补偿其他人的错误配置。一个常见的错误配置是允许带有非可路由地址的流量进入互联网。由于来自非可路由地址的流量可能在几种 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

在 FreeBSD 上启用 ALTQ

在 FreeBSD 上,ALTQ 可以与 PF 一起使用,提供服务质量(QOS)。若启用 ALTQ,可以在规则集中定义队列,这些队列确定出站数据包的处理优先级。

在启用 ALTQ 之前,请参考 altq(4)以确定系统上安装的网络适配器驱动是否支持它。

ALTQ 不可用作为可加载的内核模块。如果系统的接口支持 ALTQ,请使用“配置 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

在随机早期检测(RED)的内部和外部(RIO)模式中,RED 维护多个平均队列长度和多个阈值,每个 QOS 级别一个。

HFSC

分层公平服务曲线数据调度器(HFSC)的说明请查看 http://www-2.cs.cmu.edu/~hzhang/HFSC/main.html。

PRIQ

优先级队列(PRIQ)始终优先传输处于较高队列中的流量。

有关调度算法和示例规则集的更多信息可在 OpenBSD 的网络存档中找到。

最后更新于

FreeBSD 中文社区