第三十三章 防火墙33.1. 简介33.2. 防火墙概念33.3. PF33.3.1. 启用PF33.3.2. PF规则33.3.2.1. 一个简单的NAT网关33.3.2.2. 创建一个FTP代理33.3.2.3. 管理ICMP33.3.2.3.1. 路径MTU发现33.3.2.4. 使用表33.3.2.5. 使用过载表保护SSH33.3.2.6. 防止垃圾邮件33.3.2.7. 网络卫生33.3.2.8. 处理非路由地址33.3.3. 启用ALTQ33.4. IPFW33.4.1. 启用IPFW33.4.2. IPFW规则语法33.4.3. 规则集示例34.4.4. 内核内NAT33.4.4.1. 端口重定向33.4.4.2. 地址重定向33.4.4.3. 用户空间NAT33.4.5. IPFW命令33.4.5.1. 记录防火墙消息33.4.5.2. 构建规则脚本33.4.6. IPFW内核选项33.5. IPFILTER(IPF)33.5.1. 启用IPF33.5.2. IPF规则语法33.5.3. 规则集示例33.5.4. 配置NAT33.5.5. 查看IPF统计信息33.5.6. IPF日志记录33.6. Blacklistd33.6.1. 启用 blacklistd33.6.2. 创建一个blacklistd规则集33.6.2.1. 本地规则33.6.2.2. 远程规则33.6.3. blacklistd客户端配置33.6.4. blacklistd管理33.6.5. 从黑名单中移除主机
防火墙可以过滤流经系统的传入和传出流量。防火墙可以使用一组或多组“规则”来检查网络数据包进出网络连接的情况,并允许流量通过或阻止它。防火墙的规则可以检查数据包的一个或多个特征,如协议类型、源或目标主机地址以及源或目标端口。
防火墙可以增强主机或网络的安全性。它们可用于执行以下一项或多项操作:
• 保护和隔离内部网络的应用程序、服务和机器,使其免受公共互联网的不必要流量的影响。 • 限制或禁止内部网络主机访问公共互联网服务。 • 支持网络地址转换(network address translation,NAT),它允许内部网络使用私有IP地址,并使用单个IP地址或自动分配的公共地址共享池共享到公共互联网的单个连接。
FreeBSD在基础系统中内置了三个防火墙:PF、IPFW和IPFILTER,也称为IPF。FreeBSD还提供了两个流量整形器来控制带宽使用:altq(4) 和 dummynet(4) 。ALTQ传统上与PF密切相关,dummynet与IPFW密切相关。每个防火墙都使用规则来控制数据包对FreeBSD系统的访问,尽管它们以不同的方式进行,并且每个防火墙都有不同的规则语法。
FreeBSD提供了多种防火墙,以满足各种用户的不同要求和偏好。每个用户都应该评估哪种防火墙最能满足他们的需求。
阅读本章后,你会知道: • 如何定义数据包过滤规则。 • FreeBSD内置防火墙之间的差异。 • 如何使用和配置PF防火墙。 • 如何使用和配置IPFW防火墙。 • 如何使用和配置IPFILTER防火墙。
在阅读本章之前,您应该: • 了解基本的FreeBSD和互联网概念。
xxxxxxxxxx由于所有防火墙都基于检查所选数据包控制字段的值,因此防火墙规则集的创建者必须了解TCP/IP是如何工作的,数据包控制域中的不同值是什么,以及这些值在正常会话对话中是如何使用的。有关详细介绍,请参阅 Daryl的TCP/IP入门。规则集包含一组规则,这些规则根据数据包中包含的值传递或阻止数据包。主机之间的双向数据包交换包括会话对话。防火墙规则集既处理来自公共互联网的数据包,也处理系统作为响应而产生的数据包。每个TCP/IP服务都由其协议和侦听端口预定义。发往特定服务的数据包来自源地址,使用非特权端口,并以目标地址上的特定服务端口为目标。所有上述参数都可以用作选择标准,以创建传递或阻止服务的规则。
要查找未知的端口号,请参阅/etc/services。或者,访问 https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers 并进行端口号查找以找到特定端口号的用途。
请查看此链接,了解 特洛伊木马使用的端口号 。
FTP有两种模式:主动模式和被动模式。区别在于如何获取数据通道。被动模式更安全,因为数据通道是由顺序ftp会话请求者获取的。有关FTP和不同模式的详细说明,请参阅 http://www.slacksite.com/other/ftp.html 。
防火墙规则集可以是 exclusive 或 inclusive 的。
inclusive防火墙可以更好地控制传出流量,使其成为向公共互联网提供服务的系统的更好选择。它还控制可以访问专用网络的来自公共互联网的流量类型。所有不符合规则的流量都会被阻止并记录。inclusive防火墙通常比 exclusive防火墙更安全,因为它们大大降低了允许不必要流量的风险。
xxxxxxxxxx除非另有说明,否则本章中的所有配置和示例规则集都创建了inclusive的防火墙规则集。使用“状态防火墙(stateful firewall)”可以进一步加强安全性。这种类型的防火墙会跟踪打开的连接,只允许与现有连接匹配或打开新的、允许的连接的流量。
状态过滤将流量视为包含会话的数据包的双向交换。当在匹配规则上指定状态时,防火墙会为会话期间交换的每个预期数据包动态生成内部规则。它具有足够的匹配能力来确定数据包是否对会话有效。任何不符合会话模板的数据包都会被自动拒绝。
会话完成后,它将从动态状态表中删除。
状态过滤允许人们专注于阻止/传递新会话。如果新会话通过,则自动允许其所有后续数据包,并自动拒绝任何冒名顶替数据包。如果新会话被阻止,则不允许其后续数据包。状态过滤提供了高级匹配能力,能够防御攻击者采用的大量不同攻击方法。
NAT代表网络地址转换(Network Address Translation)。NAT功能使防火墙后的专用LAN能够共享单个ISP分配的IP地址,即使该地址是动态分配的。NAT允许局域网中的每台计算机都可以访问互联网,而无需向ISP支付多个互联网帐户或IP地址的费用。
当数据包离开防火墙,进入公共互联网时,NAT会自动将局域网上每个系统的专用局域网IP地址转换为单个公共IP地址。它还对返回的数据包执行反向转换。
根据RFC 1918,以下IP地址范围是为专用网络保留的,这些专用网络永远不会直接路由到公共互联网,因此可用于NAT:
• 10.0.0.0/8. • 172.16.0.0/12. • 192.168.0.0/16.
xxxxxxxxxx使用防火墙规则时,要非常小心。某些配置可能会将管理员锁定在服务器之外。为了安全起见,考虑从本地控制台执行初始防火墙配置,而不是通过ssh远程执行。自FreeBSD 5.3以来,OpenBSD PF防火墙的移植版本已作为基础系统的集成部分包含在内。PF是一个完整、功能齐全的防火墙,可选择支持ALTQ(Alternate Queuing,备用队列),提供服务质量(Quality of Service,QoS)。
OpenBSD项目在 PF FAQ 中保留了PF的权威参考。Peter Hansteen在 https://home.nuug.no/~peter/pf/ 有一个全面的PF教程。
xxxxxxxxxx在阅读PF常见问题解答时,请记住,多年来,FreeBSD版本的PF与上游的OpenBSD版本存在很大差异。并非所有功能在FreeBSD上的工作方式都与在OpenBSD中的工作方式相同,反之亦然。FreeBSD包过滤器邮件列表 是询问有关配置和运行PF防火墙的问题的好地方。在提问之前,请检查邮件列表档案,因为它可能已经得到了回答。
本手册的这一部分重点介绍PF,因为它与FreeBSD有关。它演示了如何启用PF和ALTQ。它还提供了几个在FreeBSD系统上创建规则集的示例。
要使用PF,必须首先加载其内核模块。本节介绍可以添加到 /etc/rc.conf 以启用PF的条目。
首先在 /etc/rc.conf 中添加 pf_enable=yes :
xxxxxxxxxx# sysrc pf_enable=yes启动PF时,可以将 pfctl(8) 中描述的其他选项传递给PF。在 /etc/rc.conf 中添加或更改此条目,并在两个引号(“”)之间指定任何所需的标志:
xxxxxxxxxxpf_flags="" # additional flags for pfctl startup如果找不到规则集配置文件,PF将不会启动。默认情况下,FreeBSD不附带规则集,也没有 /etc/pf.conf 。示例规则集可以在 /usr/share/Example.pf/ 中找到。如果自定义规则集已保存在其他位置,请在 /etc/rc.conf 中添加一行,指定文件的完整路径:
xxxxxxxxxxpf_rules="/path/to/pf.conf"PF的日志支持由 pflog(4) 提供。要启用日志支持,请在 /etc/rc.conf 中添加pflog_enable=yes :
xxxxxxxxxx# sysrc pflog_enable=yes还可以添加以下行来更改日志文件的默认位置,或指定启动 pflog(4) 时传递给 pflog 的任何其他标志:
xxxxxxxxxxpflog_logfile="/var/log/pflog" # where pflogd should store the logfilepflog_flags="" # additional flags for pflogd startup最后,如果防火墙后面有一个局域网,并且需要为局域网上的计算机转发数据包,或者需要NAT,请启用以下选项:
xxxxxxxxxxgateway_enable="YES" # Enable as LAN gateway保存所需的编辑后,可以通过键入以下命令启动PF并支持日志记录:
xxxxxxxxxx# service pf start# service pflog start默认情况下,PF从 /etc/PF.conf 读取其配置规则,并根据此文件中指定的规则或定义修改、删除或传递数据包。FreeBSD安装包括位于 /usr/share/examples/pf/ 中的几个示例文件。有关PF规则集的完整介绍,请参阅 PF常见问题解答 。
要控制PF,请使用 pfctl 。下表总结了此命令的一些有用选项。有关所有可用选项的说明,请参阅 pfctl(8) :
| 命令 | 目的 |
|---|---|
| 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 是否有错误,但不要加载规则集。 |
xxxxxxxxxxsecurity/sudo对于运行需要提升权限的pfctl等命令非常有用。它可以从端口集合中安装。要监视通过PF防火墙的流量,请考虑安装 sysutils/pftop 包或端口。安装后,可以运行 pftop 以类似于 top(1) 的格式查看流量的运行快照。
本节演示如何创建自定义规则集。它从最简单的规则集开始,并使用几个例子来演示PF的许多功能在现实世界中的使用。
最简单的规则集适用于不运行任何服务并且需要访问一个网络(可能是互联网)的单台机器。要创建这个最小规则集,请编辑 /etc/pf.conf ,使其看起来像这样:
xxxxxxxxxxblock in allpass out all keep state第一条规则默认情况下拒绝所有传入流量。第二条规则允许此系统创建的连接传递出去,同时保留这些连接的状态信息。此状态信息允许这些连接的返回流量返回,并且只应在可信任的机器上使用。规则集可以加载以下内容:
xxxxxxxxxx# pfctl -e ; pfctl -f /etc/pf.conf除了保持状态外,PF还提供了 list(列表)和 macros(宏),可以在创建规则时定义使用。宏可以包含列表,需要在使用前进行定义。例如,在规则集的最顶部插入以下行:
xxxxxxxxxxtcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"udp_services = "{ domain }"PF理解端口名和端口号,只要这些名称列在 /etc/services 中。此示例创建了两个宏。第一个是七个TCP端口名的列表,第二个是一个UDP端口名。一旦定义,宏就可以在规则中使用。在此示例中,除了此系统为七个指定的TCP服务和一个指定的UDP服务发起的连接外,所有流量都被阻止:
xxxxxxxxxxtcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"udp_services = "{ domain }"block allpass out proto tcp to any port $tcp_services keep statepass proto udp to any port $udp_services keep state尽管UDP被认为是一种无状态协议,但PF能够跟踪一些状态信息。例如,当传递一个向名称服务器询问域名的UDP请求时,PF将监视响应以将其传递回去。
每当对规则集进行编辑时,都必须加载新规则以便使用:
xxxxxxxxxx# pfctl -f /etc/pf.conf如果没有语法错误, pfctl 在规则加载期间将不会输出任何消息。在尝试加载规则之前,也可以对其进行测试:
xxxxxxxxxx# pfctl -nf /etc/pf.conf包含 -n 会导致仅解释规则,而不加载规则。这为纠正任何错误提供了机会。在任何时候,加载的最后一个有效规则集都将被强制执行,直到禁用PF或加载新规则集为止。
xxxxxxxxxx在pfctl规则集验证或加载中添加-v将以加载的方式显示完全解析的规则。这在调试规则时非常有用。本节演示如何配置运行PF的FreeBSD系统,使其充当至少一台其他机器的网关。网关需要至少两个网络接口,每个接口都连接到一个单独的网络。在这个例子中,xl0 连接到互联网,xl1 连接到内部网络。
首先,启用网关,让机器将它在一个接口上接收到的网络流量转发到另一个接口。此 sysctl 设置将转发IPv4数据包:
xxxxxxxxxx# sysctl net.inet.ip.forwarding=1要转发IPv6流量,请使用:
xxxxxxxxxx# sysctl net.inet6.ip6.forwarding=1要在系统启动时启用这些设置,请使用 sysrc(8) 将它们添加到 /etc/rc.conf :
xxxxxxxxxx# sysrc gateway_enable=yes# sysrc ipv6_gateway_enable=yes使用 ifconfig 验证这两个接口是否都已启动并正在运行。
接下来,创建PF规则以允许网关传递流量。虽然以下规则允许来自内部网络主机的有状态流量传递到网关,但 to 关键字并不能保证从源到目标的全程传递:
xxxxxxxxxxpass in on xl1 from xl1:network to xl0:network port $ports keep state该规则只允许流量通过内部接口进入网关。为了让数据包更进一步,需要一个匹配规则:
xxxxxxxxxxpass out on xl0 from xl1:network to xl0:network port $ports keep state虽然这两条规则会奏效,但很少需要这种特定的规则。对于繁忙的网络管理员来说,可读的规则集是更安全的规则集。本节的其余部分将演示如何尽可能简单地保持规则的可读性。例如,这两条规则可以替换为一条规则:
xxxxxxxxxxpass from xl1:network to any port $ports keep stateinterface:network 符号可以用宏代替,使规则集更具可读性。例如, $localnet 宏可以定义为直接连接到内部接口的网络($xl1:network)。或者,可以将 $localnet 的定义更改为IP地址/网络掩码表示法来表示网络,例如 192.168.100.1/24 表示私有地址的子网。
如果需要,$localnet 甚至可以定义为网络列表。无论具体需要什么,在典型的传递规则中都可以使用合理的 $localnet 定义,如下所示:
xxxxxxxxxxpass from $localnet to any port $ports keep state以下示例规则集允许内部网络上的计算机发起的所有流量。它首先定义了两个宏来表示网关的外部和内部3COM接口。
xxxxxxxxxx对于拨号用户,外部接口将使用tun0。对于ADSL连接,特别是那些使用以太网PPP(PPPoE)的连接,正确的外部接口是tun0,而不是物理以太网接口。xxxxxxxxxxext_if = "xl0" # macro for external interface - use tun0 for PPPoEint_if = "xl1" # macro for internal interfacelocalnet = $int_if:network# ext_if IP address could be dynamic, hence ($ext_if)nat on $ext_if from $localnet to any -> ($ext_if)block allpass from { lo0, $localnet } to any keep state此规则集引入了 nat 规则,用于处理从内部网络内的不可路由地址到分配给外部接口的IP地址的网络地址转换。当动态分配外部接口的IP地址时,包括 nat 规则最后一部分($ext_if)周围的括号。它确保即使外部IP地址发生变化,网络流量也不会严重中断。
请注意,此规则集可能允许比所需更多的流量流出网络。一个合理的设置可以创建此宏:
xxxxxxxxxxclient_out = "{ ftp-data, ftp, ssh, domain, pop3, auth, nntp, http, \ https, cvspserver, 2628, 5999, 8000, 8080 }"在主通行证规则中使用:
xxxxxxxxxxpass inet proto tcp from $localnet to any port $client_out \ flags S/SA keep state可能还需要一些其他通行规则。此选项在外部接口上启用SSH:
xxxxxxxxxxpass in inet proto tcp to $ext_if port ssh此宏定义和规则允许内部客户端使用DNS和NTP:
xxxxxxxxxxudp_services = "{ domain, ntp }"pass quick inet proto { tcp, udp } to any port $udp_services keep state请注意此规则中的 quick 关键字。由于规则集由多个规则组成,因此了解规则集中规则之间的关系非常重要。规则按照编写顺序从上到下进行评估。对于PF评估的每个数据包或连接,规则集中的最后一个匹配规则是应用的规则。然而,当数据包与包含 quick 关键字的规则匹配时,规则处理停止,数据包将根据该规则进行处理。当需要对一般规则进行例外处理时,这非常有用。
由于FTP协议的性质,配置工作FTP规则可能会有问题。FTP比防火墙早几十年,在设计上是不安全的。反对使用FTP的最常见点包括:
• 密码以明文形式传输。 • 协议要求在单独的端口上使用至少两个TCP连接(控制和数据)。 • 会话建立后,使用随机选择的端口进行数据通信。
所有这些点都带来了安全挑战,甚至在考虑客户端或服务器软件中的任何潜在安全漏洞之前。存在更安全的文件传输替代方案,例如 sftp(1) 或 scp(1) ,它们都具有身份验证和加密连接上的数据传输功能。
对于需要FTP的情况,PF将FTP流量重定向到一个名为 ftp-proxy(8) 的小型代理程序,该程序包含在FreeBSD的基本系统中。代理的作用是使用一组锚点在规则集中动态插入和删除规则,以正确处理FTP流量。
要启用FTP代理,请将此行添加到 /etc/rc.conf :
xxxxxxxxxxftpproxy_enable="YES"然后运行以下命令启动代理:
xxxxxxxxxx# service ftp-proxy start对于基本配置,需要在 /etc/pf.conf 中添加三个元素。首先,代理将用于插入为FTP会话生成的规则的锚点:
xxxxxxxxxxnat-anchor "ftp-proxy/*"rdr-anchor "ftp-proxy/*"其次,需要一个通行规则来允许FTP流量进入代理。
第三,在过滤规则之前,需要定义重定向和NAT规则。在 nat 规则之后立即插入此 rdr 规则:
xxxxxxxxxxrdr pass on $int_if proto tcp from any to any port ftp -> 127.0.0.1 port 8021最后,允许重定向的流量通过:
xxxxxxxxxxpass out proto tcp from $proxy to any port ftp其中 $proxy 扩展到代理守护进程绑定到的地址。
保存 /etc/pf.conf ,加载新规则,并从客户端验证FTP连接是否正常工作:
xxxxxxxxxx# pfctl -f /etc/pf.conf此示例涵盖了本地网络中的客户端需要联系其他地方的FTP服务器的基本设置。这种基本配置应该适用于FTP客户端和服务器的大多数组合。如 ftp-proxy(8) 所示,通过在 ftpproxy_flags= 行中添加选项,可以以各种方式更改代理的行为。某些客户端或服务器可能具有必须在配置中补偿的特定怪癖,或者可能需要以特定方式集成代理,例如将FTP流量分配给特定队列。
对于运行受PF和 ftp-proxy(8) 保护的FTP服务器的方法,请在具有自己的重定向传递规则的单独端口上使用 -R 以反向模式配置单独的FTP代理。
许多用于调试或排除TCP/IP网络故障的工具都依赖于互联网控制消息协议(Internet Control Message Protocol,ICMP),ICMP是专门为调试而设计的。
ICMP协议在主机和网关之间发送和接收控制消息,主要是向发送方提供有关通往目标主机的任何异常或困难情况的反馈。路由器在通常称为路径MTU发现(path MTU discovery)的过程中使用ICMP来协商数据包大小和其他传输参数。
从防火墙的角度来看,一些ICMP控制消息容易受到已知攻击媒介的攻击。此外,让所有诊断流量无条件通过会使调试更容易,但也会使其他人更容易提取有关网络的信息。由于这些原因,以下规则可能不是最优的:
xxxxxxxxxxpass inet proto icmp from any to any一种解决方案是让来自本地网络的所有ICMP流量通过,同时停止来自网络外部的所有探测:
xxxxxxxxxxpass inet proto icmp from $localnet to any keep statepass inet proto icmp from any to $ext_if keep state还有其他选项可供选择,展示了PF的一些灵活性。例如,可以指定 ping(8) 和 traceroute(8) 使用的消息,而不是允许所有ICMP消息。首先为该类型的消息定义一个宏:
xxxxxxxxxxicmp_types = "echoreq"以及使用宏的规则:
xxxxxxxxxxpass 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 :
xxxxxxxxxx# 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回显请求消息,因此只需要第一条规则就可以允许来自这些系统的网络跟踪。Unix traceroute 也可以被指示使用其他协议,如果使用 -I ,它将使用ICMP回显请求消息。有关详细信息,请查看 traceroute(8) 手册页。
互联网协议被设计为独立于设备,设备独立性的一个后果是,给定连接的最佳数据包大小并不总是能够可靠地预测。数据包大小的主要约束是最大传输单元(Maximum Transmission Unit,MTU),它为接口设置了数据包大小上限。键入 ifconfig 查看系统网络接口的MTU。
TCP/IP使用称为路径MTU发现(path MTU discovery)的过程来确定连接的正确数据包大小。此过程发送不同大小的数据包,并设置“Do not fragment”(不分段)标志,当达到上限时,预期ICMP返回数据包为"type 3, code 4”。type 3表示“目的地不可达”, code 4是“需要fragmentation,但设置了do-not-fragment标志”的缩写。要允许路径MTU发现以支持与其他MTU的连接,请将目标不可达类型添加到 icmp_types 宏中:
xxxxxxxxxxicmp_types = "{ echoreq, unreach }"由于传递规则已经使用了该宏,因此不需要对其进行修改以支持新的ICMP类型:
xxxxxxxxxxpass inet proto icmp all icmp-type $icmp_types keep statePF允许对ICMP类型和代码的所有变体进行过滤。可能的类型和代码列表记录在 icmp(4) 和 icmp6(4) 中。
某些类型的数据与特定时间的过滤和重定向有关,但它们的定义太长,无法包含在规则集文件中。PF支持使用表,表是定义的列表,可以在不重新加载整个规则集的情况下进行操作,并且可以提供快速查找。表名始终包含在 < > 中,如下所示:
xxxxxxxxxxtable <clients> { 192.168.2.0/24, !192.168.2.5 }在此示例中,192.168.2.0/24 网络是表的一部分,但地址 192.168.2.5 除外,该地址使用 ! 操作符。也可以从每个项目都在单独一行的文件中加载表,如本例 /etc/clients 所示:
xxxxxxxxxx192.168.2.0/24!192.168.2.5要引用该文件,请按如下方式定义表:
xxxxxxxxxxtable <clients> persist file "/etc/clients"定义表后,可以通过规则引用它:
xxxxxxxxxxpass inet proto tcp from <clients> to any port $client_out flags S/SA keep state可以使用 pfctl 实时操纵表的内容。此示例将另一个网络添加到表中:
xxxxxxxxxx# pfctl -t clients -T add 192.168.1.0/16请注意,以这种方式进行的任何更改现在都会生效,使其成为测试的理想选择,但在电源故障或重新启动后将无法生存。要使更改永久化,请在规则集中修改表的定义或编辑表引用的文件。可以使用 cron(8) 作业来维护表的磁盘副本,该作业使用 pfctl -t clients -T show >/etc/clients 等命令定期将表的内容转储到磁盘。或者,可以用内存中的表内容更新 /etc/clients :
xxxxxxxxxx# pfctl -t clients -T replace -f /etc/clients在外部接口上运行SSH的人可能在身份验证日志中看到过这样的内容:
xxxxxxxxxxSep 26 03:12:34 skapet sshd[25771]: Failed password for root from 200.72.41.31 port 40992 ssh2Sep 26 03:12:34 skapet sshd[5279]: Failed password for root from 200.72.41.31 port 40992 ssh2Sep 26 03:12:35 skapet sshd[5279]: Received disconnect from 200.72.41.31: 11: Bye ByeSep 26 03:12:44 skapet sshd[29635]: Invalid user admin from 200.72.41.31Sep 26 03:12:44 skapet sshd[24703]: input_userauth_request: invalid user adminSep 26 03:12:44 skapet sshd[24703]: Failed password for invalid user admin from 200.72.41.31 port 41484 ssh2这表示有人或某个程序试图发现用户名和密码,从而进入系统,这是一种暴力攻击。
如果合法用户需要外部SSH访问,更改SSH使用的默认端口可以提供一些保护。然而,PF提供了一种更优雅的解决方案。通行规则可以包含对连接主机可以做什么的限制,违反者可以被驱逐到一个地址表中,该表拒绝部分或全部访问。甚至可以删除超出限制的机器的所有现有连接。
要配置此项,请在规则集的表部分创建此表:
xxxxxxxxxxtable <bruteforce> persist然后,在规则集的早期,添加规则来阻止暴力访问,同时允许合法访问:
xxxxxxxxxxblock 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
是每秒数(5)允许来自任何单个主机(15)的新连接的速率。
overload <bruteforce>
意味着任何超过这些限制的主机都会将其地址添加到 brutforce 表中。规则集阻止来自 brutforce 表中地址的所有流量。
flush global
当主机达到限制时,该主机的所有(global)连接都将被终止(flush)。
xxxxxxxxxx这些规则不会阻止缓慢的野蛮人(bruteforcers),如http://home.nuug.no/~peter/hailmary2013/。此示例规则集主要用于说明。例如,如果通常需要大量的连接,但希望在ssh方面有更严格的限制,请在规则集的早期用以下规则补充上述规则:
xxxxxxxxxxpass 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)xxxxxxxxxx可能没有必要阻止所有超载者:值得注意的是,过载机制是一种通用技术,并不专门适用于SSH,完全阻止违规者的所有流量并不总是最佳选择。例如,过载规则可用于保护邮件服务或web服务,过载表可用于规则中,以最小的带宽分配将违规者分配到队列,或重定向到特定的网页。随着时间的推移,表将被重载规则填充,其大小将逐渐增加,占用更多内存。有时,被阻止的IP地址是动态分配的,此后被分配给有正当理由与本地网络中的主机通信的主机。
对于这样的情况,pfctl 提供了使表条目过期的能力。例如,此命令将删除 86400 秒(24小时)内未被引用的 <brutforce> 表条目:
xxxxxxxxxx# pfctl -t bruteforce -T expire 86400security/expireable 提供了类似的功能,它删除了在指定时间内未被访问的表条目。
安装后,可以运行expiretable来删除超过指定年龄的 <brutforce> 表条目。此示例删除所有超过24小时的条目:
xxxxxxxxxx/usr/local/sbin/expiretable -v -d -t 24h bruteforce不要与spamassassin附带的 spamd 守护进程混淆, mail/spamd 可以配置PF来提供对SPAM的外部防御。此 spamd 使用一组重定向连接到PF配置。
垃圾邮件发送者倾向于发送大量消息,垃圾邮件主要来自一些对垃圾邮件发送者友好的网络和大量被劫持的机器,这两者都会很快被报告到黑名单中。
当收到来自阻止列表中某个地址的SMTP连接时,spamd会显示其横幅并立即切换到一种模式,在这种模式下,它一次应答一个字节的SMTP流量。这种技术被称为 tarpitting ,旨在尽可能多地浪费垃圾邮件发送者的时间。使用单字节SMTP回复的具体实现通常被称为 stuttering (口吃)。
此示例演示了使用自动更新的块列表设置spamd的基本过程。有关更多信息,请参阅随 mail/spamd 安装的手册页。
步骤:配置spamd
安装 mail/spamd 包或端口。要使用spamd的灰名单功能,必须在 /dev/fd 上挂载 fdescfs(5) 。将以下行添加到 /etc/fstab :
xxxxxxxxxxfdescfs /dev/fd fdescfs rw 0 0然后,挂载文件系统:
xxxxxxxxxx# mount fdescfs接下来,编辑PF规则集以包括:
xxxxxxxxxxtable <spamd> persisttable <spamd-white> persistrdr pass on $ext_if inet proto tcp from <spamd> to \ { $ext_if, $localnet } port smtp -> 127.0.0.1 port 8025rdr 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守护进程。
下一步是在 /usr/local/etc/spamd.conf 中配置spamd,并添加一些 rc.conf 参数。
mail/spamd 的安装包括一个示例配置文件(/usr/local/etc/spamd.conf.sample)和 spamd.conf 的手册页。有关本示例中所示之外的其他配置选项,请参阅这些。
配置文件中不以 # 注释符号开头的第一行包含定义 all 列表的块,该块指定了要使用的列表:
xxxxxxxxxxall:\ :traplist:allowlist:此条目添加所需的块列表,用冒号(:)分隔。要使用分配列表从块列表中减去地址,请在该块列表的名称后立即添加分配列表的名称。例如 ::blocklist:allowlist: 。
接下来是指定块列表的定义:
xxxxxxxxxxtraplist:\ :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安装程序如何获取列表数据;支持的方法有 http 、ftp、从挂载的文件系统中的 file 以及通过外部程序的 exec 。最后, file 字段指定spamd期望接收的文件的名称。
指定的allowlist的定义类似,但省略了 msg 字段,因为不需要消息:
xxxxxxxxxxallowlist:\ :white:\ :method=file:\ :file=/var/mail/allowlist.txtxxxxxxxxxx谨慎选择数据源:使用示例spamd.conf中的所有块列表将阻止互联网的大块。管理员需要编辑文件以创建最佳配置,该配置使用适用的数据源,并在必要时使用自定义列表。接下来,将此条目添加到 /etc/rc.conf 。注释指定的手册页中描述了其他标志:
xxxxxxxxxxspamd_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) 。
要在灰名单模式下运行spamd,请将此行添加到 /etc/rc.conf:
xxxxxxxxxxspamd_grey="YES" # use spamd greylisting if YES有关其他相关参数的说明,请参阅spamd手册页。
要完成灰名单设置:
xxxxxxxxxx# service obspamd restart# service obspamlogd start在幕后,spamdb数据库工具和spamlogd白名单更新程序执行灰名单功能的基本功能。spamdb是管理员通过 /var/db/spamdb 数据库的内容管理块、灰色和允许列表的主界面。
本节介绍如何使用 block-policy 、scrub 和 antispoof 来使规则集正常运行。
block-policy 是一个选项,可以在规则集的 options 部分设置,该部分位于重定向和过滤规则之前。此选项决定PF向被规则阻止的主机发送哪些反馈(如果有的话)。该选项有两个可能的值:
drop 丢弃被阻塞的数据包,没有反馈return 返回状态代码,如 Connection rejected 。如果未设置,则默认策略为 drop 。要更改 block-policy ,请指定所需的值:
xxxxxxxxxxset block-policy return在PF中,scrub 是一个实现网络数据包规范化的关键字。此过程会重新组装碎片化的数据包,并丢弃具有无效标志组合的TCP数据包。启用 scrub 提供了一种保护措施,可以防止基于对数据包片段的错误处理的某些类型的攻击。有许多选项可供选择,但最简单的形式适用于大多数配置:
xxxxxxxxxxscrub in all某些服务(如NFS)需要特定的片段处理选项。参见 https://home.nuug.no/~peter/pf/en/scrub.html 获取更多信息。
此示例重新组装片段,清除“do not fragment”位,并将最大片段大小设置为1440字节:
xxxxxxxxxxscrub in all fragment reassemble no-df max-mss 1440anti-spoof 机制主要通过阻止出现在接口上和逻辑上不可能的方向上的数据包来防止来自欺骗或伪造IP地址的活动。
这些规则清除了来自世界其他地区的欺骗流量以及源自本地网络的任何欺骗数据包:
xxxxxxxxxxantispoof for $ext_ifantispoof for $int_if即使有一个配置正确的网关来处理网络地址转换,也可能需要补偿其他人的错误配置。一个常见的配置错误是让具有非路由(non-routable)地址的流量流出到互联网。由于来自不可路由地址的流量可能在几种DoS攻击技术中发挥作用,因此考虑明确阻止来自不可路由器地址的流量通过外部接口进入网络。
在这个例子中,定义了一个包含不可路由地址的宏,然后在阻塞规则中使用。进出这些地址的流量在网关的外部接口上悄然下降。
xxxxxxxxxxmartians = "{ 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 anyblock drop out quick on $ext_if from any to $martians在FreeBSD上,ALTQ可以与PF一起使用,以提供服务质量(QOS)。启用ALTQ后,可以在规则集中定义队列,以确定出站数据包的处理优先级。
在启用ALTQ之前,请参阅 ALTQ(4) 以确定系统上安装的网卡的驱动程序是否支持它。
ALTQ不能作为可加载内核模块使用。如果系统的接口支持ALTQ,请使用配置FreeBSD内核中的说明创建自定义内核。以下内核选项可用。首先需要启用ALTQ。指定排队调度算法需要至少一个其他选项:
xxxxxxxxxxoptions ALTQoptions ALTQ_CBQ # Class Based Queuing (CBQ)options ALTQ_RED # Random Early Detection (RED)options ALTQ_RIO # RED In/Outoptions ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC)options ALTQ_PRIQ # Priority Queuing (PRIQ)以下调度算法可用:
CBQ
基于类的排队(Class Based Queuing,CBQ)用于将连接的带宽划分为不同的类或队列,以根据过滤规则对流量进行优先级排序。
RED
随机早期检测(Random Early Detection,RED)用于通过测量队列的长度并将其与队列的最小和最大阈值进行比较来避免网络拥塞。当队列超过最大值时,所有新数据包都会随机丢弃。
RIO
在随机早期检测输入和输出(Random Early Detection In and Out,RIO)模式下,RED保持多个平均队列长度和多个阈值,每个QOS级别一个。
HFSC
分层公平服务曲线分组调度器(Hierarchical Fair Service Curve,HFSC)在http://www-2.cs.cmu.edu/~hzhang/HFSC/main.html 。
PRIQ
优先级队列(Priority Queuing,PRIQ)总是先通过较高队列中的流量。
有关调度算法和示例规则集的更多信息,请访问 OpenBSD的web存档 。
IPFW是为FreeBSD编写的有状态防火墙,支持IPv4和IPv6。它由几个组件组成:内核防火墙过滤规则处理器及其集成的数据包计费设施、日志记录设施、NAT、 dummynet(4) 流量整形器、转发设施、网桥设施和ipstealth设施。
FreeBSD在 /etc/rc.firewall 中提供了一个示例规则集,它为常见场景定义了几种防火墙类型,以帮助新手用户生成适当的规则集。IPFW提供了一种强大的语法,高级用户可以使用它来制定满足给定环境安全要求的自定义规则集。
本节介绍如何启用IPFW,概述其规则语法,并演示常见配置场景的几个规则集。
IPFW作为内核可加载模块包含在FreeBSD的基本安装中,这意味着不需要自定义内核来启用IPFW。
对于那些希望将IPFW支持静态编译到自定义内核中的用户,请参阅 【33.4.6. IPFW内核选项】。
要配置系统以在启动时启用IPFW,请在 /etc/rc.conf 中添加 firewall_enable=“YES” :
xxxxxxxxxx# sysrc firewall_enable="YES"要使用FreeBSD提供的默认防火墙类型之一,请添加另一行指定类型:
xxxxxxxxxx# sysrc firewall_type="open"可用类型有:
如果 firewall_type 设置为 client 或 simple ,请修改 /etc/rc.firewall 中的默认规则以适应系统的配置。
请注意, filename 类型用于加载自定义规则集。
加载自定义规则集的另一种方法是将 firewall_script 变量设置为包含IPFW命令的可执行脚本的绝对路径。本节中使用的示例假设 firewall_script 设置为 /etc/ipfw.rules :
xxxxxxxxxx# sysrc firewall_script="/etc/ipfw.rules"要通过 syslogd(8) 启用日志记录,请包含以下行:
xxxxxxxxxx# sysrc firewall_logging="YES"xxxxxxxxxx只有具有日志选项的防火墙规则才会被记录。默认规则不包括此选项,必须手动添加。因此,建议编辑默认规则集以进行日志记录。此外,如果日志存储在单独的文件中,则可能需要日志轮换。没有 /etc/rc.conf 变量来设置日志记录限制。要限制每次连接尝试记录规则的次数,请在 /etc/sysctl.conf 中使用此行指定次数:
xxxxxxxxxx# echo "net.inet.ip.fw.verbose_limit=5" >> /etc/sysctl.conf要通过名为 ipfw0 的专用接口启用日志记录,请将此行添加到 /etc/rc.conf 中:
xxxxxxxxxx# sysrc firewall_logif="YES"然后使用tcpdump查看正在记录的内容:
xxxxxxxxxx# tcpdump -t -n -i ipfw0xxxxxxxxxx除非连接了tcpdump,否则不会因日志记录而产生开销。保存所需的编辑后,启动防火墙。要立即启用日志记录限制,还需要设置上面指定的 sysctl 值:
xxxxxxxxxx# service ipfw start# sysctl net.inet.ip.fw.verbose_limit=5当数据包进入IPFW防火墙时,它会与规则集中的第一条规则进行比较,并一次执行一条规则,按顺序从上到下移动。当数据包与规则的选择参数匹配时,将执行规则的操作,并终止对该数据包的规则集搜索。这被称为“first match wins(首场比赛获胜)”。如果数据包与任何规则都不匹配,它将被强制IPFW默认规则号65535捕获,该规则拒绝所有数据包并默默丢弃它们。但是,如果数据包与包含 count 、 skipto 或 tee 关键字的规则匹配,则搜索将继续。有关这些关键字如何影响规则处理的详细信息,请参阅 ipfw(8) 。
创建IPFW规则时,关键字必须按以下顺序编写。有些关键字是必填的,而其他关键字是可选的。大写显示的单词表示一个变量,小写显示的单词必须位于其后的变量之前。# 符号用于标记注释的开头,可以出现在规则的末尾或单独的行上。空白行将被忽略。
xxxxxxxxxxCMD RULE_NUMBER set SET_NUMBER ACTION log LOG_AMOUNT PROTO from SRC SRC_PORT to DST DST_PORT OPTIONS本节概述了这些关键字及其选项。这并不是所有可能选项的详尽清单。有关创建ipfw规则时可以使用的规则语法的完整描述,请参阅 ipfw(8) 。
CMD
每条规则都必须以 ipfw-add 开头。
RULE-NUMBER
每个规则都与 1 到 65534 之间的数字相关联。该数字用于指示规则处理的顺序。多个规则可以具有相同的编号,在这种情况下,它们将根据添加顺序应用。
SET_NUMBER
每个规则都与一个从 0 到 31 的集合编号相关联。可以单独禁用或启用集合,从而可以快速添加或删除一组规则。如果未指定 SET_NUMBER ,则该规则将被添加到集 0 。
ACTION
规则可以与以下操作之一相关联。当数据包符合规则的选择标准时,将执行指定的操作。
allow | accept | pass | permit
这些关键字是等效的,允许符合规则的数据包。
check-state
对照动态状态表检查数据包。如果找到匹配项,则执行与生成此动态规则的规则关联的操作,否则移动到下一个规则。check-state 规则没有选择标准。如果规则集中不存在 check-state 规则,则在第一个 keep-state 或 limit 规则处检查动态规则表。
count
更新符合规则的所有数据包的计数器。搜索将继续执行下一条规则。
deny | drop
任一单词都会自动丢弃符合此规则的数据包。
其他操作可用。详情请参阅 ipfw(8) 。
LOG_AMOUNT
当数据包将规则与 log 关键字匹配时,一条消息将被记录到 syslogd(8) 中,其设施名称为 SECURITY 。只有当为该特定规则记录的数据包数量不超过指定的 LOG_AMOUNT 时,才会发生日志记录。如果未指定 LOG_AMOUNT ,则从 net.inet.ip.fw.verbose_limit 的值中获取限制。值为零会删除日志记录限制。一旦达到限制,可以通过使用 ipfw resetlog 清除该规则的日志计数器或数据包计数器来重新启用日志记录。
xxxxxxxxxx日志记录是在满足所有其他数据包匹配条件之后,在对数据包执行最终操作之前完成的。管理员决定启用登录的规则。PROTO
此可选值可用于指定 /etc/protocols 中的任何协议名称或编号。
SRC
from 关键字后面必须跟有源地址或表示源地址的关键字。地址可以用 any 、 me(在该系统上的接口上配置的任何地址)、me6(在此系统上的界面上配置的任意IPv6地址)或 table 表示,表后跟包含地址列表的查找表的编号。指定IP地址时,可以选择在其后加上CIDR掩码或子网掩码。例如,1.2.3.4/25 或 1.2.3.4:255.255.255.128 。
SRC_PORT
可以使用 /etc/services 中的端口号或名称指定可选的源端口。
DST
to 关键字后面必须跟有目标地址或表示目标地址的关键字。SRC部分中描述的相同关键字和地址可用于描述目的地。
DST_PORT
可以使用 /etc/services 中的端口号或名称指定可选的目标端口。
OPTIONS
几个关键字可以跟在源和目标后面。顾名思义,OPTIONS 是可选的。常用的选项包括 in 或 out ,指定数据包流的方向, icmptypes 后跟ICMP消息的类型,以及 keep-state 。
当 keep-state 规则匹配时,防火墙将创建一个动态规则,该规则使用相同的协议匹配源和目标地址和端口之间的双向流量。
动态规则工具容易受到SYN洪水攻击的资源耗尽的影响,这将打开大量的动态规则。要使用IPFW对抗这种类型的攻击,请使用 limit 。此选项通过检查打开的动态规则、计算此规则和IP地址组合发生的次数来限制同时会话的数量。如果此计数大于 limit 指定的值,则丢弃数据包。
有数十个选项可供选择。有关每个可用选项的说明,请参阅 ipfw(8) 。
本节演示如何创建名为 /etc/ipfw.rules 的示例有状态防火墙规则集脚本。在这个例子中,所有连接规则都使用 in或 out 来阐明方向。它们还使用 via *interface-name* 来指定数据包所经过的接口。
xxxxxxxxxx首次创建或测试防火墙规则集时,请考虑临时设置此可调参数: net.inet.ip.fw.default_to_accept="1"这将ipfw(8) 的默认策略设置为比默认的拒绝ip从任何到任何更宽松,这使得在重新启动后立即锁定系统稍微困难一些。防火墙脚本首先指示它是Bourne shell脚本,并刷新任何现有规则。然后,它创建 cmd 变量,这样就不必在每个规则的开头键入 ipfw add 。它还定义了 pif 变量,该变量表示连接到互联网的接口的名称。
x# Flush out the list before we begin.ipfw -q -f flush# Set rules command prefixcmd="ipfw -q add"pif="dc0" # interface name of NIC attached to Internet前两条规则允许可信内部接口和环回接口上的所有流量:
xxxxxxxxxx# Change xl0 to LAN NIC interface name$cmd 00005 allow all from any to any via xl0# No restrictions on Loopback Interface$cmd 00010 allow all from any to any via lo0如果数据包与动态规则表中的现有条目匹配,则下一条规则允许数据包通过:
xxxxxxxxxx$cmd 00101 check-state下一组规则定义了内部系统可以创建哪些有状态连接到互联网上的主机:
xxxxxxxxxx# Allow access to public DNS# Replace x.x.x.x with the IP address of a public DNS server# and repeat for each DNS server in /etc/resolv.conf$cmd 00110 allow tcp from any to x.x.x.x 53 out via $pif setup keep-state$cmd 00111 allow udp from any to x.x.x.x 53 out via $pif keep-state# Allow access to ISP's DHCP server for cable/DSL configurations.# Use the first rule and check log for IP address.# Then, uncomment the second rule, input the IP address, and delete the first rule$cmd 00120 allow log udp from any to any 67 out via $pif keep-state#$cmd 00120 allow udp from any to x.x.x.x 67 out via $pif keep-state# Allow outbound HTTP and HTTPS connections$cmd 00200 allow tcp from any to any 80 out via $pif setup keep-state$cmd 00220 allow tcp from any to any 443 out via $pif setup keep-state# Allow outbound email connections$cmd 00230 allow tcp from any to any 25 out via $pif setup keep-state$cmd 00231 allow tcp from any to any 110 out via $pif setup keep-state# Allow outbound ping$cmd 00250 allow icmp from any to any out via $pif keep-state# Allow outbound NTP$cmd 00260 allow udp from any to any 123 out via $pif keep-state# Allow outbound SSH$cmd 00280 allow tcp from any to any 22 out via $pif setup keep-state# deny and log all other outbound connections$cmd 00299 deny log all from any to any out via $pif下一组规则控制从互联网主机到内部网络的连接。它首先拒绝通常与攻击相关的数据包,然后明确允许特定类型的连接。所有源自互联网的授权服务都限制使用,以防止洪水泛滥。
xxxxxxxxxx# Deny all inbound traffic from non-routable reserved address spaces$cmd 00300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP$cmd 00301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP$cmd 00302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP$cmd 00303 deny all from 127.0.0.0/8 to any in via $pif #loopback$cmd 00304 deny all from 0.0.0.0/8 to any in via $pif #loopback$cmd 00305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config$cmd 00306 deny all from 192.0.2.0/24 to any in via $pif #reserved for docs$cmd 00307 deny all from 204.152.64.0/23 to any in via $pif #Sun clusterinterconnect$cmd 00308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast# Deny public pings$cmd 00310 deny icmp from any to any in via $pif# Deny ident$cmd 00315 deny tcp from any to any 113 in via $pif# Deny all Netbios services.$cmd 00320 deny tcp from any to any 137 in via $pif$cmd 00321 deny tcp from any to any 138 in via $pif$cmd 00322 deny tcp from any to any 139 in via $pif$cmd 00323 deny tcp from any to any 81 in via $pif# Deny fragments$cmd 00330 deny all from any to any frag in via $pif# Deny ACK packets that did not match the dynamic rule table$cmd 00332 deny tcp from any to any established in via $pif# Allow traffic from ISP's DHCP server.# Replace x.x.x.x with the same IP address used in rule 00120.#$cmd 00360 allow udp from any to x.x.x.x 67 in via $pif keep-state# Allow HTTP connections to internal web server$cmd 00400 allow tcp from any to me 80 in via $pif setup limit src-addr 2# Allow inbound SSH connections$cmd 00410 allow tcp from any to me 22 in via $pif setup limit src-addr 2# Reject and log all other incoming connections$cmd 00499 deny log all from any to any in via $pif最后一条规则记录了与规则集中的任何规则都不匹配的所有数据包:
xxxxxxxxxx# Everything else is denied and logged$cmd 00999 deny log all from any to anyFreeBSD的IPFW防火墙有两种NAT实现:用户区实现 natd(8) 和最近的内核内NAT实现。两者都与IPFW协同工作,提供网络地址转换。这可用于提供Internet连接共享解决方案,以便多台内部计算机可以使用单个公共IP地址连接到Internet。
为此,连接到互联网的FreeBSD机器必须充当网关。该系统必须有两个NIC,一个连接到互联网,另一个连接至内部局域网。连接到局域网的每台机器都应该在专用网络空间中分配一个IP地址,如RFC 1918所定义。
需要一些额外的配置来启用IPFW的内核内NAT功能。要在启动时启用内核内NAT支持,必须在 /etc/rc.conf 中设置以下内容:
xxxxxxxxxxgateway_enable="YES"firewall_enable="YES"firewall_nat_enable="YES"xxxxxxxxxx当firewall_nat_enable已设置但firewall_enable未设置时,它将无效且不执行任何操作。这是因为内核内NAT实现仅与IPFW兼容。当规则集包含有状态规则时,NAT规则的定位至关重要,并使用 skipto 操作。skipto 操作需要一个规则编号,以便它知道跳到哪个规则。下面的示例基于上一节中显示的防火墙规则集。它添加了一些额外的条目并修改了一些现有的规则,以便为内核内NAT配置防火墙。它首先添加了一些其他变量,这些变量表示要跳过的规则号、 keep-state 选项和将用于减少规则数量的TCP端口列表。
xxxxxxxxxxipfw -q -f flushcmd="ipfw -q add"skip="skipto 1000"pif=dc0ks="keep-state"good_tcpo="22,25,37,53,80,443,110"使用内核内NAT时,由于 libalias(3) 的架构,有必要禁用TCP分段卸载(TCP segmentation offloading,TSO),libalias是一个作为内核模块实现的库,用于提供IPFW的内核内NAT功能。TSO可以在每个网络接口的基础上使用 ifconfig(8) 禁用,也可以在系统范围内使用 sysctl(8) 停用。要在系统范围内禁用TSO,必须将其设置为 /etc/sysctl.conf :
xxxxxxxxxxnet.inet.tcp.tso="0"还将配置NAT实例。可以有多个NAT实例,每个实例都有自己的配置。对于这个例子,只需要一个NAT实例,NAT实例编号1。该配置可以采取一些选项,例如:如果指示公共接口, same_ports 负责将别名端口和本地端口号映射为相同, unreg_only 将导致NAT实例只处理未注册的(私有)地址空间, reset 将有助于保持NAT实例的功能,即使IPFW机器的公共IP地址发生变化。有关可以传递给单个NAT实例配置的所有可能选项,请参阅 ipfw(8) 。在配置有状态的NATing防火墙时,有必要允许将转换后的数据包重新注入防火墙进行进一步处理。这可以通过在防火墙脚本开始时禁用 one_pass 行为来实现。
xxxxxxxxxxipfw disable one_passipfw -q nat 1 config if $pif same_ports unreg_only reset入站NAT规则插入在允许可信和环回接口上的所有流量的两个规则之后,以及在重新组装规则之后但在 check-state 规则之前。重要的是,为该NAT规则选择的规则编号(在本例中为 100 )高于前三个规则,低于 check-state 规则。此外,由于内核内NAT的行为,建议在第一个NAT规则之前和允许可信接口上的流量的规则之后放置一个重新组装规则。通常,IP碎片不应该发生,但在处理 IPSEC/ESP/GRE 隧道流量时,可能会发生这种情况,在将整个数据包移交给内核内NAT设施之前,有必要重新组装碎片。
xxxxxxxxxxuserland natd(8)不需要重新组装规则,因为IPFW转移操作的内部工作已经负责在将数据包传递到套接字之前重新组装数据包,正如IPFW(8)中所述。此示例中使用的NAT实例和规则编号与rc.firewall创建的默认NAT实例和列表编号不匹配。rc.firewall是一个设置FreeBSD中默认防火墙规则的脚本。xxxxxxxxxx$cmd 005 allow all from any to any via xl0 # exclude LAN traffic$cmd 010 allow all from any to any via lo0 # exclude loopback traffic$cmd 099 reass all from any to any in # reassemble inbound packets$cmd 100 nat 1 ip from any to any in via $pif # NAT any inbound packets# Allow the packet through if it has an existing entry in the dynamic rules table$cmd 101 check-state修改出站规则,将 allow 操作替换为 $skip 变量,表示规则处理将在规则 1000 处继续。七个 tcp 规则已被规则 125 替换,因为 $good_tcpo 变量包含七个允许的出站端口。
xxxxxxxxxx请记住,IPFW的性能在很大程度上取决于规则集中存在的规则数量。xxxxxxxxxx# Authorized outbound packets$cmd 120 $skip udp from any to x.x.x.x 53 out via $pif $ks$cmd 121 $skip udp from any to x.x.x.x 67 out via $pif $ks$cmd 125 $skip tcp from any to any $good_tcpo out via $pif setup $ks$cmd 130 $skip icmp from any to any out via $pif $ks入站规则保持不变,除了最后一条规则,该规则删除了 via $pif ,以捕获入站和出站规则。NAT规则必须遵循最后一个出站规则,必须具有比最后一个规则更高的编号,并且规则编号必须由 skipto 操作引用。在这个规则集中,规则编号 1000 负责将所有数据包传递到我们配置的实例进行NAT处理。下一条规则允许任何经过NAT处理的数据包通过。
xxxxxxxxxx$cmd 999 deny log all from any to any$cmd 1000 nat 1 ip from any to any out via $pif # skipto location for outbound stateful rules$cmd 1001 allow ip from any to any在这个例子中,规则 100 、101 、125 、1000 和 1001 控制出站和入站数据包的地址转换,以便动态表中的条目始终注册私有LANIP地址。
考虑一个内部web浏览器,它通过端口80初始化一个新的出站HTTP会话。当第一个出站数据包进入防火墙时,它与规则 100 不匹配,因为它是出站的而不是入站的。它通过规则 101 ,因为这是第一个数据包,而且它还没有被发布到动态表中。该数据包最终与规则 125 匹配,因为它在允许的端口上出站,并且具有来自内部LAN的源IP地址。在匹配此规则时,会发生两个操作。首先, keep-state 动作向动态状态表添加条目,并执行指定的动作 skipto rule 1000 。接下来,数据包经历NAT并发送到互联网。此数据包到达目标web服务器,在那里生成并发送回响应数据包。这个新数据包进入规则集的顶部。它与规则 100 匹配,并将其目标IP地址映射回原始内部地址。然后,它由 check-state 规则处理,在表中作为现有会话找到,并释放到局域网。
在入站端,规则集必须拒绝坏数据包,只允许授权服务。与入站规则匹配的数据包被发布到动态状态表,并被释放到局域网。作为响应生成的数据包被 check-state 规则识别为属于现有会话。然后,它被发送到规则 1000 进行NAT,然后被释放到出站接口。
xxxxxxxxxx从userland natd(8) 过渡到内核内NAT起初可能看起来很无缝,但有一个小问题。当使用GENERIC内核时,当/etc/rc.conf中启用了firewall_nat_enable时,IPFW将加载libalias.ko内核模块。libalias.co内核模块仅提供基本的nat功能,而用户空间实现natd(8)在其用户空间库中具有所有可用的nat功能,无需任何额外配置。除了标准的libalias.ko内核模块外,所有功能都是指以下内核模块,这些模块可以在需要时额外加载:alias_ftp.ko、alias_bbt.ko、skinny.ko、irc.ko、alias_pptp.ko和alias_smedia.ko,使用/etc/rc.conf中的kld_list指令。如果使用自定义内核,可以在内核中使用 option LIBALIAS 编译用户土地库的全部功能。NAT的缺点通常是局域网客户端无法从互联网访问。局域网上的客户端可以与世界建立传出连接,但无法接收传入连接。如果尝试在其中一台LAN客户端计算机上运行Internet服务,则会出现问题。一个简单的方法是将NAT提供机器上的选定Internet端口重定向到LAN客户端。
例如,IRC服务器在客户端 A 上运行,web服务器在客户端 B 上运行。为了使其正常工作,必须将端口6667(IRC)和80(HTTP)上接收到的连接重定向到相应的机器。
在内核NAT中,所有配置都是在NAT实例配置中完成的。有关内核内NAT实例可以使用的完整选项列表,请参阅 ipfw(8) 。IPFW语法遵循natd语法。redirect_port 的语法如下:
xxxxxxxxxxredirect_port proto targetIP:targetPORT[-targetPORT] [aliasIP:]aliasPORT[-aliasPORT] [remoteIP[:remotePORT[-remotePORT]]]要配置上述示例设置,参数应为:
xxxxxxxxxxredirect_port tcp 192.168.0.2:6667 6667redirect_port tcp 192.168.0.3:80 80在将这些参数添加到上述规则集中NAT实例1的配置中后,TCP端口将被端口转发到运行IRC和HTTP服务的LAN客户端机器。
xxxxxxxxxxipfw -q nat 1 config if $pif same_ports unreg_only reset \ redirect_port tcp 192.168.0.2:6667 6667 \ redirect_port tcp 192.168.0.3:80 80单个端口上的端口范围可以用 redirect_Port 表示。例如,tcp 192.168.0.2:2000-3000 2000-3000 将把端口2000到3000上接收到的所有连接重定向到客户端 A 上的端口2000到3000。
如果有多个IP地址可用,地址重定向很有用。每个LAN客户端都可以通过 ipfw(8) 分配自己的外部IP地址,然后ipfw将用正确的外部IP位址重写来自LAN客户端的传出数据包,并将该特定IP位址上的所有传入流量重定向回特定LAN客户端。这也被称为静态NAT。例如,如果IP地址 128.1.1.1 、 128.1.1.2 和 128.1.1.3 可用,则 128.1.1.1 可以用作 ipfw(8) 机器的外部IP地址,而 128.1.1.2 、 128.1.1.3 则转发回LAN客户端 A 和 B 。
redirect_addr 语法如下,其中 localIP 是LAN客户端的内部IP地址, publicIP 是与LAN客户端对应的外部IP地址。
xxxxxxxxxxredirect_addr localIP publicIP在该示例中,参数将为:
xxxxxxxxxxredirect_addr 192.168.0.2 128.1.1.2redirect_addr 192.168.0.3 128.1.1.3与 redirect_port 一样,这些参数被放置在NAT实例配置中。通过地址重定向,不需要端口重定向,因为在特定IP地址上接收到的所有数据都会被重定向。
ipfw(8) 机器上的外部IP地址必须处于活动状态,并与外部接口别名。有关详细信息,请参阅 rc.conf(5) 。
让我们从一句话开始:用户空间NAT实现: natd(8) 比内核NAT有更多的开销。为了转换数据包,必须将数据包从内核复制到用户空间,然后再复制回来,这带来了内核NAT中没有的额外开销。
要在启动时启用用户空间NAT守护进程 natd(8) ,请在 /etc/rc.conf 中进行以下最低配置。其中, natd_interface 设置为连接到Internet的NIC的名称。 natd(8) 的 rc(8) 脚本将自动检查是否使用了动态IP地址,并配置自己来处理。
xxxxxxxxxxgateway_enable="YES"natd_enable="YES"natd_interface="rl0"一般来说,内核NAT中解释的上述规则集也可以与 natd(8) 一起使用。例外情况是内核内NAT实例的配置( ipfw -q nat 1 config… ),它不需要与重新组装规则99一起使用,因为它的功能包含在 divert 操作中。第100条和第1000条规则必须稍作更改,如下所示。
xxxxxxxxxx$cmd 100 divert natd ip from any to any in via $pif$cmd 1000 divert natd ip from any to any out via $pif要配置端口或地址重定向,使用与内核内NAT类似的语法。虽然,现在,与在内核NAT中指定规则集脚本中的配置不同,最好在配置文件中完成 natd(8) 的配置。为此,必须通过 /etc/rc.conf 传递一个额外的标志,指定配置文件的路径。
xxxxxxxxxxnatd_flags="-f /etc/natd.conf"xxxxxxxxxx指定的文件必须包含配置选项列表,每行一个。有关配置文件和可能变量的更多信息,请参阅natd(8)。以下是两个示例条目,每行一个: redirect_port tcp 192.168.0.2:6667 6667 redirect_addr 192.168.0.3 128.1.1.3ipfw 可用于在活动防火墙运行时手动添加或删除单个规则。使用这种方法的问题是,当系统重新启动时,所有更改都会丢失。建议将所有规则写入一个文件中,并在启动时使用该文件加载规则,并在该文件更改时替换当前运行的防火墙规则。
ipfw 是一种在控制台屏幕上显示正在运行的防火墙规则的有用方法。IPFW记帐工具为每个规则动态创建一个计数器,对与规则匹配的每个数据包进行计数。在测试规则的过程中,列出规则及其计数器是确定规则是否按预期运行的一种方法。
要按顺序列出所有运行规则,请执行以下操作:
xxxxxxxxxx# ipfw list要列出所有运行规则,并附上上次匹配规则的时间戳,请执行以下操作:
xxxxxxxxxx# ipfw -t list下一个示例列出了匹配规则的计费信息和数据包计数以及规则本身。第一列是规则编号,后面是匹配的数据包和字节数,后面是规则本身。
xxxxxxxxxx# ipfw -a list要列出静态规则之外的动态规则,请执行以下操作:
xxxxxxxxxx# ipfw -d list还要显示过期的动态规则:
xxxxxxxxxx# ipfw -d -e list要将计数器归零,请执行以下操作:
xxxxxxxxxx# ipfw zero要将数字为NUM的规则的计数器归零:
xxxxxxxxxx# ipfw zero NUM即使启用了日志记录功能,IPFW也不会自行生成任何规则日志记录。防火墙管理员决定记录规则集中的哪些规则,并将 log 关键字添加到这些规则中。通常只记录拒绝规则。通常会复制“ipfw默认拒绝一切”规则,并将 log 关键字作为规则集中的最后一个规则。这样,就可以看到与规则集中的任何规则都不匹配的所有数据包。
logging 是一把双刃剑。如果不小心,过多的日志数据或DoS攻击可能会使磁盘充满日志文件。日志消息不仅会写入syslogd,还会显示在根控制台屏幕上,很快就会变得烦人。
IPFIREWALL_VERBOSE_LIMIT=5 内核选项限制了发送到 syslogd(8) 的连续消息的数量,涉及给定规则的数据包匹配。当在内核中启用此选项时,与特定规则相关的连续消息的数量将限制在指定的数量。从200条相同的日志消息中无法获得任何信息。如果将此选项设置为五,则与特定规则相关的五条连续消息将被记录到syslogd,其余相同的连续消息将进行计数,并使用以下短语发布到syslogd:
xxxxxxxxxxlast message repeated 45 times默认情况下,所有记录的数据包消息都会写入 /etc/syslog.conf 中定义的 /var/log/security 。
大多数经验丰富的IPFW用户创建一个包含规则的文件,并以与将其作为脚本运行兼容的方式对其进行编码。这样做的主要好处是,防火墙规则可以大量刷新,而不需要重新启动系统来激活它们。这种方法在测试新规则时很方便,因为可以根据需要多次执行该过程。作为脚本,符号替换可用于将常用值替换为多个规则。
此示例脚本与 sh(1) 、 csh(1) 和 tcsh(1) shell使用的语法兼容。符号替换字段的前缀是美元符号($)。符号字段没有 $ 前缀。填充符号字段的值必须用双引号(“”)括起来。
按如下方式启动规则文件:
xxxxxxxxxx############### start of example ipfw rules script ##############ipfw -q -f flush # Delete all rules# Set defaultsoif="tun0" # out interfaceodns="192.0.2.11" # ISP's DNS server IP addresscmd="ipfw -q add " # build rule prefixks="keep-state" # just too lazy to key this each time$cmd 00500 check-state$cmd 00502 deny all from any to any frag$cmd 00501 deny tcp from any to any established$cmd 00600 allow tcp from any to any 80 out via $oif setup $ks$cmd 00610 allow tcp from any to $odns 53 out via $oif setup $ks$cmd 00611 allow udp from any to $odns 53 out via $oif $ks################### End of example ipfw rules script ############这些规则并不重要,因为本例的重点是如何填充符号替换字段。
如果上述示例位于 /etc/ipfw.rules 中,则可以通过以下命令重新加载规则:
xxxxxxxxxx# sh /etc/ipfw.rules/etc/ipfw.rules 可以位于任何位置,文件可以有任何名称。
同样的事情也可以通过手动运行这些命令来实现:
xxxxxxxxxx# ipfw -q -f flush# ipfw -q add check-state# ipfw -q add deny all from any to any frag# ipfw -q add deny tcp from any to any established# ipfw -q add allow tcp from any to any 80 out via tun0 setup keep-state# ipfw -q add allow tcp from any to 192.0.2.11 53 out via tun0 setup keep-state# ipfw -q add 00611 allow udp from any to 192.0.2.11 53 out via tun0 keep-state为了将IPFW支持静态编译到自定义内核中,请参阅 【10. 配置FreeBSD内核】中的说明。以下选项可用于自定义内核配置文件:
xxxxxxxxxxoptions IPFIREWALL # enables IPFWoptions IPFIREWALL_VERBOSE # enables logging for rules with log keyword to syslogd(8)options IPFIREWALL_VERBOSE_LIMIT=5 # limits number of logged packets per-entryoptions IPFIREWALL_DEFAULT_TO_ACCEPT # sets default policy to pass what is not explicitly deniedoptions IPFIREWALL_NAT # enables basic in-kernel NAT supportoptions LIBALIAS # enables full in-kernel NAT supportoptions IPFIREWALL_NAT64 # enables in-kernel NAT64 supportoptions IPFIREWALL_NPTV6 # enables in-kernel IPv6 NPT supportoptions IPFIREWALL_PMOD # enables protocols modification module supportoptions IPDIVERT # enables NAT through natd(8)xxxxxxxxxxIPFW可以作为内核模块加载:上述选项默认构建为模块,也可以在运行时使用可调参数进行设置。IPFILTER,也称为IPF,是一种跨平台的开源防火墙,已移植到多种操作系统,包括FreeBSD、NetBSD、OpenBSD和Solaris™。
IPFILTER是一种内核侧防火墙和NAT机制,可以由用户端程序控制和监控。可以使用 ipf 设置或删除防火墙规则,使用 ipnat 设置或删除NAT规则,可以使用 ipfstat 打印IPFILTER内核部分的运行时统计信息,并且可以使用 ipmon 将IPFILTRE操作记录到系统日志文件中。
IPF最初是使用“最后一个匹配规则获胜”的规则处理逻辑编写的,只使用无状态规则。从那时起,IPF得到了增强,包括快速和保持状态选项。
IPF常见问题解答位于 http://www.phildev.net/ipf/index.html.IPFilter 邮件列表的可搜索存档可在以下网址获得 http://marc.info/?l=ipfilter 。
本手册的这一节重点介绍IPF,因为它与FreeBSD有关。它提供了包含快速和保持状态选项的规则示例。
IPF作为内核可加载模块包含在FreeBSD的基本安装中,这意味着不需要自定义内核来启用IPF。
对于喜欢将IPF支持静态编译到自定义内核中的用户,请参阅【10. 配置FreeBSD内核】中的说明。以下内核选项可用:
xxxxxxxxxxoptions IPFILTERoptions IPFILTER_LOGoptions IPFILTER_LOOKUPoptions IPFILTER_DEFAULT_BLOCK其中 options IPFILTER 启用对IPFILTER的支持,options IPFILSTER_LOG 使用具有 log 关键字的每个规则的ipl数据包日志伪设备启用IPF日志记录,IPFILTER_LOOKUP 启用IP池以加快IP查找, options IPILTER_DEFAULT_BLOCK 更改默认行为,从而阻止任何不符合防火墙 pass 规则的数据包。
要配置系统以在启动时启用IPF,请在 /etc/rc.conf 中添加以下条目。这些条目还将启用日志记录和 default pass all 。要将默认策略更改为 block all 而不编译自定义内核,请记住在规则集末尾添加 block all 规则。
xxxxxxxxxxipfilter_enable="YES" # Start ipf firewallipfilter_rules="/etc/ipf.rules" # loads rules definition text fileipv6_ipfilter_rules="/etc/ipf6.rules" # loads rules definition text file for IPv6ipmon_enable="YES" # Start IP monitor logipmon_flags="-Ds" # D = start as daemon # s = log to syslog # v = log tcp window, ack, seq # n = map IP & port to names如果需要NAT功能,请添加以下行:
xxxxxxxxxxgateway_enable="YES" # Enable as LAN gatewayipnat_enable="YES" # Start ipnat functionipnat_rules="/etc/ipnat.rules" # rules definition file for ipnat然后,立即启动IPF:
xxxxxxxxxx# service ipfilter start要加载防火墙规则,请使用ipf指定规则集文件的名称。以下命令可用于替换当前运行的防火墙规则:
xxxxxxxxxx# ipf -Fa -f /etc/ipf.rules其中 -Fa 刷新所有内部规则表, -f 指定包含要加载的规则的文件。
这提供了对自定义规则集进行更改的能力,并使用规则的新副本更新正在运行的防火墙,而无需重新启动系统。这种方法便于测试新规则,因为可以根据需要多次执行该过程。
有关此命令可用的其他标志的详细信息,请参阅 ipf(8) 。
本节介绍用于创建有状态规则的IPF规则语法。在创建规则时,请记住,除非 quick 关键字出现在规则中,否则每个规则都是按顺序读取的,最后一个匹配的规则是应用的规则。这意味着,即使匹配数据包的第一条规则是 pass ,如果后面有一条匹配规则是 block ,数据包也会被丢弃。示例规则集可以在 /usr/share/example/ipfilter 中找到。
在创建规则时,# 字符用于标记注释的开头,可能出现在规则的末尾,解释该规则的功能,也可能出现在它自己的行上。任何空白行将被忽略。
规则中使用的关键字必须按照从左到右的特定顺序编写。有些关键字是必填的,而另一些则是可选的。一些关键字有子选项,这些子选项可能是关键字本身,也可能包含更多的子选项。关键字顺序如下,其中大写显示的单词表示一个变量,小写显示的单词必须位于其后的变量之前:
xxxxxxxxxxACTION 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 关键字表示如果数据包符合该规则,该如何处理。每一条规则都必须有 action 。以下行动得到认可:
DIRECTION
接下来,每条规则都必须使用以下关键字之一明确说明交通方向:
如果系统有多个接口,可以指定接口和方向。一个例子是 in on fxp0 。
OPTIONS
选项是可选的。但是,如果指定了多个选项,则必须按此处显示的顺序使用它们。
ipl(4) 数据包日志伪设备。ifconfig(8) 显示的接口名称。只有当数据包在指定方向上通过指定接口时,该规则才会匹配。使用 log 关键字时,可以按以下顺序使用以下限定符:
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地址不容易使用虚线数字形式/掩码长度表示法来表达。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) 。
本节演示如何创建一个示例规则集,该规则集只允许服务匹配 pass 规则,并阻止所有其他规则。
FreeBSD使用环回接口(lo0)和IP地址 127.0.0.1 进行内部通信。防火墙规则集必须包含允许这些内部使用的数据包自由移动的规则:
xxxxxxxxxx# no restrictions on loopback interfacepass in quick on lo0 allpass out quick on lo0 all连接到互联网的公共接口用于授权和控制所有出站和入站连接的访问。如果一个或多个接口通过电缆连接到专用网络,则这些内部接口可能需要规则来允许源自局域网的数据包在内部网络之间流动,或流向连接到互联网的接口。规则集应分为三个主要部分:任何受信任的内部接口、通过公共接口的出站连接和通过公共界面的入站连接。
这两条规则允许所有流量通过名为xl0的可信LAN接口:
xxxxxxxxxx# no restrictions on inside LAN interface for private networkpass out quick on xl0 allpass in quick on xl0 all公共接口的出站和入站部分的规则应该将最频繁匹配的规则放在不太常见匹配的规则之前,该部分中的最后一个规则阻止并记录该接口和方向的所有数据包。
这组规则定义了名为dc0的公共接口的出站部分。这些规则保持状态,并确定内部系统被授权访问公共互联网的特定服务。所有规则都使用 quick ,并指定适当的端口号,以及在适用的情况下指定目标地址。
xxxxxxxxxx# 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 statepass 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 rulepass 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 HTTPSpass out quick on dc0 proto tcp from any to any port = 80 flags S keep statepass out quick on dc0 proto tcp from any to any port = 443 flags S keep state# Allow emailpass out quick on dc0 proto tcp from any to any port = 110 flags S keep statepass out quick on dc0 proto tcp from any to any port = 25 flags S keep state# Allow NTPpass out quick on dc0 proto tcp from any to any port = 37 flags S keep state# Allow FTPpass out quick on dc0 proto tcp from any to any port = 21 flags S keep state# Allow SSHpass out quick on dc0 proto tcp from any to any port = 22 flags S keep state# Allow pingpass out quick on dc0 proto icmp from any to any icmp-type 8 keep state# Block and log everything elseblock out log first quick on dc0 all公共接口入站部分的规则示例首先阻止所有不需要的数据包。这减少了最后一个规则记录的数据包数量。
xxxxxxxxxx# interface facing Internet (inbound)# Block all inbound traffic from non-routable or reserved address spacesblock in quick on dc0 from 192.168.0.0/16 to any #RFC 1918 private IPblock in quick on dc0 from 172.16.0.0/12 to any #RFC 1918 private IPblock in quick on dc0 from 10.0.0.0/8 to any #RFC 1918 private IPblock in quick on dc0 from 127.0.0.0/8 to any #loopbackblock in quick on dc0 from 0.0.0.0/8 to any #loopbackblock in quick on dc0 from 169.254.0.0/16 to any #DHCP auto-configblock in quick on dc0 from 192.0.2.0/24 to any #reserved for docsblock in quick on dc0 from 204.152.64.0/23 to any #Sun cluster interconnectblock in quick on dc0 from 224.0.0.0/3 to any #Class D & E multicast# Block fragments and too short tcp packetsblock in quick on dc0 all with fragsblock in quick on dc0 proto tcp all with short# block source routed packetsblock in quick on dc0 all with opt lsrrblock in quick on dc0 all with opt ssrr# Block OS fingerprint attempts and log first occurrenceblock in log first quick on dc0 proto tcp from any to any flags FUP# Block anything with special optionsblock in quick on dc0 all with ipopts# Block public pings and identblock in quick on dc0 proto icmp all icmp-type 8block in quick on dc0 proto tcp from any to any port = 113# Block incoming Netbios servicesblock in log first quick on dc0 proto tcp/udp from any to any port = 137block in log first quick on dc0 proto tcp/udp from any to any port = 138block in log first quick on dc0 proto tcp/udp from any to any port = 139block in log first quick on dc0 proto tcp/udp from any to any port = 81每当使用 log first 选项的规则上有记录的消息时,运行 ipfstat -hio 以评估该规则匹配的次数。大量匹配可能表明系统受到攻击。
入站部分中的其余规则定义了允许从Internet启动哪些连接。最后一条规则拒绝本节中先前规则未明确允许的所有连接。
xxxxxxxxxx# 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 serverpass 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要启用NAT,请将以下语句添加到 /etc/rc.conf 中,并指定包含NAT规则的文件的名称:
xxxxxxxxxxgateway_enable="YES"ipnat_enable="YES"ipnat_rules="/etc/ipnat.rules"NAT规则是灵活的,可以完成许多不同的事情,以满足商业和家庭用户的需求。这里介绍的规则语法已经简化,以演示常见用法。有关完整的规则语法描述,请参阅 ipnat(5) 。
NAT规则的基本语法如下,其中 map 开始规则,IF 应替换为外部接口的名称:
xxxxxxxxxxmap IF LAN_IP_RANGE -> PUBLIC_ADDRESSLAN_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可以被定向为仅使用指定范围内的源端口:
xxxxxxxxxxmap dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:60000或者,使用 auto 关键字,该关键字告诉NAT确定可供使用的端口:
xxxxxxxxxxmap dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp auto第二种方法是使用公共地址池。当有太多的局域网地址无法容纳在一个公共地址中,并且有一组公共IP地址可用时,这很有用。这些公共地址可以用作一个池,NAT可以从中选择一个IP地址,因为数据包的地址在其输出时会被映射。
可以使用网络掩码或CIDR表示法指定公共IP地址的范围。这两条规则是等价的:
xxxxxxxxxxmap dc0 192.168.1.0/24 -> 204.134.75.0/255.255.255.0map dc0 192.168.1.0/24 -> 204.134.75.0/24一种常见的做法是将可公开访问的web服务器或邮件服务器隔离到内部网段。来自这些服务器的流量仍需经过NAT,但需要端口重定向将入站流量引导到正确的服务器。例如,要将使用内部地址 10.0.10.25 的web服务器映射到其公共IP地址 20.20.20.5 ,请使用以下规则:
xxxxxxxxxxrdr dc0 20.20.20.5/32 port 80 -> 10.0.10.25 port 80如果它是唯一的web服务器,则此规则也会起作用,因为它将所有外部HTTP请求重定向到 10.0.10.25 :
xxxxxxxxxxrdr dc0 0.0.0.0/0 port 80 -> 10.0.10.25 port 80IPF有一个内置的FTP代理,可以与NAT一起使用。它监控所有出站流量的主动或被动FTP连接请求,并动态创建包含FTP数据通道使用的端口号的临时过滤规则。这消除了为FTP连接打开大量高阶端口的需要。
在这个例子中,第一条规则调用代理来处理来自内部局域网的出站FTP流量。第二条规则将FTP流量从防火墙传递到互联网,第三条规则处理来自内部局域网的所有非FTP流量:
xxxxxxxxxxmap dc0 10.0.10.0/29 -> 0/32 proxy port 21 ftp/tcpmap dc0 0.0.0.0/0 -> 0/32 proxy port 21 ftp/tcpmap dc0 10.0.10.0/29 -> 0/32FTP map 规则位于NAT规则之前,因此当数据包与FTP规则匹配时,FTP代理会创建临时过滤规则,让FTP会话数据包通过并经历NAT。所有非FTP的LAN数据包都不符合FTP规则,但如果符合第三条规则,则会经历NAT。
如果没有FTP代理,则需要以下防火墙规则。请注意,如果没有代理,则需要允许 1024 以上的所有端口:
xxxxxxxxxx# Allow out LAN PC client FTP to public Internet# Active and passive modespass 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 numberspass out quick on rl0 proto tcp from any to any port > 1024 flags S keep state# Active mode let data channel in from FTP serverpass in quick on rl0 proto tcp from any to any port = 20 flags S keep state每当编辑包含NAT规则的文件时,使用 -CF 运行 ipnat 以删除当前的NAT规则并刷新动态转换表的内容。包含 -f 并指定要加载的NAT规则集的名称:
xxxxxxxxxx# ipnat -CF -f /etc/ipnat.rules要显示NAT统计信息,请执行以下操作:
xxxxxxxxxx# ipnat -s要列出NAT表的当前映射,请执行以下操作:
xxxxxxxxxx# ipnat -l要打开详细模式并显示与规则处理、活动规则和表条目相关的信息,请执行以下操作:
xxxxxxxxxx# ipnat -vIPF包括 ipfstat(8) ,可用于检索和显示数据包在通过防火墙时符合规则时收集的统计数据。统计数据是自上次启动防火墙或上次使用 ipf -Z 将其重置为零以来累积的。
默认的 ipfstat 输出如下:
xxxxxxxxxxinput 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 显示了包含规则编号的出站规则表:
xxxxxxxxxx@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 显示出站内部规则表,在每个规则前加上其使用计数:
xxxxxxxxxx2451423 pass out on xl0 from any to any354727 block out on dc0 from any to any430918 pass out quick on dc0 proto tcp/udp from any to any keep state要以类似于 top(1) 的格式显示状态表,请使用 ipfstat -t 。当防火墙受到攻击时,此选项提供了识别和查看攻击数据包的能力。可选的子标签允许选择要实时监视的目标或源IP、端口或协议。有关详细信息,请参阅 ipfstat(8) 。
IPF提供了 ipmon ,可用于以人类可读的格式写入防火墙的日志信息。它要求首先使用【10. 配置FreeBSD内核】中的说明将 options IPFILTER_LOG 添加到自定义内核中。
此命令通常在守护进程模式下运行,以提供连续的系统日志文件,以便可以查看过去事件的日志记录。由于FreeBSD有一个内置的 syslogd(8) 工具来自动轮换系统日志,因此默认的 rc.conf ipmon_flags 语句使用 -Ds :
xxxxxxxxxxipmon_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 作为日志记录工具。以下记录级别可用于进一步隔离记录的数据:
xxxxxxxxxxLOG_INFO - packets logged using the "log" keyword as the action rather than pass or block.LOG_NOTICE - packets logged which are also passedLOG_WARNING - packets logged which are also blockedLOG_ERR - packets which have been logged and which can be considered short due to an incomplete header为了设置IPF将所有数据记录到 /var/log/ipfilter.log ,首先创建空文件:
xxxxxxxxxx# touch /var/log/ipfilter.log然后,要将所有记录的消息写入指定文件,请在 /etc/syslog.conf 中添加以下语句:
xxxxxxxxxxlocal0.* /var/log/ipfilter.log要激活更改并指示 syslogd(8) 读取修改后的 /etc/syslog.conf ,请运行 service syslogd reload 。
不要忘记编辑 /etc/newsyslog.conf 以轮换新的日志文件。
ipmon 生成的消息由空格分隔的数据字段组成。所有消息共有的字段是:
@0:17 。p 表示已通过(passed), b 表示已阻止(blocked),S 表示短数据包(short packet),n 不符合任何规则(did not match any rules),L 表示日志规则(log rule)。209.53.17.22,80 → 198.73.220.17,1722 。PR 后跟协议名称或编号:例如,PR tcp 。len 后跟数据包的报头长度和总长度:例如,len 20 40 。如果数据包是TCP数据包,则将有一个以连字符开头的附加字段,后跟与设置的任何标志相对应的字母。有关字母及其标志的列表,请参阅 ipf(5) 。
如果数据包是ICMP数据包,则末尾将有两个字段:第一个始终是“ICMP”,下一个是ICMP消息和子消息类型,用斜线分隔。例如:icmp 3/3 表示端口不可达消息。
黑名单(blacklistd)是一个守护进程,它监听套接字,等待从其他守护进程接收有关连接尝试失败或成功的通知。它最广泛地用于阻止开放端口上过多的连接尝试。一个典型的例子是,在互联网上运行的SSH收到了来自机器人或脚本的大量请求,试图猜测密码并获得访问权限。使用黑名单,守护进程可以通知防火墙创建一个过滤规则,在多次尝试后阻止来自单个源的过度连接尝试。Blacklistd最初是在NetBSD上开发的,出现在版本7中。FreeBSD 11从NetBSD导入黑名单。
本章介绍了如何设置黑名单、配置黑名单,并提供了如何使用黑名单的示例。读者应该熟悉基本的防火墙概念,如规则。有关详细信息,请参阅防火墙一章。示例中使用了PF,但FreeBSD上可用的其他防火墙也应该能够处理黑名单。
黑名单的主要配置存储在 blacklistd.conf(5) 。还可以使用各种命令行选项来更改黑名单的运行时行为。重启后的持久配置应存储在 /etc/blacklistd.conf 中。要在系统启动期间启用守护进程,请在 /etc/rc.conf 中添加一行 blacklistd_enable ,如下所示:
xxxxxxxxxx# sysrc blacklistd_enable=yes要手动启动服务,请运行以下命令:
xxxxxxxxxx# service blacklistd start黑名单规则在 blacklistd.conf(5) 中配置,每行一个条目。每个规则都包含一个由空格或制表符分隔的元组。规则属于本地或远程,分别适用于运行黑名单的计算机或外部源。
本地规则的 blacklistd.conf 条目示例如下:
xxxxxxxxxx[local]ssh stream * * * 3 24h遵循 [local] 部分的所有规则都被视为适用于本地计算机的本地规则(这是默认设置)。当遇到 [remote] 部分时,它后面的所有规则都作为远程机器规则处理。
由制表符或空格分隔的七个字段定义了一个规则。前四个字段标识应被阻止的流量。接下来的三个字段定义了backlistd的行为。通配符表示为星号(*),与此字段中的任何内容匹配。第一个字段定义位置。在本地规则中,这些是网络端口。位置字段的语法如下:
xxxxxxxxxx[address|interface][/mask][:port]地址可以指定为数字格式的IPv4或方括号中的IPv6。也可以使用 em0 这样的接口名称。
套接字类型由第二个字段定义。TCP套接字的类型是 stream ,而UDP表示为 dgram 。上面的示例使用TCP,因为SSH正在使用该协议。
协议可用于黑名单规则的第三个字段。可以使用以下协议:tcp、udp、tcp6、udp6 或数字。与示例中一样,通配符通常用于匹配所有协议,除非有理由通过某种协议区分流量。
在第四个字段中,定义了报告事件的守护进程的有效用户或所有者。这里可以使用用户名或UID,也可以使用通配符(见上面的示例规则)。
数据包过滤器规则名称由第五个字段声明,该字段启动规则的行为部分。默认情况下,blacklistd将所有块放在 pf.conf 中名为 blacklistd 的pf锚点下,如下所示:
xxxxxxxxxxanchor "blacklistd/*" in on $ext_ifblock inpass out对于单独的块列表,可以在此字段中使用锚点名称。在其他情况下,通配符就足够了。当名称以连字符(-)开头时,意味着应使用前缀有默认规则名称的锚点。上面使用连字符的修改示例如下:
xxxxxxxxxxssh stream * * -ssh 3 24h有了这样的规则,任何新的块列表规则都会被添加到一个名为 blacklistd-ssh 的锚点中。
要阻止单个规则违规的整个子网,可以使用规则名称中的/。这将导致名称的剩余部分被解释为应用于规则中指定的地址的掩码。例如,此规则将阻止每个与 /24 相邻的地址。
xxxxxxxxxx22 stream tcp * */24 3 24hxxxxxxxxxx在这里指定正确的协议很重要。IPv4和IPv6对/24的处理方式不同,这就是为什么*不能用于此规则的第三个字段的原因。此规则定义了如果该网络中的任何一台主机行为异常,该网络上的其他所有内容也将被阻止。
第六个字段称为 nfail ,用于设置阻止列出所讨论的远程IP所需的登录失败次数。当在这个位置使用通配符时,这意味着区块永远不会发生。在上面的示例规则中,定义了三个限制,这意味着在一个连接上三次尝试登录SSH后,IP将被阻止。
黑名单规则定义中的最后一个字段指定主机被列入黑名单的时间。默认单位是秒,但也可以分别为分钟、小时和天指定m、h 和 d 等后缀。
整个示例规则意味着,在对SSH进行三次身份验证后,将为该主机生成一个新的PF块规则。规则匹配是通过首先从最具体到最不具体逐一检查本地规则来执行的。当匹配发生时,将应用 remote 规则,并由匹配的 remote 规则更改名称、nfail 和禁用字段。
远程规则用于指定黑名单如何根据当前正在评估的远程主机更改其行为。远程规则中的每个字段都与本地规则中的相同。唯一的区别在于黑名单使用它们的方式。为了解释这一点,使用了以下示例规则:
xxxxxxxxxx[remote]203.0.113.128/25 * * * =/25 = 48h地址字段可以是IP地址(v4或v6)、端口或两者。这允许为特定的远程地址范围设置特殊规则,如本例所示。套接字类型、协议和所有者的字段与本地规则中的解释相同。
但是名称字段不同:远程规则中的等号(=)告诉blacklistd使用匹配的本地规则中的值。这意味着获取防火墙规则条目并添加 /25 前缀(网络掩码 255.255.255.128 )。当来自该地址范围的连接被阻止时,整个子网都会受到影响。这里也可以使用PF锚点名称,在这种情况下,黑名单会将此地址块的规则添加到该名称的锚点中。指定通配符时使用默认表。
可以为地址定义 nfail 列中的自定义失败次数。这对于特定规则的例外情况很有用,可能会允许某人在登录尝试中不那么严格地应用规则或更宽容一些。当在第六个字段中使用星号时,将禁用阻止。
与来自办公室等本地网络的尝试相比,远程规则允许对登录尝试实施更严格的限制。
FreeBSD中有一些软件包可以利用黑名单的功能。最突出的两个是 ftpd(8) 和 sshd(8) ,用于阻止过度的连接尝试。要在SSH守护进程中激活黑名单,请在 /etc/SSH/sshd_config 中添加以下行:
xxxxxxxxxxUseBlacklist yes之后重新启动sshd以使这些更改生效。
ftpd(8) 的黑名单是使用 -B 启用的,可以在 /etc/inetd.conf 中启用,也可以在 /etc/rc.conf 中用作标志,如下所示:
xxxxxxxxxxftpd_flags="-B"这就是让这些程序与黑名单对话所需要的一切。
Blacklistd为用户提供了一个名为 blacklistctl(8) 的管理工具。它显示根据 blacklistd.conf(5) 中定义的规则被阻止的地址和网络。要查看当前被阻止的主机列表,请使用 dump 和 -b 组合,如下所示。
xxxxxxxxxx# blacklistctl dump -b address/ma:port id nfail last access213.0.123.128/25:22 OK 6/3 2019/06/08 14:30:19此示例显示,端口22上允许的三次尝试中有6次来自地址范围 213.0.123.128/25 。列出的尝试次数超过了允许的次数,因为SSH允许客户端在单个TCP连接上尝试多次登录。当前正在进行的连接不会被黑名单阻止。最后一次连接尝试列在输出的 last access 列中。
要查看此主机在阻止列表上的剩余时间,请在前面的命令中添加 -r 。
xxxxxxxxxx# blacklistctl dump -br address/ma:port id nfail remaining time213.0.123.128/25:22 OK 6/3 36s在这个例子中,距离该主机不再被阻止还有36秒。
有时,在剩余时间到期之前,有必要从阻止列表中删除主机。不幸的是,黑名单中没有这样做的功能。但是,可以使用 pfctl 从PF表中删除地址。对于每个被阻塞的端口,在 /etc/pf.conf 中定义的黑名单锚点内都有一个子锚点。例如,如果有一个用于阻塞端口22的子锚点,则称为 blacklistd/22 。子锚点内有一个表,其中包含被阻止的地址。此表称为端口,后跟端口号。在这个例子中,它将被称为 port22 。有了这些信息,现在可以使用 pfctl(8) 显示以下列出的所有地址:
xxxxxxxxxx# pfctl -a blacklistd/22 -t port22 -T show...213.0.123.128/25...在从列表中识别出要取消阻止的地址后,以下命令会将其从列表中删除:
xxxxxxxxxx# pfctl -a blacklistd/22 -t port22 -T delete 213.0.123.128/25该地址现在已从PF中删除,但仍将显示在黑名单ctl列表中,因为它不知道PF中的任何更改。黑名单数据库中的条目最终将过期并从其输出中删除。如果主机再次与黑名单中的阻止规则之一匹配,则将再次添加该条目。