分页: 1 / 1

《The BOOK Of PF》中文版 —— 5. 利用list和macro使规则稍微严格一些

发表于 : 2010-07-13 9:06
whoami

尽管我们可使用第一个规则集说明网络及数据包如何工作,但是它实在是太简单了, 也许并不适合实际的应用。 为了体验一下配置文件的完整结构设定, 我们设定一个更真实的例子。但是这个规则集还是针对一个独立主机只连接到一个网络的情况。
在这个配置里, 我们开始先拒绝一些通讯,然后允许我们需要的通讯。详说明3。这也给我们提供了一个机会向读者介绍两个PF中的角色—— list 和macro,也正是这些角色使PF成为一个很棒的工具。
我们要修改一下 /etc/pf.conf, 第一条规则是

代码: 全选

block all
这比我们使用的首个规则集要严格一些,这个新规则拒绝了进、出站这两个方向上的所有通讯。 这是合理的常见默认配置。在我们后面讨论的所有完整规则集里, 都将这条规则作为过滤法则的基准。后面的规则将会阻止某些通讯, 但是在我们讨论实际规则以前, 我们需要在配置文件很靠前的位置稍微做一些修改。我们需要定义一些macros以便我们可以在后面的规则集里使用它们:

代码: 全选

tcp_services = "{ ssh, smtp, domain, www, pop3, auth, https, pop3s }"
udp_services = "{ domain }"
这里我们做了一些示范。你现在知道macros(宏)是什么样了, 而且我们也告诉你了macros 也可以是lists(列表)。你现在可能想知道具体的端口号, 但是就像本例显示的一样, 在PF中你可以直接使用服务名称来代替端口号。这些服务名称列在 /etc/services 文件内。
这使我们可以更简单地编写规则, 例如像这样:

代码: 全选

block all
pass out proto tcp to any port $tcp_services
pass proto udp to any port $udp_services
说明
请注意,如果你使用的PF版本比OpenBSD 4.1的PF版本要旧,请在规则里加上keep state。
说明3
你可能会问为什么我要在规则集里加上默认拒绝规则。简而言之它可以有助于你思考规则时的控制。包过滤的主要目的就是控制, 而不是玩警察抓小偷的游戏。关于这个机理,Marcus Ranum写了一篇内容生动丰富的文章 ——“The Six Dumbest Ideas in Computer Security,” 我们强烈推荐您阅读。它可以在 http://www.ranum.com/security/computer_ ... index.html里找到,是值得一读的好文章。

这里的字符串$tcp_services和$udp_services是macro引用。
当规则集被调用时Macros在这里被展开, 并且在引用Macros的地方将插入全部的列表。Macros很便于阅读。即便在这样的小型规则集里, 如果我们不使用全部的列表和端口号,而是使用宏和列表,你也能轻易地领会和维护这些规则。
你需要在这里培养良好的习惯,也就是尽量地使用宏以提高规则集的可读性。
当你的规则集展开时, 你会为此感到高兴。
你可能会奇怪,UDP是无状态醒和无连接的,但PF怎么能为UDP通讯产生和维护状态信息以便放行返回的UDP通讯的? 一个最常见的应用UDP状态信息的例子是处理域名解析。当你请求一个域名服务器将一个域名解析为一个IP地址时或将一个IP地址反向解析为一个域名时, 我敢打赌你肯定希望收到服务器的回应。保持状态信息或功能等同于你的UDP通讯可能实现这样的功能。
因为我们已经修改了 pf.conf 文件, 我们必须导入新规则:

代码: 全选

$ sudo pfctl -f /etc/pf.conf
如果没有语法错误, pfctl在导入规则时不会输出任何信息。
这里值得一提的是,尽管在本例的特定条件下可能输出的结果没有什么差异, 但是你可以用 -v 标签来生成更详尽的pfctl输出:

代码: 全选

$ sudo pfctl -vf /etc/pf.conf
如果你的规则集里没有错误, pfctl将不会有任何输出而直接返回一个命令行提示符。
如果你扩展了你的规则集, 你可能想在导入前先检查一下这些规则。 检查的命令是:

代码: 全选

pfctl -nf /etc/pf.conf
这里的 -n 选项让PF只是解析但不导入这些规则。这样你可以获得一次修改的机会。如果PF在规则集里发现了任何语法错误, 它将退出并告诉你规则集里的哪些行有问题。
在任何情况下, 除非你清除了你的规则(using pfctl -F and some specifier),在你企图从配置文件导入新规则前,最后导入的规则集一直有效,如果你要终止它,那么停止PF,要么导入新的规则集 。 规则集导入的工作流程是, pfctl在切换到新的规则集前先进行语法检查,然后在再导入它。 导入一个有效的规则集时,没有无规则集或执行部分规则集的中间状态。(译者,感觉这里强调的是PF的工作不会停止或出错。) 这个结果是清除规则集很难说是一个好主意, 因为它使你的packet filter进入一个pass all模式。
测试规则集
一旦你有一个在pfctl导入时没有错误提示的规则集, 现在就是看看是否该规则集符合你的要求。
用诸如

代码: 全选

$ host gobsd.org
这样的命令测试一下域名解析,结果应该和前一个例子显示的一样。 但是, 可能此时你的系统仍然保留着上次 DNS 查询的缓存, 所以为了获得真实的测试结果, 请选择一个你最近没有访问过的域名(例如你不会考虑为其投票的政党站点)。你也可以浏览互联网以及使用几个email相关的服务。 但是不管怎样, 除了ssh, smtp, domain, www, pop3, auth, https和pop3s,任何企图访问远程主机其它TCP服务的尝试都应该失败。 而且应该和第一个测试规则一样, 你的系统应该拒绝不匹配状态表里任何项目的所有连接。 也就是说,PF只允许那些由你本地发起连接的返回通讯进站。