《The BOOK Of PF》中文版 —— 24. 记录, 监视和统计
发表于 : 2010-07-28 21:21
无论是在家里还是某个网络,对这本书的读者来说,通过网络练习控制可能是他们的主要目标。保持控制的一个基本要点就是将访问请求控制在网络提供的相关服务上。幸运的是, PF (像多数类Unix的组件一样) 可以生成网络活动日志数据。
PF提供了大量细节级的记录日志选项处理日志文件和提取特定类型的数据。你只要利用基本系统内的工具就可以完成很多任务, 但是你还可以通过BSD的package系统里的几个工具更有效地收集、学习、提供日志(log)数据。 本章中我们将带你了解常规的PF日志以及利用其它工具提取和提供有用的信息。
PF日志基本知识
PF将哪些数据记录在日志里以及用那种级别详细地记录日志完全由你决定, 和你在规则集里测定出的一样。 原理很简单: 在每个你想log(记录日志)的规则里添加上log关键字。
当你导入了添加好log的规则后, 任何匹配这条规则(也就是放行或禁止)的连接的初始信息将被拷贝到pflog设备上。
PF也将记录一些其它数据,例如时间戳(timestamp), 接口(interface),该数据包被放行或禁止, 以及导入的规则集里相关的规则序列号。然后pflogd日志进程将收集PF的log数据, 当系统中启用了PF时,pflogd就随着系统默认启动。默认储存log数据的位置在 /var/log/pflog; 不过, 这个log是tcpdump使用的以二进制格式记录的。
详说明1
我们先从一个简单的log例子开始。为你想要log的规则添加上关键字log:
重新载入规则集, 你会发现这个文件随着时间的推移逐渐增大以及里面的timestanp(时间戳)也在不断发生变化。要想知道文件中储存了哪些数据,你可以使用tcpdump加上 -r 选项来读取这个文件。
如果已经记录了一段时间, 输入
在命令行上将产生大量的输出。下面这一小段仅仅是tcpdump输出的前几行,整个输出要滚屏几次才能全部看到,几乎每一行都很长,需要换行才可以显示完整:
你会发现tcpdump是非常灵活的程序, 特别是在输出信息方面, 它提供了很多显示选项,例如本例中的显示格式。
这个程序一般都会显示数据包抵达的日期和时间(这里的 -ttt 选项指定了长格式)。接下来, tcpdump列出了导入的规则中的规则编号以及数据包所在的接口, 接下来列出了源和目标地址及端口 (这里的 -n 选项是让tcpdump显示IP地址, 不是主机名)。最后是不同的数据包属性。你可以通过阅读tcpdump的用户手册发现其它一些对你有用的选项。
在我们刚给出的例子中, 导入规则集中的第十条规则看起来像事无巨细地记录了所有信息,不管是是匹配的IDENT请求还是域名查询都被会记录下来。 你会发现这类信息对调试并无价值, 而事实上拥有这类信息是相当重要的,它可以让你对网络中究竟发生了一些什么一览无遗。只要你稍微努力并耐心地读一读tcpdump的用户手册,你就可以在网络上截获任何有用的log数据。
如果你想将记录(log)的通讯信息实时显示出来, 你可以用tcpdump直接从log设备本身读取 log信息。要这样, 在命令行上使用 -i 选项指定要读取的接口, 但是下面命令好理解一些:
输出信息也很容易分辨和理解。这一小段显示的最开始是一个ssh连接。后面的两个连接是spamd同步, 再接下来是两个域名查询。如果命令继续运行, 显示结构将逐渐滚动到屏幕上方, 不过自然你也可以将这些数据保存到一个文件或提供给一个单独的程序做进一步处理。
说明
在某些情况下, 你并非对所有的信息都有兴趣,而是仅对往返于特定主机或匹配特定标准的某类通讯感兴趣。在这类情况下, tcpdump自带的过滤特性可悲用来提取你所需要的数据。请参看tcpdump的用户手册以便了解细节。
记录所有的数据包: log (all)
在大多数调试情况下、或者出于一般性的监视目的, 记录一个通讯的第一个数据包已经可以提供足够的信息了。 不过,有时你可能想记录所有匹配某条规则的数据包。要实现这个目的,你可以在要监视的规则里使用 log (all) 选项. 例如,我们将它放在一个最小的规则集里, 像这样:
这会让log记录的冗长的信息。为了举例说明log (all) 究竟多生成了多少信息, 我们这里提供了一个不同的规则集片段、它放行域名查询和网络时间同步通讯:
在这一小段规则前加上上面的 log (all) 规则, 下面的一段输出显示了当一个俄罗斯的域名服务器请我的服务器发出一个域名请求时发生的一些通讯:
这里有六行显示结果,而原来只有一行的输出。 即便我们的在例子里tcpdump过滤了(不显示)域名端口的通讯, 它显示的信息也非常冗长了,更别提如果我们要将log(all)选项应用在另一个或更多的规则里了。如果你的网关储存量有限,而你又需要记录所有的信息, 你可能需要再买一些额外的存储设备。
记录(log)到多个pflog接口
在OpenBSD 4.1以前的PF版本里只有一个pflog接口。从OpenBSD 4.1开始, 当这个pflog接口变成可克隆的设备后,事情发生了变化。这意味着除了默认的pflog0, 你还可以用ifconfig命令创建多个pflog接口。 反过来说,你可以将规则集里不同的log数据分别记录在不同的pflog接口上。在需要的情况下,这也使单独处理某些数据变得更加容易了。
多个pflog接口的设置工作量变化不大,但是影响很显著 。为了将数据记录(log)到几个pflog接口上, 你需要确保在在规则集导入前已经创建了所有在规则集中使用的log接口。如果你的规则集使用了一个不存在的接口, 则准备写入(log)的数据将被丢弃。
要增加多个pflog接口,在命令行上像这样:
用同样的方法可以增加多个pflog接口。然后在规则集里加上log关键字时指定log设备,像这样:
在OpenBSD里,要让设置永远生效,你需要创建一个hostname.pflog1文件,内容只需要包含
以此类推,创建N个pflog接口则建立hostname.pflogN文件。
在FreeBSD里, 克隆的folog接口的配置工作在rc.conf文件里完成, 类似如下格式:
在NetBSD里, 我在写本书时还不能使用克隆的pflog接口。
像我们在第六章看到的那样,将规则集里的不同部分log信息定向到不同的接口就能将PF的log数据提供给不同的应用程序。反之,它使诸如spamlogd这样的程序仅处理相关的数据,而同时其它的log处理程序则可以处理另外的PF记录数据。
记录到syslog, 本地或远程
一个避免将log数据记录到网关本身的方法是指示网关将日志记录到另一台机器的系统日志(system log)上。即便PF原有的log机制并非将传统的syslog风格的日志(logging)记录到一个文本文件里,但是如果你的系统已经构建了中央日志体系, 将日志保存在中央日志服务器上也是很顺理成章的想法。
如果你不怕这些危言耸听的说法,还要通过syslog操作PF的日志记录, 我们在这里告诉你一个简单的方法。
在常规的PF设置里, pflogd处理log数据并将这些数据拷贝到log文件。如果你的设置思路主要是将log文件储存在一个远程系统上, 你肯定要禁用PF的数据积累。你可以这样做,通过rc.conf.local (在OpenBSD) 里面的进程(daemon)启动选项将pflog的日志文件设置为/dev/null:
在FreeBSD和NetBSD里也类似, 在rc.conf里修改pflog_logfile= 这行,像这样:
然后杀掉并用新参数重新启动pflogd进程。
下一个步骤是确认log数据现在不再由pflogd来收集, 而是通过一个有意义的途径传送到日志处理系统。着分为两个步骤: 首先, 设置系统日志记录程序,让它将数据传送给日志处理系统, 接下来, 使用tcpdump根据日志记录器的内容转换数据并将其注入syslog系统。
让syslogd处理数据很简单: 选择log工具, log级别以及动作详说明2 将得到的这行放进 /etc/syslog.conf 文件。假设你已经将系统的日志记录器设置在了loghost.example.com,用它接收数据,然后选择了local2作为log设备, 而log级别设置为info, 那么这行正确的写法应该是
修改完成后, 你需要重启syslogd以便其读取新配置。接下来设置tcpdump转换来自pflog设备的log数据 ,并且将结果依次提供给系统日志记录器(logger)。(whoami:这里写的似乎有问题,我只有按自己的理解翻译了。) 这里我们还是用tcpdump命令,在基本例子的基础上加上一些额外的内容:
这里的 nohup 命令确保在tcpdump在没有可控终端或者被置入后台运行时继续进行处理 (在上面的代码里用的后缀符号 & 就是让程序在后台运行)。这里的 -l 选项指定了tcpdump以行缓冲(line-buffered)的形式输出, 这在将数据重定向到其它程序时很有用, 我们这里就正好是将数据重定向到其它程序。在管路的另一端, 日志记录器为其打上标记pf,这样可以在数据流内识别出这些PF数据,然后用-p选项指定其优先级别为local2.info。最终的结果就是将日志记录在远程记录主机上你指定的文件中, 在log文件内的选项看起来像这样:
这里显示的log片段主要是web浏览活动及其伴随的域名查询。
用label对每条规则进行跟踪统计
从log数据获取的连续信息反映了系统跟踪的数据包随着时间推移的基本活动。 在其它情况下, 连接的序列或历史并没有从计数器被清零后匹配某条规则的数据包或字节数总量更重要。
在15页的从pfclt获取统计信息里我们已经看到了如何使用pfctl -s all来查阅全局汇总信息和一些其它数据。 如果你想查看这个数据更细致的统计分析, 你基本可以使用稍微变化一些的pfctl命令来跟踪每条规则的总的通讯, 例如像 pfctl -vs rules, 这将会显示统计的同时也显示该规则:
这种格式非常容易阅读并且设计的十分合理,让你在一瞥之后就知道发生了什么。
在另一方面, 上面命令的输出格式并不适合输出给脚本或其它程序来进一步处理。
如果你想提取这些统计信息和更多的项目并将其输出为一个更易脚本阅读的格式,还有就是想自己决定跟踪哪些规则, 规则 labels 正是为这个目的而设计的。
Labels的功能要比为处理特定的通讯而鉴定规则多得多。
PF的labels也使提取通讯统计变得更容易了。通过在规则中加上labels, 你可以储存规则集的中你感兴趣的额外信息或者需要特别关注的信息。使用label的一个特别好的例子就是当你需要出于会计目的而测量带宽时。
这里,我们分别为进站和出站mail通讯的pass规则加上labels mail-in 和 mail-out:
导入带有labels规则集后的某个时间, 你可以用命令 pfctl -vsl 检查数据:
这条命令的输出信息先显示这个label, 然后是这条规则评估(执行)的时间, 接下来是通过的数据包总量。 第三个值是通过的总的字节数, 后面是pass in的数据包数量, pass in的字节数, pass out的数据包数量, 以及最后的pass out的字节数。尽管没有提供便于人们阅读的一些细节, 但是这样的格式更便于提供给脚本或其它程序分析。
从规则集被导入开始,这个计算器便开始运行并积累数据,一直到规则被重新设定。 在很多情况下设置一个cron任务是很有意义的,这个任务在固定的周期内读取label数值、并将这些数值写入某种永久的储存器上。如果你在固定的周期内运行数据收集, 你可以考虑采用pfctl -vszl来取代其收集数据。当PF读到这里的 z 选项时重置计数器,而你的数据收集器将会获得周期性的数据或从上次脚本运行后的数据累积。
说明
值得一提的是带有宏(macro)和列表(list)的规则将展开成几个不同的规则。如果你的规则集包含有宏和列表并加上了label, 在内存里将会产生一系列规则, 所有的这些规则将分别带有一个具有同样名称的label。尽管这可能导致pfctl -vsl的输出结果很晦涩, 但这并非是一个真正的问题,只要接收数据的程序或脚本可以通过将这些同名label数据叠加起来并可以正确地分析数据总和。
用于PF日志和统计的额外工具
要保证控制网络的另一个要素是可以实时查看最新的系统状态。我们在本小节将探讨选择好用的监视工具。
我们这里没有完整地罗列出所有可与PF相关配合的工具。不过, 所有这里提到的工具全可以在OpenBSD和FreeBSD(NetBSD有一个例外)的packages系统中找到。
通过pftop监控
如果目前你想监视放行的进出通讯, Can Erkin Acar的pftop是一个非常用用的工具。顾名思义—pftop通过传统的Unix进程查看器top,用极有创意的一种格式实时地显示通讯的快照。
下面是我的一台网关上运行pftop的screenshot, 我仅进行了最少量的编辑:
你可以用不同的标准对连接进行排序, PF规则的这些标准有volume, age, source 和 destination addresses, 以及少量其它选项。
这个程序本身不包含在基本系统里, 也许使用各种pfctl的选项可以提取的信息和它的类似(尽管实时显示方面不尽相同) 。不管怎样, pftop可以从packages获取, 在OpenBSD和FreeBSD的port树中,它在 sysutils/pftop, 而在NetBSD的pkgsrc的sysutils/pftop
用pfstat生成通讯图表
一旦你有一个系统运行并生成需要监视的通讯, 用带有曲线的图表表示通讯是更受欢迎的。 幸运的是, 要实现PF数据图形化这样的愿望很简单。
一个最流行的解决方案就是pfstat, 一个由Daniel Hartmeier开发的小工具,它可以提取和统计PF自动产生的数据。pfstat工具可以通过OpenBSD的 package 系统,或者port中的 net/pfstat 获取, 在FreeBSD的 ports系统里是 sysutils/pfstat, 而NetBSD的 pkgsrc系统里在 sysutils/pfstat。
这个程序收集在配置文件里指定的数据并提供出有数据生成的 JPG 或 PNG 图表文件。数据的来源既可以通过本地运行PF系统的 /dev/pf 设备获取,也可以通过一台远程也在运行pfstatd进程的计算机上获取。
设置pfstat主要是要确定你想将哪些PF数据揉在一起生成一张图表以及怎样生成图表 。 然后,你编写配置文件并开启cron任务来收集数据及生成图表。
这个程序带有一个注释很详细的配置文件示例,而其用户手册言简意。这个配置示例是你编写自己配置文件的基础。我将在这里举一个小例子。
下面这个pfstat.conf的片段和你将找到的配置文件示例很相似:详说明3
每分钟收集一次状态的插入、删除、搜索,然后将每天的数据生成一个JPG文件,生成的图形类似附件中F8-1, 图中所示的是我的一台比较轻松的网关。
要查看同样数据的更详细的信息, 我决定让数据显示最近一小时的结果, 仅提高了图表的解析度。我将周期调整为1小时前到现在, 并把尺寸调整为宽600、高300,生成的图是F8-2。
pfstat的主页在 http://www.benzedrine.cx/pfstat.html 包含了一系列其它的例子, 并展示由benzedrine.cx域的网关上传送出来的数据生成的实时更新图表。 通过阅读这些例子而获取通讯相关知识, 你就应该可以创建适合自己站点的pfstat配置。
用pfflowd收集NetFlow数据
NetFlow是一个网络数据收集和分析的方法,它催生出一大批支持记录和分析TCP/IP连接的数据的工具。NetFlow源自于Cisco, 随着时间的推移,它逐渐作为一项重要的管理和分析功能被不同的网络设备所支持。
如果你已经在使用NetFlow, 它是不错的工具,而且更关键的是通过pfflowd软件包你能将PF的数据提供给NetFlow工具进行分析处理。
NetFlow数据模型将网络流量定义为一个具有相同源和目的地址和协议的数据包单向序列。 它很好地绘制了PF的状态信息, 而pfflowd被用来从本地系统的pfsync设备记录状态的变化。一旦被启用, pfflowd就充当了一个NetFlow的探测器,它将pfsync数据转换为NetFlow格式以便传送给网络上的NetFlow控制器。
pfflowd工具由 Damien Miller 编写和维护,可以在他的网站 (http://www.mindrot.org/projects/pfflowd) 或者OpenBSD和FreeBSD的package系统的 net/pfflowd 获得。在写本章时它还不能在NetBSD上使用。
SNMP工具和PF相关的SNMP MIBs
简单网络管理协议(The Simple Network Management Protocol —— 简称SNMP) 是为网路管理员在一个集中的系统上收集和监控多个网络节点上系统运行和潜在配置变化的关键数据。
在1998年8月这个协议最早出现在RFC 1067,现在其第三个主要版本在RFCs 3411到 3418里面有定义。SNMP协议带有一个定义良好的接口以及一个扩展管理信息库(MIB)的方法,MIB定义了被管理的设备和对象。
如果你的网络足够大,支持SNMP的管理能力在正式的网络里就变得不可或缺的要素了,你可能在购买此书前已经先翻阅了这一小节以便确认次数是否值得你购买。
无论是具有专利还是开源的网络的管理和监控系统, 通常提供各种形式的SNMP支持 , 它是某些产品的核心功能。在BSD家族里, SNMP的支持一般由net-snmp软件包提供, 它提供了管理系统所需的检索和收集SNMP数据的一些工具。这个软件包在OpenBSD的 net/net-snmp, FreeBSD的 net-mgmt/net-snmp, 以及NetBSD的 net/net-snmp.
幸运的是, 还有一个net-snmp的扩展组件, 它可以让PF的数据用于SNMP监控。 Joel Knight 维护的MIBs就是用来收集PF、CARP、以及OpenBSD的内核探测器数据的, 它可以作为net-snmp补丁,下载地址http://www.packetmischief.ca/openbsd/snmp。
安装好这个package(软件包)和扩展后, 具有SNMP功能的监视系统也就可以详尽地监视(获取)PF数据了。 此外值得一提的是,FreeBSD的bsnmpd包含了一个PF模块。请参阅bsnmpd的用户手册以获取更多信息。
记住, 有用的日志(log)数据是提高调试效率的基本要素
在本章里我们介绍了在一个开启PF的系统上收集、显示和解析数据的要点。知道如何从系统行为中获取有用的信息就可以实现几个目的。
监视一个正在运行的系统状况对其本身来说是有意义的, 但是更为重要的是阅读和解析log数据以确定系统是真正按照规范运行。 另一个记录日志数据的重要作用是,在你修改配置后跟踪检查的其效果, 例如,当你优化系统后。
基于Log数据或其它的可观察项检查你的配置文件并做优化调整是我们下一章里涉及的一大块内容。
PF提供了大量细节级的记录日志选项处理日志文件和提取特定类型的数据。你只要利用基本系统内的工具就可以完成很多任务, 但是你还可以通过BSD的package系统里的几个工具更有效地收集、学习、提供日志(log)数据。 本章中我们将带你了解常规的PF日志以及利用其它工具提取和提供有用的信息。
PF日志基本知识
PF将哪些数据记录在日志里以及用那种级别详细地记录日志完全由你决定, 和你在规则集里测定出的一样。 原理很简单: 在每个你想log(记录日志)的规则里添加上log关键字。
当你导入了添加好log的规则后, 任何匹配这条规则(也就是放行或禁止)的连接的初始信息将被拷贝到pflog设备上。
PF也将记录一些其它数据,例如时间戳(timestamp), 接口(interface),该数据包被放行或禁止, 以及导入的规则集里相关的规则序列号。然后pflogd日志进程将收集PF的log数据, 当系统中启用了PF时,pflogd就随着系统默认启动。默认储存log数据的位置在 /var/log/pflog; 不过, 这个log是tcpdump使用的以二进制格式记录的。
详说明1
说明1
用于从log文件里提取和显示信息的额外工具将在后面讨论。
别担心, 有关此格式的参考资料很丰富,而且它也是被广泛支持的二进制格式。
我们先从一个简单的log例子开始。为你想要log的规则添加上关键字log:
代码: 全选
block log all
pass log quick proto { tcp, udp } from any to any port ssh
重新载入规则集, 你会发现这个文件随着时间的推移逐渐增大以及里面的timestanp(时间戳)也在不断发生变化。要想知道文件中储存了哪些数据,你可以使用tcpdump加上 -r 选项来读取这个文件。
如果已经记录了一段时间, 输入
代码: 全选
$ sudo tcpdump -n -ttt -r /var/log/pflog
代码: 全选
$ sudo tcpdump -n -ttt -r /var/log/pflog
tcpdump: WARNING: snaplen raised from 96 to 116
Sep 13 13:00:30.556038 rule 10/(match) pass in on epic0: 194.54.107.19.34834 >
194.54.103.66.113: S 3097635127:3097635127(0) win 16384 <mss 1460,nop,nop,sackOK,nop,wscale
0,[|tcp]> (DF)
Sep 13 13:00:30.556063 rule 10/(match) pass out on fxp0: 194.54.107.19.34834 >
194.54.103.66.113: S 3097635127:3097635127(0) win 16384 <mss 1460,nop,nop,sackOK,nop,wscale
0,[|tcp]> (DF)
Sep 13 13:01:07.796096 rule 10/(match) pass in on epic0: 194.54.107.19.29572 >
194.54.103.66.113: S 2345499144:2345499144(0) win 16384 <mss 1460,nop,nop,sackOK,nop,wscale
0,[|tcp]> (DF)
Sep 13 13:01:07.796120 rule 10/(match) pass out on fxp0: 194.54.107.19.29572 >
194.54.103.66.113: S 2345499144:2345499144(0) win 16384 <mss 1460,nop,nop,sackOK,nop,wscale
0,[|tcp]> (DF)
Sep 13 13:01:15.096643 rule 10/(match) pass in on epic0: 194.54.107.19.29774 >
194.54.103.65.53: 49442 [1au][|domain]
Sep 13 13:01:15.607619 rule 12/(match) pass in on epic0: 194.54.107.19.29774 >
194.54.107.18.53: 34932 [1au][|domain]
你会发现tcpdump是非常灵活的程序, 特别是在输出信息方面, 它提供了很多显示选项,例如本例中的显示格式。
这个程序一般都会显示数据包抵达的日期和时间(这里的 -ttt 选项指定了长格式)。接下来, tcpdump列出了导入的规则中的规则编号以及数据包所在的接口, 接下来列出了源和目标地址及端口 (这里的 -n 选项是让tcpdump显示IP地址, 不是主机名)。最后是不同的数据包属性。你可以通过阅读tcpdump的用户手册发现其它一些对你有用的选项。
解密规则编号
值得一提的是log文件中的规则编号是指导入内存中的规则集里面的规则编号。在导入规则集的过程中有一些自动步骤,例如展开宏和优化,这些步骤很可能导致储存在log文件内的规则编号与你在pf.conf里计算的编号不一致。如果你感觉自己无法了解log文件的某项具体匹配了哪条规则, 你可以用命令 pfctl -vvs rules 来查看(或者 pfctl –vvsr, 如果你懒得打字) ,然后再继续研究输出内容。
在我们刚给出的例子中, 导入规则集中的第十条规则看起来像事无巨细地记录了所有信息,不管是是匹配的IDENT请求还是域名查询都被会记录下来。 你会发现这类信息对调试并无价值, 而事实上拥有这类信息是相当重要的,它可以让你对网络中究竟发生了一些什么一览无遗。只要你稍微努力并耐心地读一读tcpdump的用户手册,你就可以在网络上截获任何有用的log数据。
如果你想将记录(log)的通讯信息实时显示出来, 你可以用tcpdump直接从log设备本身读取 log信息。要这样, 在命令行上使用 -i 选项指定要读取的接口, 但是下面命令好理解一些:
代码: 全选
$ sudo tcpdump -nettti pflog0
tcpdump: WARNING: pflog0: no IPv4 address assigned
tcpdump: listening on pflog0, link-type PFLOG
Sep 13 15:26:52.122002 rule 17/(match) pass in on epic0: 91.143.126.48.46618 >
194.54.103.65.22: [|tcp] (DF)
Sep 13 15:28:02.771442 rule 12/(match) pass in on epic0: 194.54.107.19.8025 >
194.54.107.18.8025: udp 50
Sep 13 15:28:02.773958 rule 10/(match) pass in on epic0: 194.54.107.19.8025 >
194.54.103.65.8025: udp 50
Sep 13 15:29:27.882888 rule 10/(match) pass in on epic0: 194.54.107.19.29774 >
194.54.103.65.53:[|domain]
Sep 13 15:29:28.394320 rule 12/(match) pass in on epic0: 194.54.107.19.29774 >
194.54.107.18.53:[|domain]
输出信息也很容易分辨和理解。这一小段显示的最开始是一个ssh连接。后面的两个连接是spamd同步, 再接下来是两个域名查询。如果命令继续运行, 显示结构将逐渐滚动到屏幕上方, 不过自然你也可以将这些数据保存到一个文件或提供给一个单独的程序做进一步处理。
说明
在某些情况下, 你并非对所有的信息都有兴趣,而是仅对往返于特定主机或匹配特定标准的某类通讯感兴趣。在这类情况下, tcpdump自带的过滤特性可悲用来提取你所需要的数据。请参看tcpdump的用户手册以便了解细节。
记录所有的数据包: log (all)
在大多数调试情况下、或者出于一般性的监视目的, 记录一个通讯的第一个数据包已经可以提供足够的信息了。 不过,有时你可能想记录所有匹配某条规则的数据包。要实现这个目的,你可以在要监视的规则里使用 log (all) 选项. 例如,我们将它放在一个最小的规则集里, 像这样:
代码: 全选
block log (all) all
pass log (all) quick proto tcp from any to any port ssh keep state
代码: 全选
udp_services = "{ domain, ntp }"
pass log (all) inet proto udp from any to any port $udp_services
代码: 全选
$ sudo tcpdump -n -ttt -i pflog0 port domain
tcpdump: WARNING: pflog0: no IPv4 address assigned
tcpdump: listening on pflog0, link-type PFLOG
Sep 30 14:27:41.260190 212.5.66.14.53 > 194.54.107.19.53:[|domain]
Sep 30 14:27:41.260253 212.5.66.14.53 > 194.54.107.19.53:[|domain]
Sep 30 14:27:41.260267 212.5.66.14.53 > 194.54.107.19.53:[|domain]
Sep 30 14:27:41.260638 194.54.107.19.53 > 212.5.66.14.53:[|domain]
Sep 30 14:27:41.260798 194.54.107.19.53 > 212.5.66.14.53:[|domain]
Sep 30 14:27:41.260923 194.54.107.19.53 > 212.5.66.14.53:[|domain]
记录(log)到多个pflog接口
在OpenBSD 4.1以前的PF版本里只有一个pflog接口。从OpenBSD 4.1开始, 当这个pflog接口变成可克隆的设备后,事情发生了变化。这意味着除了默认的pflog0, 你还可以用ifconfig命令创建多个pflog接口。 反过来说,你可以将规则集里不同的log数据分别记录在不同的pflog接口上。在需要的情况下,这也使单独处理某些数据变得更加容易了。
多个pflog接口的设置工作量变化不大,但是影响很显著 。为了将数据记录(log)到几个pflog接口上, 你需要确保在在规则集导入前已经创建了所有在规则集中使用的log接口。如果你的规则集使用了一个不存在的接口, 则准备写入(log)的数据将被丢弃。
要增加多个pflog接口,在命令行上像这样:
代码: 全选
$ sudo ifconfig create pflog1
用同样的方法可以增加多个pflog接口。然后在规则集里加上log关键字时指定log设备,像这样:
代码: 全选
pass log (to pflog1) proto tcp from any to $emailserver port $email
pass log (to pflog1) proto tcp from $emailserver to any port smtp
在OpenBSD里,要让设置永远生效,你需要创建一个hostname.pflog1文件,内容只需要包含
代码: 全选
up
在FreeBSD里, 克隆的folog接口的配置工作在rc.conf文件里完成, 类似如下格式:
代码: 全选
ifconfig_pflog1="up"
像我们在第六章看到的那样,将规则集里的不同部分log信息定向到不同的接口就能将PF的log数据提供给不同的应用程序。反之,它使诸如spamlogd这样的程序仅处理相关的数据,而同时其它的log处理程序则可以处理另外的PF记录数据。
记录到syslog, 本地或远程
一个避免将log数据记录到网关本身的方法是指示网关将日志记录到另一台机器的系统日志(system log)上。即便PF原有的log机制并非将传统的syslog风格的日志(logging)记录到一个文本文件里,但是如果你的系统已经构建了中央日志体系, 将日志保存在中央日志服务器上也是很顺理成章的想法。
一些有关SYSLOG的注意事项
BSD老手可能会告诉你, 传统的系统日志程序syslog在管理来自其它主机的UDP通讯时很幼稚, 他们经常提到危险的就是DoS攻击可能影响所有的磁盘。还有一个经常存在的风险是无论在系统或者网络承受高负载的情况下log信息可能会丢失。因此, 如果你的网络中所有相关主机都通过一个良好的加密网络通讯,你应该考虑只将系统设置为仅在远程记录(log)日志文件。 在所有的BSD里, 默认情况下syslogd并未设定为接收另一台主机的log数据。如果你打算使用远程suslog日志系统,请参阅syslogd的用户手册以便了解怎样监听远程主机的Log数据。
如果你不怕这些危言耸听的说法,还要通过syslog操作PF的日志记录, 我们在这里告诉你一个简单的方法。
在常规的PF设置里, pflogd处理log数据并将这些数据拷贝到log文件。如果你的设置思路主要是将log文件储存在一个远程系统上, 你肯定要禁用PF的数据积累。你可以这样做,通过rc.conf.local (在OpenBSD) 里面的进程(daemon)启动选项将pflog的日志文件设置为/dev/null:
代码: 全选
pflogd_flags="-f /dev/null"
代码: 全选
pflog_logfile="/dev/null"
下一个步骤是确认log数据现在不再由pflogd来收集, 而是通过一个有意义的途径传送到日志处理系统。着分为两个步骤: 首先, 设置系统日志记录程序,让它将数据传送给日志处理系统, 接下来, 使用tcpdump根据日志记录器的内容转换数据并将其注入syslog系统。
让syslogd处理数据很简单: 选择log工具, log级别以及动作详说明2 将得到的这行放进 /etc/syslog.conf 文件。假设你已经将系统的日志记录器设置在了loghost.example.com,用它接收数据,然后选择了local2作为log设备, 而log级别设置为info, 那么这行正确的写法应该是
代码: 全选
local2.info @loghost.example.com
说明2
在syslog.conf的用户手册里对这些概念的解释很详尽, 如果你想理解系统日志,自然需要阅读它。这里的“动作”部分通常是本地系统的一个文件, 你通过阅读这里的配置文件和用户手册就清楚了。
修改完成后, 你需要重启syslogd以便其读取新配置。接下来设置tcpdump转换来自pflog设备的log数据 ,并且将结果依次提供给系统日志记录器(logger)。(whoami:这里写的似乎有问题,我只有按自己的理解翻译了。) 这里我们还是用tcpdump命令,在基本例子的基础上加上一些额外的内容:
代码: 全选
$ sudo nohup tcpdump -lnettti pflog0 | logger -t pf -p local2.info &
代码: 全选
pf: Sep 21 14:05:11.492590 rule 93/(match) pass in on ath0: 10.168.103.11.15842 >
82.117.50.17.80: [|tcp] (DF)
pf: Sep 21 14:05:11.492648 rule 93/(match) pass out on xl0: 194.54.107.19.15842 >
82.117.50.17.80: [|tcp] (DF)
pf: Sep 21 14:05:11.506289 rule 93/(match) pass in on ath0: 10.168.103.11.27984 >
82.117.50.17.80: [|tcp] (DF)
pf: Sep 21 14:05:11.506330 rule 93/(match) pass out on xl0: 194.54.107.19.27984 >
82.117.50.17.80: [|tcp] (DF)
pf: Sep 21 14:05:11.573561 rule 136/(match) pass in on ath0: 10.168.103.11.6430 >
10.168.103.1.53:[|domain]
pf: Sep 21 14:05:11.574276 rule 136/(match) pass out on xl0: 194.54.107.19.26281 >
209.62.178.21.53:[|domain]
用label对每条规则进行跟踪统计
从log数据获取的连续信息反映了系统跟踪的数据包随着时间推移的基本活动。 在其它情况下, 连接的序列或历史并没有从计数器被清零后匹配某条规则的数据包或字节数总量更重要。
在15页的从pfclt获取统计信息里我们已经看到了如何使用pfctl -s all来查阅全局汇总信息和一些其它数据。 如果你想查看这个数据更细致的统计分析, 你基本可以使用稍微变化一些的pfctl命令来跟踪每条规则的总的通讯, 例如像 pfctl -vs rules, 这将会显示统计的同时也显示该规则:
代码: 全选
$ pfctl -vs rules
pass inet proto tcp from any to 192.0.2.225 port = smtp flags S/SA keep state label "mail-in"
[ Evaluations: 1664158 Packets: 1601986 Bytes: 763762591 States: 0 ]
[ Inserted: uid 0 pid 24490 ]
pass inet proto tcp from 192.0.2.225 to any port = smtp flags S/SA keep state label "mail-out"
[ Evaluations: 2814933 Packets: 2711211 Bytes: 492510664 States: 0 ]
[ Inserted: uid 0 pid 24490 ]
在另一方面, 上面命令的输出格式并不适合输出给脚本或其它程序来进一步处理。
如果你想提取这些统计信息和更多的项目并将其输出为一个更易脚本阅读的格式,还有就是想自己决定跟踪哪些规则, 规则 labels 正是为这个目的而设计的。
Labels的功能要比为处理特定的通讯而鉴定规则多得多。
PF的labels也使提取通讯统计变得更容易了。通过在规则中加上labels, 你可以储存规则集的中你感兴趣的额外信息或者需要特别关注的信息。使用label的一个特别好的例子就是当你需要出于会计目的而测量带宽时。
这里,我们分别为进站和出站mail通讯的pass规则加上labels mail-in 和 mail-out:
代码: 全选
pass log proto { tcp, udp } from any to $emailserver port smtp label "mail-in"
pass log proto { tcp, udp } from $emailserver to any port smtp label "mail-out"
代码: 全选
$ sudo pfctl -vsl
mail-in 1664158 1601986 763762591 887895 682427415 714091 81335176
mail-out 2814933 2711211 492510664 1407278 239776267 1303933 252734397
从规则集被导入开始,这个计算器便开始运行并积累数据,一直到规则被重新设定。 在很多情况下设置一个cron任务是很有意义的,这个任务在固定的周期内读取label数值、并将这些数值写入某种永久的储存器上。如果你在固定的周期内运行数据收集, 你可以考虑采用pfctl -vszl来取代其收集数据。当PF读到这里的 z 选项时重置计数器,而你的数据收集器将会获得周期性的数据或从上次脚本运行后的数据累积。
说明
值得一提的是带有宏(macro)和列表(list)的规则将展开成几个不同的规则。如果你的规则集包含有宏和列表并加上了label, 在内存里将会产生一系列规则, 所有的这些规则将分别带有一个具有同样名称的label。尽管这可能导致pfctl -vsl的输出结果很晦涩, 但这并非是一个真正的问题,只要接收数据的程序或脚本可以通过将这些同名label数据叠加起来并可以正确地分析数据总和。
用于PF日志和统计的额外工具
要保证控制网络的另一个要素是可以实时查看最新的系统状态。我们在本小节将探讨选择好用的监视工具。
我们这里没有完整地罗列出所有可与PF相关配合的工具。不过, 所有这里提到的工具全可以在OpenBSD和FreeBSD(NetBSD有一个例外)的packages系统中找到。
通过pftop监控
如果目前你想监视放行的进出通讯, Can Erkin Acar的pftop是一个非常用用的工具。顾名思义—pftop通过传统的Unix进程查看器top,用极有创意的一种格式实时地显示通讯的快照。
下面是我的一台网关上运行pftop的screenshot, 我仅进行了最少量的编辑:
代码: 全选
pfTop: Up State 1-21/67, View: default, Order: none, Cache: 10000 19:52:28
PR DIR SRC DEST STATE AGE EXP PKTS BYTES
tcp Out 194.54.103.89:3847 216.193.211.2:25 9:9 28 67 29 3608
tcp In 207.182.140.5:44870 127.0.0.1:8025 4:4 15 86400 30 1594
tcp In 207.182.140.5:36469 127.0.0.1:8025 10:10 418 75 810 44675
tcp In 194.54.107.19:51593 194.54.103.65:22 4:4 146 86395 158 37326
tcp In 194.54.107.19:64926 194.54.103.65:22 4:4 193 86243 131 21186
tcp In 194.54.103.76:3010 64.136.25.171:80 9:9 154 59 11 1570
tcp In 194.54.103.76:3013 64.136.25.171:80 4:4 4 86397 6 1370
tcp In 194.54.103.66:3847 216.193.211.2:25 9:9 28 67 29 3608
tcp Out 194.54.103.76:3009 64.136.25.171:80 9:9 214 0 9 1490
tcp Out 194.54.103.76:3010 64.136.25.171:80 4:4 64 86337 7 1410
udp Out 194.54.107.18:41423 194.54.96.9:53 2:1 36 0 2 235
udp In 194.54.107.19:58732 194.54.103.66:53 1:2 36 0 2 219
udp In 194.54.107.19:54402 194.54.103.66:53 1:2 36 0 2 255
udp In 194.54.107.19:54681 194.54.103.66:53 1:2 36 0 2 271
你可以用不同的标准对连接进行排序, PF规则的这些标准有volume, age, source 和 destination addresses, 以及少量其它选项。
这个程序本身不包含在基本系统里, 也许使用各种pfctl的选项可以提取的信息和它的类似(尽管实时显示方面不尽相同) 。不管怎样, pftop可以从packages获取, 在OpenBSD和FreeBSD的port树中,它在 sysutils/pftop, 而在NetBSD的pkgsrc的sysutils/pftop
用pfstat生成通讯图表
一旦你有一个系统运行并生成需要监视的通讯, 用带有曲线的图表表示通讯是更受欢迎的。 幸运的是, 要实现PF数据图形化这样的愿望很简单。
一个最流行的解决方案就是pfstat, 一个由Daniel Hartmeier开发的小工具,它可以提取和统计PF自动产生的数据。pfstat工具可以通过OpenBSD的 package 系统,或者port中的 net/pfstat 获取, 在FreeBSD的 ports系统里是 sysutils/pfstat, 而NetBSD的 pkgsrc系统里在 sysutils/pfstat。
这个程序收集在配置文件里指定的数据并提供出有数据生成的 JPG 或 PNG 图表文件。数据的来源既可以通过本地运行PF系统的 /dev/pf 设备获取,也可以通过一台远程也在运行pfstatd进程的计算机上获取。
设置pfstat主要是要确定你想将哪些PF数据揉在一起生成一张图表以及怎样生成图表 。 然后,你编写配置文件并开启cron任务来收集数据及生成图表。
这个程序带有一个注释很详细的配置文件示例,而其用户手册言简意。这个配置示例是你编写自己配置文件的基础。我将在这里举一个小例子。
下面这个pfstat.conf的片段和你将找到的配置文件示例很相似:详说明3
说明3
示例文件里的color值可以让你的图表生成红、蓝、绿色线。 因为我们提供的是单色印刷版本, 所以我们将这些颜色变成了灰度值: 0 192 0 修改为105 105 105, 0 0 255 修改为 192 192 192, 而 255 0 0 修改为 0 0 0。
代码: 全选
collect 8 = global states inserts diff
collect 9 = global states removals diff
collect 10 = global states searches diff
image "/var/www/users/peter/bsdly.net/pfstat-states.jpg" {
from 1 days to now
width 980 height 300
left
graph 8 "inserts" "states/s" color 0 192 0 filled,
graph 9 "removals" "states/s" color 0 0 255
right
graph 10 "searches" "states/s" color 255 0 0
}
每分钟收集一次状态的插入、删除、搜索,然后将每天的数据生成一个JPG文件,生成的图形类似附件中F8-1, 图中所示的是我的一台比较轻松的网关。
要查看同样数据的更详细的信息, 我决定让数据显示最近一小时的结果, 仅提高了图表的解析度。我将周期调整为1小时前到现在, 并把尺寸调整为宽600、高300,生成的图是F8-2。
pfstat的主页在 http://www.benzedrine.cx/pfstat.html 包含了一系列其它的例子, 并展示由benzedrine.cx域的网关上传送出来的数据生成的实时更新图表。 通过阅读这些例子而获取通讯相关知识, 你就应该可以创建适合自己站点的pfstat配置。
用pfflowd收集NetFlow数据
NetFlow是一个网络数据收集和分析的方法,它催生出一大批支持记录和分析TCP/IP连接的数据的工具。NetFlow源自于Cisco, 随着时间的推移,它逐渐作为一项重要的管理和分析功能被不同的网络设备所支持。
如果你已经在使用NetFlow, 它是不错的工具,而且更关键的是通过pfflowd软件包你能将PF的数据提供给NetFlow工具进行分析处理。
NetFlow数据模型将网络流量定义为一个具有相同源和目的地址和协议的数据包单向序列。 它很好地绘制了PF的状态信息, 而pfflowd被用来从本地系统的pfsync设备记录状态的变化。一旦被启用, pfflowd就充当了一个NetFlow的探测器,它将pfsync数据转换为NetFlow格式以便传送给网络上的NetFlow控制器。
pfflowd工具由 Damien Miller 编写和维护,可以在他的网站 (http://www.mindrot.org/projects/pfflowd) 或者OpenBSD和FreeBSD的package系统的 net/pfflowd 获得。在写本章时它还不能在NetBSD上使用。
SNMP工具和PF相关的SNMP MIBs
简单网络管理协议(The Simple Network Management Protocol —— 简称SNMP) 是为网路管理员在一个集中的系统上收集和监控多个网络节点上系统运行和潜在配置变化的关键数据。
在1998年8月这个协议最早出现在RFC 1067,现在其第三个主要版本在RFCs 3411到 3418里面有定义。SNMP协议带有一个定义良好的接口以及一个扩展管理信息库(MIB)的方法,MIB定义了被管理的设备和对象。
如果你的网络足够大,支持SNMP的管理能力在正式的网络里就变得不可或缺的要素了,你可能在购买此书前已经先翻阅了这一小节以便确认次数是否值得你购买。
无论是具有专利还是开源的网络的管理和监控系统, 通常提供各种形式的SNMP支持 , 它是某些产品的核心功能。在BSD家族里, SNMP的支持一般由net-snmp软件包提供, 它提供了管理系统所需的检索和收集SNMP数据的一些工具。这个软件包在OpenBSD的 net/net-snmp, FreeBSD的 net-mgmt/net-snmp, 以及NetBSD的 net/net-snmp.
幸运的是, 还有一个net-snmp的扩展组件, 它可以让PF的数据用于SNMP监控。 Joel Knight 维护的MIBs就是用来收集PF、CARP、以及OpenBSD的内核探测器数据的, 它可以作为net-snmp补丁,下载地址http://www.packetmischief.ca/openbsd/snmp。
安装好这个package(软件包)和扩展后, 具有SNMP功能的监视系统也就可以详尽地监视(获取)PF数据了。 此外值得一提的是,FreeBSD的bsnmpd包含了一个PF模块。请参阅bsnmpd的用户手册以获取更多信息。
记住, 有用的日志(log)数据是提高调试效率的基本要素
在本章里我们介绍了在一个开启PF的系统上收集、显示和解析数据的要点。知道如何从系统行为中获取有用的信息就可以实现几个目的。
监视一个正在运行的系统状况对其本身来说是有意义的, 但是更为重要的是阅读和解析log数据以确定系统是真正按照规范运行。 另一个记录日志数据的重要作用是,在你修改配置后跟踪检查的其效果, 例如,当你优化系统后。
基于Log数据或其它的可观察项检查你的配置文件并做优化调整是我们下一章里涉及的一大块内容。