《The BOOK Of PF》中文版 —— 21. 调整表格以进行主动式防御——打发不速之客
发表于 : 2010-07-14 23:20
21. 调整表格以进行主动式防御——打发不速之客
在前面一章我们花了相当大的时间和精力来确保我们提供的服务可用,即便当我们严格地进行数据包过滤时也是如此。现在你已经完成了防火墙布置, 你将马上发现有些服务会慢慢就会吸引一些不速之客。
在本章中, 我们将研究怎样使用PF的内置特性,例如tables(表格)和状态跟踪选项, 有时将PF与用户层程序结合使用, 以便阻止不速之客的光临以及构建功能性更强的网络。
我们的环境: 我们已经设置了一个网络,它带有匹配站点所需的包过滤系统, 而且它是一个功能网络的一部分, 我们提供的一些服务,并要求从任何地方都可访问这些服务。很不幸的是,保证服务可以访问就意味着存在一个风险,在某个地方的某个人可能利用你开放的服务搞一些恶作剧。gobsd.org
可以确定你的网络至少有两种服务:通过安全shell协议的远程登录和STMP电子邮件服务都是外面那些坏小子渴望的目标。 在下小节“打发不速之客”里,我们通过一些方法让那些非认证的ssh访问更困难, 然后我们在第71页的"用spamd拒绝垃圾信息发送者”里再介绍一下如何用更有效的方法阻止垃圾信息发送者骚扰你的服务器和用户。
打发不速之客
这里所说的安全的shell服务通常是说SSH, 一个对Unix管理员来说相当重要的服务。 这是一个人机互动的主要渠道。事实上,在强壮的系统上这个服务通常是启用的,因此这个服务也经常成为脚本仔们攻击的目标。
如果你在任何一台机器上运行安全shell登录服务, 我可以肯定你在认证日志里(whoami:OpenBSD里是/var/log/authlog以及相似的名称的.gz文件)看到过类似的记录:
这种事情会重复发生, 但是这正是不速之客采取暴力攻击的特征。
某个人, 或者更像某个地方一台失守的计算机正在尝试用暴力攻击的方法获取你的用户名和密码以便获得系统的访问权。
最简单的解决方法就是写一个阻止所有访问的pf.conf规则集,但是这会带来另一种问题, 包括怎样让一个合法用户访问系统资源。将你的sshd设置为仅接受基于key的认证也是有效的, 但是这种方式无力阻止这类小屁孩似的反复尝试用户名和密码的举动。你可能也考虑过将服务转移到其它端口, 不过可能过段时间又来了,原来刷你22端口的那个小屁孩可能扫描的全部端口直至22222,然后重新开始原来的尝试。
从OpenBSD 3.7 (或者FreeBSD 6.0)开始, PF已经提供了一个更完美的解决方案,你可以写一些pass(放行)规则限制访问主机时的特定操作。
此外, 你可以将这些无聊者放进一个拒绝某些或全部访问的表格(table)里。如果你想,你甚至可以丢弃目前超过限制的主机的所有连接。这里说一下怎样做。
首先, 首先将下面这行加入到规则里的table区域来设置一个table:
然后在规则集的相当靠前的位置上设置一条阻止来自暴力攻击者通讯的规则, 像这样:
最后在你的规则集里加入类似这样的内容:
这条规则和我们以前看到的很相似是吧?事实上, 前面和我们原来的设置是一样的。你需要留意的是圆括号内的内容, 被称为状态跟踪(state-tracking)选项。这些内容将大大缓解你的网络压力。
[INDENT]max-src-conn 是你允许从一台主机同时连接的线程数。本例中, 我将其设置为100,不过, 在你的设置里可能会不同,这要根据你网络的通讯模式。
max-src-conn-rate 是指单台主机新建连接的速率, 这里的15个连接/5秒。同样你需要根据自己的情况调整。
overload <bruteforce> 是任何超过这些限制的主机将被加入table <bruteforce> 内。我们这里的规则集阻止所有列在表格<bruteforce>内的IP地址。
flush global 表示当一台主机超过限制, 这台主机的连接将被终止(flushed)。 这里的global部分表示此外这个flush对连接的操作也匹配其它的放行规则。
[/INDENT]这些规则的效果还是很引人注目的,在我这里的暴力破解尝试还未成功过: 在出现认证信息之前就超时了, 这也正是我们所希望的。
同样, 请记住这个示例规则主要是作为一个说明,你的网络可能需要不同的或结合此规则的更好规则。
如果将同时连接数和新建连接速率设置的比较低可能会导致合法通讯被阻止。一种这样的情况就是当很多机器NAT在一个公共网关后面时,很容易预料的场景就是可能出现自我造成的类似Dos攻击的假象, 因为在被NAT主机上的用户是合法的商业用户,他们需要连接到网关另一端的某些服务,而在网关上启用了严格的超负载规则(overload rules)。
例如, 通常你想允许大量的连接数量,但是又想限制一下其中的ssh连接, 你可执行如上所述的规则,在你的规则集前面加上类似如下的内容:
通过阅读相关的用户手册和PF用户指南你应该可以找出适合自己的设定参数——当然这多少要靠一些你平时积累的经验。
你无需阻止所有的超负载用户
值得在这里说说的两个要点是: 超负载是一个通用技术,并非仅限于应用在ssh服务上, 而且阻止所有超过负载限制的用户也不总是我们希望的。例如, 你可以使用一个overload规则来保护一个email或者web服务; 你也可以在一个规则里使用overload表格将超负载用户放在到一个最小带宽队列里 (请参阅第87页的“用ALTQ定向通讯”)。 在web环境里还有个有效的方法就是仅将所有的http请求重定向到指定的某个网页 (很像第43页外松内紧那小节里面的authpf)。
用pfctl整理Table
现在我们有了由超负载规则组合的几个表格(tables), 而且因为我们希望我们的网关可以连续工作几个月, 因此这些tables将随着时间的推移持续增长并消耗更多的内存。
有时你可能发现一个上周因超负载尝试被你阻止的某个IP地址实际是一个动态分配的IP地址, 这个IP地址实际上已经已经分配给你该ISP的另一个用户,而这个用户也许是一个合法用户,有正当的理由访问网络内的主机。(译者:也就是说原来那个坏小子的IP地址早就更换了)
这种情况下就需要提供一种方法来删除原表格内不再需要的项目。在OpenBSD 4.1里, pfctl 就可以提供基于最后统计设置时间将表格内的某些选项重置为过期的功能。(译者:翻译得有点绕口,通俗一点说也就是不再阻止那些已经过期的IP地址。)
在多数情况下, 这就是该项在表格内存在的时间。 这个expire关键字不难理解,而表格中项目的有效期以秒为单位计算。
例如, 下面的命令:将删除表格 <bruteforce> 中已存在了86,400秒的项目, 或者说24小时以前。你可能像设置一个crontab项以便在一定的周期内进行对表格内的过期项进行清理, 例如每小时一次, 每天一次, 或每天几次。
它的前任: expiretable
在可以使用pfctl以前, table逾期的相关任务多半由Henrik Gustafsson编写的特定程序expiretable完成。 这个程序可以实现类似PF中使用的pfctl -T expire的基本功能,它主要使用在OpenBSD 4.0或更早的版本上。
你应该让expiretable以一个进程的身份运行,它可以删除表格 <bruteforce> 里面时间超过24小时的项目,具体做法是将下面的内容加入到 /etc/rc.local 文件:
expiretable当时很快就被加入到FreeBSD和OpenBSD的port树里, 分别在 security/expiretable 和 sysutils/expiretable目录下。
如果你的packages系统里没有expiretable, 你可以从Henrik的网站 http://expiretable.fnord.se 上下载。
在前面一章我们花了相当大的时间和精力来确保我们提供的服务可用,即便当我们严格地进行数据包过滤时也是如此。现在你已经完成了防火墙布置, 你将马上发现有些服务会慢慢就会吸引一些不速之客。
在本章中, 我们将研究怎样使用PF的内置特性,例如tables(表格)和状态跟踪选项, 有时将PF与用户层程序结合使用, 以便阻止不速之客的光临以及构建功能性更强的网络。
我们的环境: 我们已经设置了一个网络,它带有匹配站点所需的包过滤系统, 而且它是一个功能网络的一部分, 我们提供的一些服务,并要求从任何地方都可访问这些服务。很不幸的是,保证服务可以访问就意味着存在一个风险,在某个地方的某个人可能利用你开放的服务搞一些恶作剧。gobsd.org
可以确定你的网络至少有两种服务:通过安全shell协议的远程登录和STMP电子邮件服务都是外面那些坏小子渴望的目标。 在下小节“打发不速之客”里,我们通过一些方法让那些非认证的ssh访问更困难, 然后我们在第71页的"用spamd拒绝垃圾信息发送者”里再介绍一下如何用更有效的方法阻止垃圾信息发送者骚扰你的服务器和用户。
打发不速之客
这里所说的安全的shell服务通常是说SSH, 一个对Unix管理员来说相当重要的服务。 这是一个人机互动的主要渠道。事实上,在强壮的系统上这个服务通常是启用的,因此这个服务也经常成为脚本仔们攻击的目标。
如果你在任何一台机器上运行安全shell登录服务, 我可以肯定你在认证日志里(whoami:OpenBSD里是/var/log/authlog以及相似的名称的.gz文件)看到过类似的记录:
代码: 全选
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
Sep 26 03:12:44 skapet sshd[29635]: Failed password for invalid user admin from 200.72.41.31
port 41484 ssh2
Sep 26 03:12:45 skapet sshd[24703]: Connection closed by 200.72.41.31
Sep 26 03:13:10 skapet sshd[11459]: Failed password for root from 200.72.41.31 port 43344 ssh2
Sep 26 03:13:10 skapet sshd[7635]: Failed password for root from 200.72.41.31 port 43344 ssh2
Sep 26 03:13:10 skapet sshd[11459]: Received disconnect from 200.72.41.31: 11: Bye Bye
Sep 26 03:13:15 skapet sshd[31357]: Invalid user admin from 200.72.41.31
Sep 26 03:13:15 skapet sshd[10543]: input_userauth_request: invalid user admin
Sep 26 03:13:15 skapet sshd[10543]: Failed password for invalid user admin from 200.72.41.31
port 43811 ssh2
Sep 26 03:13:15 skapet sshd[31357]: Failed password for invalid user admin from 200.72.41.31
port 43811 ssh2
Sep 26 03:13:15 skapet sshd[10543]: Received disconnect from 200.72.41.31: 11: Bye Bye
Sep 26 03:13:25 skapet sshd[6526]: Connection closed by 200.72.41.31
某个人, 或者更像某个地方一台失守的计算机正在尝试用暴力攻击的方法获取你的用户名和密码以便获得系统的访问权。
最简单的解决方法就是写一个阻止所有访问的pf.conf规则集,但是这会带来另一种问题, 包括怎样让一个合法用户访问系统资源。将你的sshd设置为仅接受基于key的认证也是有效的, 但是这种方式无力阻止这类小屁孩似的反复尝试用户名和密码的举动。你可能也考虑过将服务转移到其它端口, 不过可能过段时间又来了,原来刷你22端口的那个小屁孩可能扫描的全部端口直至22222,然后重新开始原来的尝试。
从OpenBSD 3.7 (或者FreeBSD 6.0)开始, PF已经提供了一个更完美的解决方案,你可以写一些pass(放行)规则限制访问主机时的特定操作。
此外, 你可以将这些无聊者放进一个拒绝某些或全部访问的表格(table)里。如果你想,你甚至可以丢弃目前超过限制的主机的所有连接。这里说一下怎样做。
首先, 首先将下面这行加入到规则里的table区域来设置一个table:
代码: 全选
table <bruteforce> persist
然后在规则集的相当靠前的位置上设置一条阻止来自暴力攻击者通讯的规则, 像这样:
代码: 全选
block quick from <bruteforce>
最后在你的规则集里加入类似这样的内容:
代码: 全选
pass inet proto tcp from any to $localnet port $tcp_services \
keep state (max-src-conn 100, max-src-conn-rate 15/5, \
overload <bruteforce> flush global)
这条规则和我们以前看到的很相似是吧?事实上, 前面和我们原来的设置是一样的。你需要留意的是圆括号内的内容, 被称为状态跟踪(state-tracking)选项。这些内容将大大缓解你的网络压力。
[INDENT]max-src-conn 是你允许从一台主机同时连接的线程数。本例中, 我将其设置为100,不过, 在你的设置里可能会不同,这要根据你网络的通讯模式。
max-src-conn-rate 是指单台主机新建连接的速率, 这里的15个连接/5秒。同样你需要根据自己的情况调整。
overload <bruteforce> 是任何超过这些限制的主机将被加入table <bruteforce> 内。我们这里的规则集阻止所有列在表格<bruteforce>内的IP地址。
警告
郑重提示:一旦某台主机超过了任何一个限制并被放进overload table内, 规则集将不会匹配来自这台主机的通讯。你需要确认超负荷者(overloaders)已被处理, 如果仅通过一个默认的block规则或者类似的规则。
flush global 表示当一台主机超过限制, 这台主机的连接将被终止(flushed)。 这里的global部分表示此外这个flush对连接的操作也匹配其它的放行规则。
[/INDENT]这些规则的效果还是很引人注目的,在我这里的暴力破解尝试还未成功过: 在出现认证信息之前就超时了, 这也正是我们所希望的。
同样, 请记住这个示例规则主要是作为一个说明,你的网络可能需要不同的或结合此规则的更好规则。
如果将同时连接数和新建连接速率设置的比较低可能会导致合法通讯被阻止。一种这样的情况就是当很多机器NAT在一个公共网关后面时,很容易预料的场景就是可能出现自我造成的类似Dos攻击的假象, 因为在被NAT主机上的用户是合法的商业用户,他们需要连接到网关另一端的某些服务,而在网关上启用了严格的超负载规则(overload rules)。
例如, 通常你想允许大量的连接数量,但是又想限制一下其中的ssh连接, 你可执行如上所述的规则,在你的规则集前面加上类似如下的内容:
代码: 全选
pass quick proto { tcp, udp } from any to any port ssh \
keep state (max-src-conn 15, max-src-conn-rate 5/3, \
overload <bruteforce> flush global)
你无需阻止所有的超负载用户
值得在这里说说的两个要点是: 超负载是一个通用技术,并非仅限于应用在ssh服务上, 而且阻止所有超过负载限制的用户也不总是我们希望的。例如, 你可以使用一个overload规则来保护一个email或者web服务; 你也可以在一个规则里使用overload表格将超负载用户放在到一个最小带宽队列里 (请参阅第87页的“用ALTQ定向通讯”)。 在web环境里还有个有效的方法就是仅将所有的http请求重定向到指定的某个网页 (很像第43页外松内紧那小节里面的authpf)。
用pfctl整理Table
现在我们有了由超负载规则组合的几个表格(tables), 而且因为我们希望我们的网关可以连续工作几个月, 因此这些tables将随着时间的推移持续增长并消耗更多的内存。
有时你可能发现一个上周因超负载尝试被你阻止的某个IP地址实际是一个动态分配的IP地址, 这个IP地址实际上已经已经分配给你该ISP的另一个用户,而这个用户也许是一个合法用户,有正当的理由访问网络内的主机。(译者:也就是说原来那个坏小子的IP地址早就更换了)
这种情况下就需要提供一种方法来删除原表格内不再需要的项目。在OpenBSD 4.1里, pfctl 就可以提供基于最后统计设置时间将表格内的某些选项重置为过期的功能。(译者:翻译得有点绕口,通俗一点说也就是不再阻止那些已经过期的IP地址。)
在多数情况下, 这就是该项在表格内存在的时间。 这个expire关键字不难理解,而表格中项目的有效期以秒为单位计算。
例如, 下面的命令:
代码: 全选
# pfctl -t bruteforce -T expire 86400
它的前任: expiretable
在可以使用pfctl以前, table逾期的相关任务多半由Henrik Gustafsson编写的特定程序expiretable完成。 这个程序可以实现类似PF中使用的pfctl -T expire的基本功能,它主要使用在OpenBSD 4.0或更早的版本上。
你应该让expiretable以一个进程的身份运行,它可以删除表格 <bruteforce> 里面时间超过24小时的项目,具体做法是将下面的内容加入到 /etc/rc.local 文件:
代码: 全选
/usr/local/sbin/expiretable -v -d -t 24h bruteforce
expiretable当时很快就被加入到FreeBSD和OpenBSD的port树里, 分别在 security/expiretable 和 sysutils/expiretable目录下。
如果你的packages系统里没有expiretable, 你可以从Henrik的网站 http://expiretable.fnord.se 上下载。