网络流分析-全-
网络流分析(全)
原文:Network Flow Analysis
译者:飞龙
引言

所有背景的网络管理员都有一个共同的、压倒性的愿望。无论你管理的是一个通过全球 MPLS 网状连接的 400 个独立的制造工厂的网络,还是负责三台计算机和一台老式的打印机,网络管理员都共同拥有一个持久而强烈的愿望:我们希望我们的用户闭嘴。
将问题归咎于网络很容易。网络无处不在。企业假设网络将完美运行,并据此做出决策。一个用户不能从他的 20 世纪 PC 打开另一个大陆上的文件服务器上的 900MB Excel 电子表格吗?网络问题。在遥远的 Farawayistan 的网站运行缓慢吗?网络问题。一个用户不能通过 33.6Kbps 的调制解调器获得更快的响应吗?网络问题。总的来说,用户不关心诸如带宽成本、跨大陆光纤的物理布局或光速这样的琐事。他们希望网络按他们想象的方式工作。
这个问题因网络的不可见性而加剧。路由器和交换机是黑盒子。你向网络提供电缆,它就提供连接。传统上,服务器在活动日志和报告方面比网络设备要好得多。系统管理员可以编写脚本,在服务器进程失败时发出通知并尝试解决问题,但很少网络管理员拥有可以自我监控或修复的设备。存储在网络设备上的使用信息最多只能显示最后几分钟。当用户报告应用程序失败时,许多系统管理员检查他们的日志并报告,“我没有问题。一定是网络的问题。”更复杂的网络管理员有如 MRTG、CiscoWorks 或 OpenView 等流量测量工具,但这些并不能证明网络没有问题。它们仅仅显示网络是否具有或缺乏软件可以报告的特定问题集。交换机上行链路端口上没有媒体错误,并不能说明 TCP/IP 错误或防火墙问题。在这样的最小化日志记录下,将问题归咎于网络变得非常容易,而且很难反驳。
此外,现代网络管理员通常没有正式的认证或培训过程。需要计算机科学学位来管理网络的日子已经一去不复返了。现有的网络管理认证通常是为系统管理员准备的。一个“操作系统供应商认证”的网络管理员实际上是在认证操作系统提供给网络的各项服务,而不是网络本身。例如,当你为微软 DHCP 服务器认证学习时,你会学到一些关于网络的知识,但更多的是关于那个特定的 DHCP 实现。网络服务管理是一项有用的技能,但与网络底层管理并不相同。网络管理员只能通过艰难的方式学习——而且确实非常艰难。
这是一件遗憾的事情,因为网络管理员可以在任何组织中扮演一个强大的角色。网络管理员可以帮助解决几乎每一个技术问题。网络管理员可以让自己成为组织中无价、不可或缺且不可替代的组成部分。一个掌握了工具、理解了协议并抑制了对周围人智力轻视的自然情感的网络管理员,除非公司在他周围解散,否则不会被解雇。
一些网络管理员理解这一点,并且总是乐于助人。如果一个用户或系统管理员报告了一个问题,这个网络管理员总是准备好跳进来,使用数据包分析器或防火墙日志并提供见解。这是出色的客户服务,如果用户能在网络管理员观察的时候复制出问题。复制问题会消耗无尽的时间,让所有相关人员都变得焦躁不安。
假设你有一个工具,可以具体告诉你昨天、上周或去年网络发生了什么?想象一下能够精确识别服务器和硬件变更对网络的影响。假设你能告诉系统管理员新服务器传输了哪些虚假流量?就让我们暂时梦想一下,能够明确且没有否认风险地声明,“那个问题不是网络问题。”然后想想,通过利用现有的设备来完成所有这些。
网络流量分析让你能够做到这一点。也许你不会完全平息你的用户——没有神圣干预是无法做到的。但你可以在问题发生之前识别出你的网络上的问题。你可以权威、明确和果断地回答问题。人们将不再自动责怪网络。你的工作将变得不那么有压力,因为你将不再认为你知道发生了什么。你将知道。
本书将引导网络管理员利用任何免费的类 Unix 操作系统、免费软件和现有的网络硬件构建一个基于流的网络管理系统。
网络管理和网络管理
网络管理员和网络经理之间有什么区别?
网络管理 包括配置硬件、联系技术支持和布线。网络管理 涉及对网络的决策。网络经理通常从网络管理员起步,并且可能仍然执行网络管理任务,但他们的技术知识指导管理决策。
虽然改变你的职位名称需要管理层的干预,但任何网络管理员都可以通过完成所需的工作转变为网络经理。你负责你的设备,并且你可能在某个地方能够找到一些计算资源的访问权限。最困难的投入将是你的时间。然而,一旦你开始提供基于事实的回答和诊断,人们就会注意到这种变化。随着时间的推移,公司管理层将开始让你参与关于网络的决策,甚至可能寻求你关于建立在网络之上的业务流程的建议,无论你的名片上写着什么,你都将成为事实上的网络经理。
网络管理工具
对于一个网络管理系统来说,这些说法相当令人印象深刻,尤其是如果你熟悉现有的网络管理工具。许多人对自己广泛使用的网络管理系统感到自豪。让我们来看看一些流行的免费网络管理工具,看看它们是如何相互配合的,以及流量分析如何改进它们。
MRTG、Cricket 和 Cacti
MRTG、Cricket 和 Cacti 使用 SNMP 在设备接口上生成网络流量的图表,并将结果存储在固定大小的数据库中。知道在任何时候有多少流量穿过你的网络是绝对必要的,我自己也大量使用这类工具。固定大小的数据库意味着你不需要担心数据库管理;它们易于设置,并能快速产生有用的信息。
知道你的电路已满可以解释为什么连接速度慢,但接下来的明显问题是“满的是什么?”MRTG 风格的工具无法回答这个问题。流量可以。此外,这些工具通常使用五分钟的流量平均值。它们掩盖了短暂的峰值和低谷。最后,这些工具将历史数据压缩为长期平均值。如果你想了解六个月前的流量细节,你必须重新配置这些工具或使用另一个工具。
RTG
与之前的工具类似,RTG 使用 SNMP 来测量穿过设备接口的网络流量,并绘制数据图表。与 MRTG 及其衍生工具不同,RTG 测量更短的流量间隔,并将每个单独的结果存储在数据库中。它提供了对流量拥堵的更多详细可见性。如果你想查看网络接口在单分钟内的流量变化,RTG 就是你的朋友。你还可以与历史数据进行详细比较。
数据库的存在意味着你必须对数据库有所了解,或者拥有无限的磁盘空间。此外,RTG 不能显示流量的内容,只能显示流量的数量。它解决了 MRTG 风格工具的一个问题,但不是其他问题。
Nagios 和 Big Brother
如果你不再关注流量数量,你还需要检查你的网络设备的健康状况。Nagios 和 Big Brother 等免费软件在这方面非常有用;当交换机的冗余电源失败、端口开始产生 CRC 错误或交换机自行重启时,你都可以得到警报。你必须有这些信息来维护一个可靠的网络。
知道你的硬件正在正常运行是至关重要的,但一个交换机运行正常并不意味着通过它的流量没有遇到麻烦。一个功能正常的交换机或路由器会像期望的流量一样可靠地传输不期望的流量。
CiscoWorks、OpenView 以及更多
然后是你拥有的商业网络管理套件。这些产品中的大多数要么是带有漂亮界面的工具包,要么仅限于简单的网络。这些工具很有吸引力。它们看起来任何人都可以使用。但这些工具往往想要控制你的整个计算基础设施,从路由器到桌面,而在生产环境中部署它们通常都会失败。
大多数人没有意识到的是,当你设置好这些软件套件以符合你的需求时,你所做的工作与构建自己的流量分析系统所做的工作一样多。然而,你确实有满足感,那就是把本应属于你口袋里的钱给了其他公司。 (你说那是老板的钱?为商业产品获取报价。在绩效评估时,告诉你的经理你没有花那笔钱就得到了相同的结果,并希望分得一杯羹。这样做比花完钱后要求加薪更有可能成功。)
足够抱怨了:解决方案是什么?
解决方案:网络管理很糟糕。工具都不够好,或者又贵又不好。你如何摆脱这个困境?你记录通过你的网络传输的流量。
是的,这是一个很高的要求。幸运的是,你不需要记录每个网络事务的全部内容。暂时想想网络管理员的职责。你的部分责任包括提供网络服务,如 DNS 和 DHCP。你可能每隔几天就要给你的代理服务器喂食,并在每周一早上清理入侵检测系统中的脚本小子。但暂时把运行在网络上的服务放在一边,考虑一下基础网络。
网络的存在就是为了将流量从一个主机传输到另一个主机。仅此而已。网络管理员负责实现这一点。
也许您是公司唯一的 IT 人员,并且还负责其他所有事情。然而,大多数时候,网络管理员与系统管理员、一两个数据库管理员、帮助台和其他 IT 专业人员一起工作。在这种情况下,网络管理员的职责是及时交付数据包。这些数据包的成功交付完成了您的职责。
能够证明数据包已到达目的地并被接受将彻底改变您与同事的关系。突然之间,您有了证据。网络不再是每当出现问题就无差别地承担责任的实体。当然,其中一些错误将是您的责任。但许多错误不是,没有什么比第一次彻底证明问题不是您的,而且您可以严格证明问题所在的感觉更令人欣慰。(这里的技巧在于不要用这个证据疏远那些同事,但我稍后会谈到这一点。)
您不需要记录流量内容的完整记录来证明您的观点。您只需要证明主机之间成功发生了网络级通信。例如,如果用户无法显示您内部 Web 服务器上的页面,您不需要记录用户桌面和服务器之间网络连接内容的完整记录。您只需要记录客户端和服务器之间发生了网络对话,网络在两者之间传输了数据,并且网络层上对话正常且无错误地结束。您不需要记录对话中的每个单独的图像或文本块。这不是网络管理员的职责。证明网络在客户端和服务器之间传输了 Web 流量,证明了网络正常工作。请注意,作为网络管理员,您仍然有责任帮助解决问题;只是没有人会在您工作时责怪您。
Flow-Tools 及其先决条件
Flow-tools 是标准可免费获得的流量管理和分析工具包。尽管您可以找到许多其他流量管理工具,但 Flow-tools 存在时间最长,并且是最广泛部署的免费工具包。许多人基于 Flow-tools 编写了流量分析接口,本书将介绍其中几个。
Flow-tools 是为 Unix-like 系统编写的,例如 Linux、OpenSolaris、各种 BSD、商业选项如 AIX 等,以及许多其他系统。我的参考平台是 FreeBSD,但本书中的所有内容在 Linux 上也能正常工作。您可能会在使用更具挑战性或独特的平台时遇到困难。本书提供了流量管理工具的命令示例,但您必须知道如何调用超级用户权限、导航文件系统等。
这部分软件大多使用 Perl。你不需要编写自己的 Perl,但你需要编辑 Perl 脚本来设置诸如公司名称和 IP 地址之类的变量。一些流量软件包括特定的 Perl 钩子,我将为 Perl 爱好者介绍它们。
如果你想要使用 flow-tools 执行流量数据的即兴报告,你需要一个绘图程序。我讨论了gnuplot。如果你在桌面上安装了 X 服务器,你将最舒适地使用gnuplot,但这不是强制性的。
此外,要使用 flow-tools,你必须理解 Unix 纪元时间。纪元时间是自 1970 年 1 月 1 日 00:00:00 起,在 UTC 时区内的秒数。许多网站提供纪元到日期的转换器。你可以在命令行中使用date命令将纪元秒转换为日期,但语法在不同的类 Unix 操作系统中有所不同。
谈到时间,在你的网络中拥有良好的时间管理将增强你的网络管理能力。因此,我建议安装并使用网络时间协议。为你的网络使用权威的时间源。如果你的服务器日志中的时间戳与你的网络流量记录中的时间戳相匹配,你的分析将会容易得多。
流量可以包括边界网关协议(BGP)信息。我讨论了如何管理流量 BGP 数据,但这些解释假设了基本的 BGP 知识。如果你不使用 BGP,你的流量数据将不包含任何 BGP 数据。你可以安全地跳过基于 BGP 的流量数据的讨论。
最后,你必须理解网络。如果你现在对网络基础知识没有牢固的掌握,但在完成你的流量管理实现时,你将会有。
流量和本书
在你能够使用流量信息管理网络之前,你必须理解流量是如何工作的,数据来自哪里,它是如何收集和处理的,以及基于流量的管理的优势和局限性。第一章介绍了流量。
许多路由器和交换机可以执行流量导出,其中硬件跟踪流量数据并将其传输到管理系统。如果你的硬件不能导出流量,你可以在软件中执行流量导出。第二章讨论了流量导出以及如何在硬件和软件中配置它,以及如何使用行业标准流量工具软件包从许多不同的网络设备中收集那些流量记录。
第三章教你如何查看你收集的流量记录。流量记录包含大量信息,选择合适的查看格式将帮助你获得所需的认识。
流量记录包括通过网络传输的所有流量,但你通常只对非常具体的信息感兴趣,例如特定电路或特定主机的流量。第四章演示了如何过滤流量以仅显示有趣的数据。
有时你可能更感兴趣于报告汇总的流量数据,而不是单个流量。哪些主机发送了最多的流量?你网络中最受欢迎的 UDP 端口是什么?哪些主机连接到最多的其他主机?Flow-tools 支持广泛的报告,我将在第五章中介绍。
另一个常见的需求是简单可视化网络流量;换句话说,以图形格式展示流量记录。第六章介绍了 FlowScan,这是一款基于 Web 的软件,为用户提供流量图表。它还介绍了用于编写 FlowScan 的Cflow.pm Perl 模块,如果你有兴趣,你可以用它来编写自己的流量分析软件。
虽然 FlowScan 对用户来说效果很好,但网络管理员需要更强大的工具。第七章介绍了 FlowViewer,这是一个基于 Web 的工具,允许你深入分析你的流量。
基于 Web 的软件可以处理许多网络可视化任务,但自动化可视化和图形化临时数据并不在其中。有时,你需要准备图表来显示今天的流量与上周或去年相比的情况。在第八章中,你将使用gnuplot创建任意流量数据的图表。
最后,第九章讨论了一些流量收集的边缘情况,并讨论了如何使用流量记录主动改进你的网络。
然而,在进行所有高级操作之前,让我们先深入、仔细地看看第一章中的流量。
第一章. 流的基本概念

我假设到这一点,你已经接受了流可以解决你的问题的想法。现在,让我们具体了解一下流是什么,它们有什么好处,以及你如何实现和分析它们。本章重点介绍在 TCP/IP 网络上常见的流,特别是 TCP、UDP 和 ICMP 流。
本章假设你已具备 TCP/IP 的基本理解,并试图帮助你更深入地理解它。如果你发现自己越来越困惑,我建议你查阅 Charles M. Kozierok 的《TCP/IP 指南》(No Starch Press,2005 年)。我也鼓励你花些时间与数据包嗅探器一起观察现实世界中的 TCP/IP 事务,因为没有比观察它们执行实际工作更好的学习网络协议的方法了。
注意
经验丰富的网络管理员可能会发现本章重复了他们已经知道的主题。如果你已经理解了三次握手,如果看到0x2让你想到“TCP 重置”,那么你可能想跳过这一章。然而,本章从基于流的角度覆盖了这些材料,所以如果你决定跳过,当你困惑时不要来找我哭诉。
什么是流?
严格来说,一个流是一系列具有相同源和目的 IP 地址、源和目的端口以及 IP 协议的分组。这也被称为五元组 IP 流。流这个词有时也用来指单个流的聚合。流记录是关于流的信息摘要,记录了哪些主机与哪些其他主机通信,何时发生这种通信,如何传输流量,以及关于网络对话的其他基本信息。流分析系统收集流信息,并为你提供一个系统来搜索、过滤和打印流信息。流记录总结了网络上每个连接。
你想知道哪种流量正在填充你的互联网 T1,客户端 PC 在做什么,或者哪种错误正在到达服务器吗?检查流记录。想知道昨天凌晨 3 点到 3 点 05 分之间网络发生了什么,当时文件服务器神秘地崩溃并重新启动吗?检查昨天的流记录。
好消息是,大多数网络硬件都可以报告流量作为流。让这种硬件将流信息发送到记录主机只会产生很小的开销;你不需要安装任何东西。
由于流量记录不包括网络连接交换的数据,因此流量记录很小。例如,在我写这篇文章的时候,我的数据中心有一个 DS3,几个 T1,一个千兆以太网骨干网,以及各种较小的子网和 DMZ。尽管如此,三年完整的流量记录使用的磁盘空间不到 100GB。当然,这不算小,但按照现代标准,这只是一小部分磁盘空间,远低于捕获每个交换完整内容所需的磁盘空间。
即使有数 GB 的数据,流量记录也不允许无限的故障排除。任何曾经使用数据包嗅探器来监视 telnet 或未加密 Web 会话的人都知道,网络中穿越的所有内容都可以被捕获、分析和重建。一个监听者可以看到用户访问了哪些网站,用户下载了哪些文件,用户向网站发送了什么内容,以及交换中使用的任何用户名和密码。流量记录不包含这些数据;它们只是告诉网络管理员,一个客户端访问了运行在特定 IP 地址上的网站,用户与该网站建立了多少连接,交换了多少数据,但不是这些交换的内容。
仅记录流量信息而不是完整的数据包可能听起来有限,但国家安全局(NSA)正是通过对电话记录进行类似分析来捕捉罪犯和恐怖分子。同样,AT&T 的无线窃听是通过网络流量分析发现的。知道谁和谁交谈,交谈的时间以及每一方说了多少是非常宝贵的。
流量与会话的比较
不同的协议使用诸如会话、事务和对话等词汇来描述网络交互。这些与流量有何不同?请记住,流量中的所有流量都是同一方向流动的。当客户端连接到 Web 服务器并下载文件时,它创建了一个简单的 HTTP 会话。然而,这个会话(即这个事务)实际上是两个流量:一个从客户端到服务器,另一个从服务器到客户端。每个流量都反映了另一个。
流量系统架构
典型的基于流量的管理系统有三个组件:一个传感器(或多个传感器)、一个收集器和报告系统。组件也可以组合,正如你将在第二章中学到的。
一种称为探针的传感器是一种监听网络并捕获流量数据的设备。传感器可能是一个具有集成流量导出功能的交换机、路由器或防火墙,或者它可能是一段软件,监听以太网分接或监控模式下的交换机端口。传感器跟踪网络连接,并在它认为连接已完成或连接达到超时后,传输数据。
收集器是接收传感器记录并将它们写入磁盘的软件。收集器是您基于流的网络管理基础设施中绝对关键的部分。不幸的是,没有一种通用的磁盘格式被普遍接受用于存储流量记录。这使分析变得复杂,并限制了您可以使用报告工具的范围,但您将在本书中学习如何克服这一点。
最后,报告系统读取收集器文件并生成易于理解的报告。报告系统必须理解收集器使用的文件格式。
你可以找到许多基于流的管理系统中每个组件的不同实现。每个硬件供应商的高端设备都配备了流量传感器,许多人也为他们偏好的操作系统编写或实现了流量传感器。一些不同的收集器曾经突出,后来又消失,例如 cflowd,许多想要展示他们对最新酷脚本语言掌握的人也编写了满足他们特定需求的报告系统。
新手可能会看到众多选项,从而认为流量管理过于复杂,甚至不敢尝试。更糟糕的是,其中许多软件已经过时,但 1998 年的互联网邮件列表存档却强烈推荐它们。新手可能会花费数小时追踪这些软件,最终发现它们无法用现代编译器构建。此外,许多可能的组合存在细微的不兼容性。
这种情况令人沮丧不已,许多人在仅仅几小时后就会放弃对基于流的网络管理的研究。
本书介绍了一套单一的软件组件,它们可以协同工作。这些组件要么仍在积极开发中,要么拥有广泛的用户基础。核心平台是 flow-tools 工具包([code.google.com/p/flow-tools/](http://code.google.com/p/flow-tools/))。多年来,flow-tools 一直是标准化的免费流量收集和报告软件,并且与所有常见传感器兼容。此外,许多报告工具在正确配置的情况下会利用 flow-tools 的数据格式。你将在本书中学习如何使 flow-tools 与其他一些流行的工具集成。
网络流量历史
高速路由器和交换机硬件在不对操作系统进行操作的情况下直接引导流量,换句话说,即不在软件中做出每个转发决策。数据包路由的决策在可能的最底层做出,通常在硬件内部。大约在 1996 年,思科发明了一种通过流量引导路由决策的方法。随后,流量信息的价值得到了认可,并作为名为 NetFlow 的功能提供给网络管理员。
NetFlow 版本
NetFlow 在其历史中经历了多次修订。
NetFlow 版本 1
NetFlow 版本 1 是思科最早的发布版本。其他供应商对 NetFlow 报告协议进行了逆向工程,并发布了他们自己的兼容 NetFlow 的报告系统。一些供应商仍然支持 NetFlow 版本 1,如果你只有这个版本,它仍然可以解决你许多问题。它只包含最少的流量信息。
NetFlow 版本 5
最古老的广泛部署的流量记录格式是 NetFlow 版本 5。许多供应商,如 Juniper 和 Nokia,实现了此协议。
NetFlow 版本 5 包括七个关键值:源 IP 地址、目的 IP 地址、源端口(仅 TCP 和 UDP 协议)、目的端口、IP 协议、流量到达系统上的接口,以及 IP 服务类型。它还包括有关 BGP、导出器 IP 地址以及一些其他流量特性的信息。尽管随着时间的推移,流量记录变得越来越详细,但 NetFlow 版本 5 对于大多数环境来说已经足够了。
NetFlow 版本 7
NetFlow 版本 7 仅由高端思科 Catalyst 交换机支持。其流量记录格式包括版本 5 中不可用的交换和路由信息,例如流量的下一跳地址的 IP 地址。如果你有支持 NetFlow 版本 7 的硬件,这本书将向你展示如何利用它。
NetFlow 版本 8
NetFlow 版本 8 是一组类似的格式,用于汇总信息。如果你有很多高带宽连接,并且必须最小化你用于收集和分析流量记录的资源量,NetFlow 版本 8 可能很有用。然而,只有思科支持它,并且它很少使用。然而,鉴于我们不断增长的计算能力和磁盘容量,NetFlow 版本 8 通常并不具有吸引力。
NetFlow 版本 9
NetFlow 版本 9 是思科的最终版本。它是基于模板且可扩展的,这意味着第三方供应商可以将任意信息添加到 NetFlow 记录中。版本 9 也是第一个支持 IPv6(IP 版本 6)的版本。NetFlow 版本 9 仅在少数商业产品中部署。
NetFlow 竞赛
随着思科部署越来越多的 NetFlow 版本,其他网络公司看到了导出和报告流量数据的好处。例如,思科根据其客户的需要开发了 NetFlow,这些需要并不一定是全球网络社区的需要。其他供应商根据其客户的需要实现了基于流的类似报告。因此,NetFlow 的竞争对手出现了,其中最著名的是 sFlow。来自 3Com、HP、Extreme 和 Juniper 等供应商的一些设备支持 sFlow。
注意
sFlow 特别不是 NetFlow,因为思科拥有这个词。大约在 sFlow 发布的同时,人们开始使用流量导出而不是NetFlow。
随着竞争对手数量的增加,网络社区看到了一个共同标准定义的流导出协议的优势。当前的工作重点集中在这种基于标准的方法上。
最新标准
在 2000 年代初,互联网工程任务组创建了一个工作组来定义流格式并防止进一步的流格式碎片化。该工作组选择使用 NetFlow 版本 9 作为基本协议,并进行了少量修改以使其更友好。思科仍然参与其中,但现在作为成员而不是唯一的控制利益方。
网络流标准的最新版本被称为 IP 流信息导出(IPFIX)。尽管许多硬件供应商也在实施 IPFIX 支持以及旧版本的支持,但该格式很少被部署。IPFIX 比早期的流版本更复杂,并且使用更多的系统资源。早期 NetFlow 版本之间的差异是渐进式的,但 NetFlow 版本 9 和 IPFIX 代表了与早期版本的重大突破。人们也在研究使用 IPFIX 来管理非网络数据,例如安全事件。
本书将探讨的解决方案涵盖了 NetFlow 版本 1 至 7。版本 8 和 9 很少需要,尽管 IPv6 需要 NetFlow 版本 9 或更高版本,但世界上大多数人对 IPv6 不感兴趣,并且将保持这种不感兴趣的态度,直到 IPv4 地址空间短缺变得无法忍受。一旦 IPv6 不再是可选的,我预计供应商将直接跳到 IPFIX。当 IPFIX 变得更加普遍时,我毫不怀疑用户社区将把 IPFIX 支持添加到本书涵盖的工具中。
NETFLOW VS. FLOW EXPORT
在本书中,有时我会使用“NetFlow”这个词;有时我会使用“流管理”或“流导出”。它们之间的区别是,思科拥有“NetFlow”这个词,而其他供应商支持与 NetFlow 兼容的流导出技术。你可能在使用 NetFlow,或者你可能在使用一个与 NetFlow 兼容的流导出系统,这取决于你的设备。这种区别只是语义上的,但只要可能,我都会避免惹恼任何可能像压扁虫子一样压垮我的跨国公司。
现实世界中的流
“流是一系列所有共享相同的源和目的 IP 地址、源和目的端口以及 IP 协议的分组。”这到底是什么意思呢?让我们拆解这个描述,看看它在现实世界的几个地方真正意味着什么。我将从最简单的网络流量开始,一个 ping 请求和响应,然后继续到更复杂的 DNS 和 HTTP 请求的例子。
ICMP 流
尽管 ICMP 最常与 ping 请求相关联,但它也携带了互联网路由和管理的基本指令。某些个别流,如 ICMP 重定向,可以携带有用的信息,但为了简单起见,我将涵盖常见的 ping。
ICMP 没有 TCP 风格的标志,也没有 TCP 和 UDP 那样的端口。相反,ICMP 数据包被分配一个ICMP 类型和一个可选的ICMP 代码。ICMP 类型标识了数据包的一般用途。ping 请求和响应消息有自己的 ICMP 类型,并且一个 ICMP 类型可能关联有提供更多详细信息的 ICMP 代码。(你将在第三章中了解更多关于 ICMP 类型和代码的内容。)
要 ping 服务器,客户端会创建一个包含客户端源地址和服务器目标地址的 ICMP 数据包。客户端将 ICMP 类型设置为 8,或echo-request,并将数据包发送到网络。这个 ping 数据包是第一个数据流的全部内容。
作为回应,服务器创建了一个包含服务器源地址、客户端目标地址以及 ICMP 类型为 0,或echo-response的 ICMP 数据包。这是完整的第二个数据流。
话虽如此,如果你的客户端发送多个 ping 请求,流系统会将后续的 ping 分配到同一个数据流。例如,Windows 系统通常发送五个 ping 请求并期望得到五个 ping 响应。你的流系统记录一个包含五个请求和一个包含五个响应的单个数据流。
流传感器无法知道 ICMP 数据流何时完成,因为流量中没有内部标记表明“不会再有数据包到达”。传感器将 ICMP 数据流保留在内存中,直到超时时间到期,此时传感器将数据流标记为完成并将它们传输到收集器。
UDP 数据流
现在考虑一个基本的 DNS 请求,以了解 UDP 数据流是如何工作的。UDP 会话比 ICMP 数据流稍微复杂一些:尽管 UDP 不像 ICMP 那样使用类型和代码,也不像 TCP 那样有标志,但 UDP 使用 TCP 风格的端口号。此外,UDP 没有内置的会话或事务概念,这就是为什么人们将其描述为无连接。然而,UDP 确实携带有用的应用层数据,并且大多数 UDP 流量都是某种会话或事务的一部分。在普通网络上最常见的 UDP 数据流是 DNS 请求。DNS 请求是可能的最简单的网络请求之一,并产生最短的数据流。其他 UDP 网络协议,如 bootp,在每个数据流中生成更多的数据包,但为了理解数据流,你将在这里查看谦逊的 DNS 请求。
当一个客户端连接到 DNS 服务器时,它会创建一个包含客户端源 IP 地址和服务器目标 IP 地址的 UDP 数据包。与 TCP 类似,UDP 请求从客户端的一个未使用端口发起,并使用标准的 DNS 端口 53 作为目标端口。一个简单的 DNS 查询,例如请求www.nostarch.com的地址,可以完全包含在一个数据包中。这个单一的数据包是第三个示例数据流的开始。
第四个流开始于服务器通过创建一个源 IP 为服务器、目标 IP 为客户端的 UDP 数据包来响应。同样,源端口和目标端口与客户端发送的数据包相反。包含典型网站信息的 DNS 响应也完全包含在一个数据包中。
这些流现在已经完成,不会再有流量作为它们的一部分传输。你可以在图 1-1 中看到这些流。

图 1-1. UDP 网络事务与流成员
因为 UDP 是无连接的,网络流量中不包含标记来告诉观察者某个特定的会话已经完成。数据包没有 TCP 式的 FIN 标志来宣布“我完成了,所以现在挂断”,因此流量传感器无法知道这些流已经完成。传感器将这些流保存在内存中,直到超时时间到期,此时传感器将流标记为完成并将它们传输到收集器。
TCP 流
我将涵盖的最复杂的网络流是 TCP 流,例如那些由 Web 服务器和浏览器使用的流。TCP 协议包括 UDP 使用的端口,还包括指示连接状态的内部标志。TCP 告诉客户端和服务器连接是被请求、进行中还是正在拆除。例如,现在你有了www.nostarch.com的 IP 地址,让我们看看一个 Web 客户端从这个网站请求单个、静态、简单的 Web 对象。^([1)]
第五个流开始于一个连接到 Web 服务器的客户端向服务器发送一个数据包,该数据包的源 IP 是客户端,目标 IP 是服务器。客户端在本地系统上分配一个未使用的端口,用于此连接的专用,这就是数据包的源端口。Web 服务器通常运行在端口 80 上,因此这是数据包的目标端口。在连接的第一个数据包中,客户端设置同步(SYN)请求标志(这个初始数据包通常被称为SYN 请求)。客户端正在联系服务器,说“嘿,我能和你说话吗?”
当服务器在端口 80 上接收到 SYN 请求并决定接受连接时,它准备一个响应数据包。这个响应数据包的源地址是服务器,目标地址是客户端。源端口是 80,客户端请求的端口;目标端口是之前数据包的源端口。
第六个流是作为对 SYN 数据包的响应发送的数据包,因此服务器设置了确认(ACK)标志。因为服务器在此 TCP/IP 会话之前没有发送任何数据包,它还设置了 SYN 标志以请求同步(通常称为SYN-ACK 数据包)。
一个网络事务中的第二个流?是的。记住,单个流共享相同的源和目的 IP 地址,以及其他一些内容。你有一个来自客户端的源地址和一个来自服务器的源地址的流。一个流的源端口与另一个流的目的端口相匹配,允许你将它们匹配起来,但这些都是两个独立的流。流让你能够确定在任何给定事务中每个方向的流量有多少。
当客户端收到服务器的响应时,它会将传入的数据包与它试图与该服务器建立的连接进行匹配。客户端向服务器发送一个从分配的本地端口发出的数据包。现在连接已经同步:客户端和服务器都知道连接中涉及的 IP 地址以及每边的端口号(以及唯一标识此连接的序列号和其他一些特性)。然而,由于这个数据包是现有连接的一部分,因此不需要 SYN 标志。但是,客户端必须确认服务器在其最后的数据包中包含的 SYN 请求,因此这个下一个数据包包括 ACK 标志。
从客户端到服务器的这个数据包可能是事务中的第三个数据包,但它是由客户端发送给服务器的第二个数据包。它共享事务中第一个数据包的源和目的 IP 地址以及端口号,这两个数据包都使用相同的 IP 协议(TCP)。这个第三个数据包是第一个流中的第二个数据包。(图 1-2
图 1-2. 带有流成员的 TCP 三次握手
现在连接已经建立,客户端可以传输实际数据,例如 HTTP GET 请求。GET 请求是第一个流的一部分,从客户端到服务器。服务器的响应,包括任何 HTML、图像或错误代码,成为第二个流的一部分,从服务器到客户端。数据包现在来回流动,包括必要的 ACK 以确认先前数据包的接收。
事务结束时,任一方发送一个设置了“完成” (FIN) 标志的数据包。这个数据包被称为 FIN 请求,它标志着 TCP/IP 会话的结束。另一系统发送一个 ACK 然后发送它自己的 FIN。客户端向最后的 FIN 发送 ACK,关闭连接。流量传感器看到 FIN 和 ACK,终止两个流,并立即将 TCP 流记录传输到收集器。
其他协议
流量管理系统可以跟踪除 ICMP、UDP 和 TCP 之外的协议,但这三个协议构成了网络流量的绝大多数。你的流量系统将记录用于 IPSec VPN 的 AH 和 ESP 协议等协议的流量,但流量不会记录这种流量的内部特征。
对于这些不太常见的协议,流量系统会记录协议、时间、数据包数量以及其他重要的流量信息。
^([1]) 当然,No Starch Press 网站是完全动态的、交互式的,并且由一个复杂的自我修改人工智能为每个观众单独生成,它没有任何简单的“个体对象”。你应该去看看。在那里买些东西吧。
流量导出和超时
大多数中高端路由器和交换机存储流量数据,但它们并不一定提供一种让人类可以在本地查看流量数据的方法。相反,为了分析流量记录,你必须首先从硬件中将流量记录导出到计算机上。流量传感器在网络活动完成或超时到期时导出它们的记录。
导出的记录不一定是完整的 TCP/IP 会话。例如,从互联网网站下载 ISO 镜像可能需要非常长的时间,而这个会话可能会在几个连续的流量记录中表示。
为什么要把长时间运行的会话拆分成多个记录呢?假设你的路由器只在每个 TCP/IP 会话结束时导出流量记录。现在假设你的一个用户开始了一个可能需要几个小时才能耗尽你的互联网连接的大型下载。作为网络管理员,你很快会接到一个电话,抱怨互联网真的非常慢。为了解决这个问题,你将希望识别出过去几分钟内你网络上的情况,而不仅仅是当大下载完成时。通过将长时间运行的连接记录拆分成每几分钟一个的离散流量记录,路由器让你能够几乎实时地查看数据。你可以在这个大下载仍在进行时查看流量记录,并在问题持续一整天之前识别出问题。你可以关闭违规用户,或者如果用户是高管或 IT 团队成员,你可以通知打电话的人,由于太阳辐射干扰,互联网将暂时变慢,他们只需等待即可。
网络硬件根据配置的超时时间或设备跟踪单个流量的最大时间来创建流量记录。当一个特定连接持续的时间与超时时间相同,设备就会导出流量记录并创建一个新的记录。例如,如果你的路由器有一个一分钟的超时时间,它就会每分钟导出一次大下载的记录。尽管这个记录不会包括完整的 TCP 会话,但你可以通过查看你的流量记录来说,“在这分钟内,最大的带宽使用者是这台特定的工作站从这个特定的网站下载。”如果你需要,你有时间进行干预。
超时还有助于管理 UDP、ICMP 和其他非 TCP 流量的流量记录。网络设备将为这些交易中的每一个创建流量记录。当超时时间到期时,设备导出流量记录。尽管网络设备无法确切知道 UDP 流量何时结束,但超时保证了该记录最终会被导出。
你可以更改超时时间以适应你的需求。我将在本书的后面部分讨论这样做的原因,但你应该知道更改超时时间会影响系统资源。增加超时时间会增加设备进行流量跟踪所需的内存和 CPU。
数据包采样流量
流量导出最初出现在硬件资源非常有限的路由器上。在这些设备中,随着接口带宽的增加,跟踪每个数据包所需的计算能力超过了路由器或分接器能够提供的。相反,硬件采样数据包来创建流量数据,只记录和导出通过设备的数据流中指定的一部分。这种流量数据必然是不完整的。
今天,大多数硬件可以在大多数小型和中型环境中跟踪通过机器的大部分或所有流量.^([2]) 一旦你开始进入 10 千兆网络,对每 100 个或每 1000 个数据包进行采样就成为了常态。随着硬件容量的增加,我们将进行更全面的采样,但带宽也会相应增加。一旦太比特以太网变得普遍,我预计我们将有在 10 千兆以太网上进行流量捕获的能力,即使我们真的需要那么多的数据!
你应该采样你的网络流量还是记录所有流量?如果可能的话,你应该记录通过你的网络的所有流量。只有当你的硬件无法支持完整的流量跟踪时,你才应该进行采样。采样一些数据比没有数据要好,但尽可能记录更多细节对于故障排除来说更有用。
你现在应该对流量系统的工作方式、其组件如何组合以及如何组装流量分析系统有一个很好的了解。让我们从你的流量工具收集器和你的第一个传感器开始。
^([2]) 我与互联网软件联盟(ISC)的一位资深技术专家就其流量导出系统进行了交谈。ISC 从其多个千兆比特的互联网上行链路中采样。如果你,像 ISC 一样,拥有的带宽只能用“你肯定是在开玩笑吧(哔哔)”来形容,你可能也需要进行采样。
第二章。收集器和传感器

收集器和传感器是任何流系统不可替代的组件。为什么?你可以以无数种方式分析数据,但在你这样做之前,你必须收集和存储数据,而这是通过传感器和收集器来完成的。
由于这些流系统组件至关重要,你将从收集器开始实施,然后进行到第一个传感器。
收集器注意事项
收集器是接收来自网络设备记录的主机,你将在那里进行大部分工作。你必须对你的收集器进行良好的系统管理,但在硬件、操作系统和软件方面你有很大的灵活性。
操作系统
收集器运行在类 Unix 操作系统上。几乎任何现代类 Unix 操作系统都足够使用。我推荐使用 BSD 操作系统。(如果你从未使用过 BSD,请允许我建议你购买我的 BSD 书籍之一,例如《Absolute FreeBSD》或《Absolute OpenBSD》。)
话虽如此,Linux、OpenSolaris 或任何具有最新 GCC 编译器和库的标准 32 位或 64 位类 Unix 系统都可以正常工作。然而,如果你的操作系统不太常见,你将面临更多关于收集器和报告系统的问题。一些商业类 Unix 操作系统因其符合技术标准但与所有其他类 Unix 操作系统在奇怪或根本无法言喻的方式上有所不同而闻名。[1] 选择一个与其他系统兼容性好的系统。
无论你选择哪个系统,它都必须是安全的。每个活跃的类 Unix 操作系统都有当前的安全和加固指南。获取它。阅读它。使用它。你的收集器不应提供除与流管理相关的其他服务。这将让你比多用途机器更能加固系统。
系统资源
流收集器除了磁盘空间外,使用的系统资源非常少。(我曾在奔腾 Pro 服务器上运行过流收集器。)
需要的磁盘空间取决于你网络上的流量类型以及你希望保留记录的时间长度。在我的环境中,平均 5Mbps 的数据流每月大约使用 2GB 的磁盘空间。今天,磁盘容量增长速度超过了网络利用率。我发现,如果你继续购买更大的硬盘,你有可能无限期地保留所有数据。
额外的内存和 CPU 资源将加速流报告。当为流收集器配置机器时,我建议使用较慢但容量更大的硬盘(如“绿色”硬盘之一)并增加内存。较慢的硬盘可以节省你的金钱和电力,额外的内存将提高系统的缓冲区缓存,并让你更快地分析数据。
为你的收集器至少配备 4GB 或更多的 RAM。任何现代类 Unix 操作系统都会在 RAM 中缓存最近访问的磁盘文件。大量的内存将比其他任何东西都能加速在同一数据上运行多个报告。
^([3]) 我本想点名道姓,但 IBM 的律师比我强。
传感器考虑因素
传感器是捕获你的网络流量数据并将其转发到收集器的设备或程序。流量传感器可能是基于流量的管理系统中最难实施的部分,尤其是在地理上大的网络中。你不想为了安装一个流量传感器而穿越整个大陆!
好消息是,你不必担心那些长途旅行。事实上,你可能已经安装了流量传感器,但你还没有配置它们。你有互联网边界路由器吗?让它们充当传感器。你有一个高端的 Cisco 交换机吗?太好了,就用那个。
如果你没有能够完成这项工作的硬件,你可以在软件中实现流量传感器。
位置
如果你有一个中等大小的网络,你很快就会意识到你需要对传感器位置进行选择。也许你在总部有几个小型交换机和一台大型核心交换机,半打 DMZ,一个互联网边界,以及几个通过 VPN 或 MPLS 连接的远程设施。你可以在这些位置中的每一个都安装传感器。哪些是值得努力的?
互联网边界
从你的互联网边界开始。几乎所有的现代商用级路由器都可以导出流量记录。分析这些流量将告诉你如何使用你的互联网接入。了解你的流量中有多少是网页浏览,有多少是访问 VPN,将立即帮助你做出更好的决策。
以太网核心
接下来看看你的网络的以太网核心。内部局域网将比广域互联网连接有更多的流量。分析内部网络的流量数据将迅速暴露问题、配置错误和性能问题。你的网络架构决定了传感器的放置。
如果你有一个大型核心交换机,例如 Cisco 4000 或 7000,交换机本身可能可以导出流量信息。
如果你以太网核心中有多个交换机,你可能认为需要在每个上都进行流量导出,但这过于雄心勃勃。你不需要记录办公室网络中每个交换机上通过的每个数据包的完整记录。
在考虑数据捕获位置时,考虑流量如何从设备流向设备,并仅从中央“瓶颈”配置流量导出。例如,我的主要数据中心有一个在大型企业中常见的配置:一个大型 Cisco 交换机在其核心,以及每层的布线间中的客户端交换机。每个布线间的交换机和每台服务器都直接连接到核心交换机。任何离开本地交换机的流量都必须通过核心交换机。
我只从中心交换机收集流量数据。这意味着我对完全留在机柜交换机上的任何流量都视而不见,但我捕获了所有客户端广播流量以及任何发送到服务器或离开网络的流量。即使客户端使用连接到本地交换机的打印机,打印作业也会穿越连接到核心交换机的打印服务器。一个单独的流量导出点足以提供对整个网络的充分可见性。
如果你的以太网核心只有一个或两个小交换机,并且没有任何交换机可以导出流量信息,如果你中的一个交换机有一个“嗅探器”或“监控”端口,你仍然可以实施基于流量的网络管理。其中一个交换机实际上是网络核心。如果你还没有指定一个特定的交换机作为核心,请使用服务服务器数量最多的交换机。将软件流量传感器连接到监控端口(参见配置软件流量传感器,在配置软件流量传感器中)。
来自远程设施
将类似的推理应用于远程设施。每个远程设施至少有一个路由器连接到全球网络。它可能连接到 MPLS 云或互联网,但它仍然是连接到外部世界的一个链接。捕获该设备的流量。
如果远程设施有一个具有导出功能的中心交换机,也可以使用它。如果该地点报告了许多问题,中心交换机无法导出流量,考虑实施软件传感器或升级中心交换机。
让远程站点将它们的流量导出到你的中心收集器。维护多个收集器会增加你的工作量,但收益却微乎其微。
来自私有网络段/DMZ
跟踪核心网络和互联网边界的流量,可以深入了解整个网络,包括 DMZ 等隔离或私有网络段上的服务器。你可以看到 DMZ 服务器与核心网络和互联网之间的流量。但你无法看到 DMZ 服务器之间的流量。
如果你只有一个或两个服务器在 DMZ 中,你可能不需要在该网络段上配置流量导出。如果你有多个服务器,你将需要流量导出。然而,你不必立即做出决定。首先微调你的核心和边界网络上的流量管理安装,然后在你 DMZ 上实施流量导出。
实施收集器
理论已经足够,计划也已经足够。让我们安装一些东西吧!
网络搜索可以找到许多免费可用的流量收集器。其中最大的三个是 cflowd、flowd 和 flow-tools。Cflowd 已经过时,不受支持,且在 64 位系统上无法编译。我对 flowd 抱有很高的期望,但这是一个相对较新的工具,用户或第三方软件的支持还不够广泛。这就留下了 flow-tools,这是最常用的流量管理工具包。
Flow-tools 较旧,但拥有一个非常广泛的用户群体。原始作者(Mark Fullmer)于 2005 年发布了版本 0.68,并继续进行其他项目。任何未维护的软件都会逐渐过时,但一群用户在 2007 年承担了 flow-tools 的责任。这些用户收集改进和错误修复,并在需要时发布更新版本。尽管您仍然会偶尔发现错误,就像任何软件一样,flow-tools 拥有广泛的用户基础。
注意
不要使用 flow-tools 的 0.68 版本。它存在许多小问题,并且在 64 位系统上无法正确运行。(它似乎在 64 位系统上运行,但实际上会损坏数据,这甚至比完全无法运行还要糟糕!)花时间安装较新版本,即写作时的 0.68.5。
安装 Flow-tools
您可以从操作系统软件包或从源代码安装 flow-tools。在安装之前,访问 flow-tools 网站 code.google.com/p/flow-tools/ 下载最新版本。
从软件包安装
大多数类 Unix 操作系统提供免费软件的预包装版本。如果您可以使用预编译的预包装软件,请这样做。
然而,许多操作系统只包含 flow-tools 版本 0.68,而不是包含错误修复的新版本。一些操作系统,如 FreeBSD,将较新的软件作为名为 flow-tools-ng 的软件包提供。
flow-tools 软件包名称中的详细细节很重要。例如,flow-tools 最近是版本 0.68.4。对 CentOS flow-tools RPM 的搜索揭示了版本 0.68-4,这实际上是 flow-tools 软件包 0.68 的第 4 次修订。乍一看,这可能看起来像是正确的软件包,但实际上并不是。
当这本书印刷时,理想情况下,主要操作系统供应商将提供更新后的软件包。如果没有,您需要从源代码安装。
从源代码安装
要从源代码安装 flow-tools 的最新版本,请从 code.google.com/p/flow-tools/ 下载源代码,并提取它。您需要 GNU make 和 GCC,以及您操作系统的库和头文件。
# `tar -xf flow-tools-0.68.4.tar.bz2`
现在进入 flow-tools 目录,阅读 INSTALL 文件以获取当前的编译说明。该过程可能包括 configure、make 和 make install 等步骤。
在安装之前,运行 ./configure —help 以列出构建和安装选项。我在安装时发现最有用的选项是 prefix,它允许您指定您希望软件安装的位置。
大多数类 Unix 操作系统在 /usr/local/bin、/usr/local/sbin 等位置安装预包装软件。然而,当你从源代码构建像 flow-tools 这样的软件包时,你的安装并没有与系统的包管理系统集成。我建议将其安装在系统其他部分不使用的位置,因为你不希望操作系统更新覆盖 flow-tools 的一部分,或者更糟糕的是,将其回滚到操作系统附带的老旧版本!(别忘了更新你的 PATH 和 MANPATH 环境变量以包括你的新目录。)
在以下示例中,你将在 /usr/local/flow 下安装 flow-tools。我将在整本书的示例中使用这个目录。
# `./configure --prefix=/usr/local/flow`
# `make`
# `make install`
如果你的系统缺少任何先决条件,安装过程将在第一个命令后产生错误。安装成功后,你将在 /usr/local/flow/bin 下找到命令,在 /usr/local/flow/share/man 下找到手册页等等。
不要清理
在从源代码构建 flow-tools 后,不要运行 make clean。我发现我偶尔需要回到源代码中进行故障排除。
运行 flow-capture
flow-capture 程序监听指定的 UDP 端口以接收流量导出。然后它捕获数据并将流量记录写入磁盘。flow-capture 必须知道在哪里写入文件,多久启动一个新文件,以及从哪里接受流量信息等等。flow-capture 的手册页提供了许多选项,但以下示例对于许多情况就足够了:
# `flow-capture -p /var/run/flow-capture.pid -n 287`
`-w /var/db/flows -S 5 192.0.2.1/192.0.2.10/5678`
-p 参数告诉 flow-capture 将其进程 ID (PID) 文件存储在哪里。对于大多数类 Unix 操作系统,/var/run/flow-capture.pid 是一个常见的默认位置。
-n 选项告诉 flow-capture 在 24 小时内应该旋转其日志文件多少次。287 告诉 flow-capture 每五分钟创建一个新的日志文件。(你们中敏锐的人会注意到一天包含 288 个五分钟周期。Flow-capture 在一天内创建一个文件,然后旋转到新文件 287 次,因此一天总共创建 288 个日志文件。)你将使用的许多附加报告程序都期望以五分钟为增量来处理日志文件。
使用 -w 选项告诉 flow-capture 将其文件写入何处。/var/db/flows 是一个常见的选项,尽管有些人更喜欢 /var/log/flows。无论如何,每个收集器都需要自己的目录,因此你可能想使用类似 /var/db/flows/internet 或 /var/log/internet_flows 的东西。
-S 5 选项告诉 flow-capture 将消息记录到 syslog,说明它处理了多少流量,接收了多少数据包,以及它认为丢弃了多少流量。参数(5)是日志消息之间的分钟数。
注意
flow-capture 使用 syslog 设施 LOCAL6。 (查看一个 syslog 教程以了解如何管理 syslog 消息。)你不能不深入研究 flow-capture 源代码来更改此设施。
最后一个命令行参数(192.0.2.10/192.0.2.1/5678)指定了flow-capture的网络配置。第一个地址是flow-capture在本地机器上监听的 IP 地址。如您在上面的列表中看到的,我们的示例收集器在 IP 地址 192.0.2.10 上运行。如果您在这个位置放置 0,收集器将接受机器上所有 IP 地址的流量。即使您的收集器只有一个 IP 地址,我也建议明确地将该地址分配给您的收集器。您可能在以后添加更多 IP 地址到您的收集器,而且您可能不希望flow-capture也附加到这些地址。
第二个 IP 地址,192.0.2.1,是允许向此收集器发送数据的传感器的地址。如果您在这里放置 0(或删除它)而不是 IP 地址,flow-capture将接受来自任何地址的流量数据。这样做会增加入侵者向您的收集器发送虚假数据的风险,但同时也允许您同时接受来自多个来源的流量。(然而,几乎所有类 Unix 操作系统都有数据包过滤功能,可以让你保护这个端口,除了你指定的传感器之外。)
最后,5678是flow-capture监听的 UDP 端口。因为没有任何权威机构正式分配 UDP 端口用于 Cisco NetFlow,您应该使用任何未被其他服务保留的高编号端口。端口 6434 分配给了 sFlow,端口 4739-4740 分配给了 IPFIX,所以您可能想使用这些端口之一。此外,许多 Cisco NetFlow 产品使用端口 2055,这是为 Cisco 分配给一个从未公开发布的产品。
尝试使用适合您系统的选项在您的系统上启动flow-capture。确认它持续运行几分钟。这验证了您在构建或安装软件时没有犯任何基本错误,并且您的命令行基本上是正确的。
在启动时启动 flow-capture
您的操作系统必须在启动时启动flow-capture,就像它启动任何其他关键服务一样。这样做的方法因操作系统而异。如果您从操作系统供应商提供的软件包中安装了 flow-tools,它几乎肯定包含一个启动脚本。例如,Red Hat Linux RPM 在/etc/init.d中安装了一个启动脚本。FreeBSD 软件包包括一个配置在/etc/rc.local中的启动脚本。您需要告诉脚本在哪里存储捕获的流量文件,多久轮换一次,以及接受哪些主机的流量数据——实际上,就是您在上一个部分中设置的flow-capture命令中的所有设置。
注意
如果您选择的操作系统包中不包含启动脚本,请将您的 flow-capture 命令适当地添加到计算机的启动系统中。请检查您的操作系统文档。有时这只需将命令复制到 /etc/rc.local 即可。flow-capture 应该只在网络和本地存储启动后才开始运行。
重新启动您的系统以验证 flow-capture 是否在启动时启动。
收集器的数量?
现在您已经运行了一个 flow-capture 实例,是时候决定如何处理传入的数据了。您可以选择让所有传感器将数据发送到单个收集器,或者让每个传感器将数据发送到其自己的收集器实例。
将所有传感器记录发送到一个收集器是简单的。配置一个且仅有一个收集器,不要限制可以发送到它的地址。配置所有您的传感器使用该单个收集器。收集器将所有传感器的流量记录混合到一个共同的日志文件中。但是,您如何区分来自网络不同部分的流量?您可以通过传感器 IP 地址来区分流量,但这会增加分析的步骤。
如果没有其他强有力的理由,我建议为每个流量传感器运行一个单独的收集器,以帮助您保持数据分离。所有 flow-capture 实例都可以运行在同一台服务器上并使用相同的 IP 地址,您可以为每个 flow-capture 进程分配其自己的 UDP 端口和数据目录,这样您就可以分别分析每个网络段的数据。合并分离的数据比分离合并的数据要容易得多。
收集器日志文件
您的收集器在传感器开始发送数据之前不会记录任何内容。然而,一旦数据达到收集器,收集器就会创建以下格式的日志文件:
| tmp-v05.2009-11-15.134501-0500 |
|---|
文件名中的前缀 tmp 表示这是一个临时文件。flow-capture 仍在向该文件写入。接下来是创建流量文件的年、月、日,然后是 24 小时格式的时间戳。给出的是流量文件创建的时间,而不是日志文件完成和关闭的时间。这个示例流量文件是在 2009 年 11 月 15 日 (2009-11-15),13:45:01 或下午 1:45:01 (134501) 创建的。最后的数字 (−0500) 是相对于 UTC 的时间区域偏移。我的收集器在东部标准时间运行,比 UTC 东边五个小时。如果您的收集器位于 UTC 西边的时间区域,时间区域偏移将前面有一个 +。如果您有多个收集器位于多个时区,我建议它们都使用相同的时间区域,例如 UTC。
当需要创建新文件时,flow-capture 将当前临时文件重命名为以 ft- 开头,并创建一个新的临时文件。名称的其他部分保持不变,这使得您可以轻松地根据创建时间识别和排序流量文件。
收集器故障排除
如果您配置传感器将数据发送到您的收集器,但 flow-capture 在几分钟内没有生成任何日志文件,请开始故障排除。要么传感器没有传输数据,要么 flow-capture 没有将数据写入磁盘,或者传感器和收集器之间的防火墙阻止了该端口。
要开始故障排除,首先使用 tcpdump 验证传感器数据是否到达您的收集器,以便将网络问题与本地软件问题分开。
# `tcpdump -p -n -i em0 udp and port 5678`
-p 告诉 tcpdump 不要将接口置于混杂模式。这意味着系统将仅嗅探到达本地接口的流量。(适当的交换机配置应防止混杂模式嗅探,但使用 -p 意味着机器甚至不会尝试。)-i 参数给出了您想要监听的接口名称,在这种情况下是 em0,这恰好是我系统上的一个网卡。(大多数 Linux 发行版的主网络接口为 eth0。)最后,指定您的收集器运行的端口,在这种情况下是 5678。
此命令应打印出指定端口到达您的收集主机上的每个数据包的信息。如果您没有看到任何数据到达收集主机,请检查您的传感器配置以及传感器和收集主机之间任何防火墙的配置,然后使用您的数据包嗅探器逐渐接近传感器,直到找到数据停止的地方。如果您到达传感器并发现它没有将任何流量导出放在线路上,您的传感器配置可能存在问题。如果需要,请联系您的供应商以获得帮助。
如果系统正在接收流量数据,但 flow-capture 没有写入任何日志文件,请检查您的 flow-capture 配置,以确保您指定了正确的 UDP 端口和目录。验证运行 flow-capture 的用户是否有权向该目录写入文件。此外,检查系统日志,如 /var/log/messages,以查找错误信息。(记住,flow-capture 使用 LOCAL6。请确保配置 syslog 将 LOCAL6 消息记录到文件中。)
配置硬件流量传感器
在大多数情况下,配置硬件流量传感器是您最简单和最佳的选择。许多网络硬件制造商,如 Cisco,在其产品中包含流量导出。Cisco 路由器自 1990 年代以来就支持 NetFlow。一些较大的 Cisco 交换机也支持 NetFlow,但为了获得最佳效果,您必须将交换机的配置与路由器不同。Juniper 路由器也支持流量导出,因此我将介绍如何配置它们。一些较小的路由器供应商也支持流量导出,但您需要检查供应商的文档以获取配置说明。
书中的示例将假设流量收集器正在主机 10.10.10.10 上运行 UDP 端口 5678。请根据您的环境替换这些值。
Cisco 路由器
通过接口接口配置 Cisco 路由器上的 NetFlow。您可能只需要在上游接口(s)上启用 NetFlow,而不是在本地以太网接口上。 (如果您有一个复杂的以太网基础设施,例如 HSRP 或 VRRP 集群,您可能还希望监控以太网接口上的流量。)在以下示例中,您在接口 Serial0/0 上激活 NetFlow:
Router# `conf t`
Router(config)# `int s0/0`
Router(config-if)# `ip route-cache flow`
Router(config-if)# `exit`
在所有上游路由器接口上重复此配置,然后告诉路由器将流量数据发送到何处。
Router(config)# `ip flow-export version 5`
Router(config)# `ip flow-export destination 10.10.10.10 5678`
现在保存您的作品。您应该会发现数据几乎立即发送到您的收集器。
要查看您路由器上跟踪的信息流,请使用 IOS 命令show ip cache flow。
一些 Cisco 型号使用略有不同的语法。如果您遇到麻烦,请在 Cisco 的网站或互联网上搜索建议。
Cisco 交换机
在 Cisco 交换机上,NetFlow 是一个相对较新的发展,并且仅限于高端型号。通常,只有模块化交换机,如 4000、6000 及其后继产品支持 NetFlow 导出。许多交换机还需要一个附加的 NetFlow 卡,您可能或可能没有。堆叠式交换机不需要,较小的独立式管理交换机也不需要。为整个交换机启用或禁用 NetFlow,而不是基于每个接口。
NetFlow 支持因型号和安装的 IOS 版本而异。这里提供一个示例配置,但请不要盲目将其安装在您的交换机上!Cisco 交换机可以通过许多不同的方式执行许多不同的任务,而在我的环境中有效的方法可能不适合您。
在您的路由器上配置 NetFlow 之前,询问 Cisco 如何捕获您环境中该型号交换机的所有流量数据。您的配置可能看起来类似于以下示例。
注意
如果您决定只想尝试一下并看看会发生什么,请先备份您的配置,并在没有用户在网络上时尝试它。
Switch# `conf t`
Switch(config)# `ip route-cache flow`
Switch(config)# `ip flow ingress`
Switch(config)# `ip flow ingress layer2-switched`
Switch(config)# `ip flow-export version 7`
Switch(config)# `ip flow-export destination 10.10.10.10 5678`
第二行的配置语句(ip route-cache flow)告诉交换机激活流量,下一行(ip flow ingress)告诉交换机根据它们进入交换机的路由来跟踪流量。
默认情况下,这些具有路由功能的交换机仅导出它们路由的流量信息,而不是交换以太网流量。然而,由于您还想捕获关于本地以太网流量的信息,您告诉交换机使用ip flow ingress layer2-switched同时捕获第 2 层流量。
Cisco 交换机使用 NetFlow 版本 7,所以您不妨使用它。使用ip flow-export version 7来开启它。最后,您告诉交换机将流量数据发送到10.10.10.10,端口5678。
完成您的配置后,保存您的作品。数据应该几乎立即到达您的收集器。与 Cisco 路由器一样,使用命令show ip cache flow来查看当前的流量统计信息。
Juniper 路由器
Juniper 的配置比 Cisco 的配置长得多,但配置并不困难。首先,告诉 Juniper 如何采样流量流量,以及您希望将流量发送到何处。
forwarding-options {
sampling {
input {
family inet {
❶ rate 1;
run-length 9;
}
}
output {
❷ cflowd 10.10.10.10 {
❸ port 5678
❹ source-address 172.16.16.16;
version 5;
no-local-dump;
}
}
}
}
尽管有很多括号,但这个配置并不难理解。您从❶开始,定义您想要如何大量采样流量。在这个例子中,我将采样率设置为 1。Juniper 从每 1 个或所有流量中采样 1 个流量。如果您将采样率设置为 100,Juniper 将每 100 个数据包中采样 1 个。这个例子暴露了我的个人偏见;如果可能,我会记录所有流量。如果完整的流量记录使您的路由器过载,请增加采样级别,直到硬件可以支持为止。那些拥有 10GB 网络的您几乎肯定必须采样!确定您网络上的最低可持续采样率唯一的方法是通过实验。过度采样会导致路由器过载并造成数据包丢失。
如您所记得,cflowd 是一个过时的流量收集器。Juniper 硬件使用该名称来指定路由器将发送流量的位置。在❷处,您告诉 Juniper 在哪里找到您的流量收集器,收集器运行的 UDP 端口(❸),以及从路由器(❹)发送数据包的地址。
现在启用您想要捕获流量数据的接口的采样。
...
family inet {
sampling {
input;
output;
}
...
此配置将此接口的入站和出站流量发送到流量导出(或采样)引擎。
配置软件流量传感器
假设您需要在网络上进行流量导出,但没有支持流量导出的交换机。不必担心,您可以在不购买新硬件的情况下,通过软件实现流量传感器。
使用软件而不是硬件进行流量感知有局限性。首先,软件需要在服务器上运行,因此它会给您的网络增加另一个设备。此外,您只能从管理型以太网交换机捕获数据。软件可能无法捕获所有流量,并且可能不会告诉您它错过了什么。而且流量传感器软件是网络管理员必须配置、修补和维护的另一件事。您的工作还不够多吗?然而,对于小型网络来说,软件是唯一现实的选择。
设置传感器服务器硬件
流量传感器软件需要的系统资源非常少。您可以使用管理员因运行速度过慢而停用的台式机。我曾在 Soekris(www.soekris.com/)等小型计算机上运行有效的流量传感器。即使是拥有 266MHz CPU 和 128MB RAM 的普通机器,在捕获低流量局域网的流量时也大部分处于空闲状态。
无论你选择什么硬件,你的流量传感器机器至少需要两个网络接口。一个接口必须能够处理每秒许多个数据包。如果你正在回收一个带有主板集成网络卡的废弃台式机,假设内置网络卡的质量不足以满足需求。非常少的台式机主板厂商使用高端网络芯片组,他们更愿意使用价格低廉的芯片组,这些芯片组对于大多数用户来说刚刚足够。如果你不确定要购买什么网络卡,英特尔的网络卡通常足以用于流量传感器。服务器级系统上的嵌入式网络卡通常足够用;它们不是很好,但足够了。
最后,如果你为流量传感器硬件回收一台旧机器,请获取一个新的硬盘。流量传感器使用的硬盘空间非常少,但硬盘是随着时间推移最有可能出现故障的系统组件。你不想安装流量传感器,结果在几周后看到你的工作因为硬盘损坏而消失!(资深系统管理员可以考虑使用 FreeSBIE 等工具包制作一个可启动的流量传感器 CD,这样你可以轻松地大量生产可替换的传感器。)
最后,我建议在你的流量传感器服务器和收集器上使用相同的操作系统。这当然不是必需的,但仅仅因为可以就在生产环境中运行多个操作系统,这可能是手头时间过多的一个迹象。
网络设置
使用软件流量传感器需要你有具备端口镜像或端口监控功能的交换机。这通常被称为嗅探端口。交换机将所有通过交换机的流量复制到监控接口。在继续之前,你可能需要使用数据包嗅探器来验证这一点。
要在思科系统上配置监控端口,定义你想要监控的接口以及你想要将流量重定向到的接口。在以下示例中,一个思科交换机正在将所有来自 VLAN 1 的流量复制到接口 Gi0/4。许多交换机厂商也提供基于 Web 的配置工具。
router# `conf t`
❶ router(config)# `monitor session 1 source vlan 1`
❷ router(config)# `monitor session 1 destination interface` `Gi0/4`
你从❶开始,定义一个监控会话并告诉交换机要监控哪个 VLAN 或端口。然后,在❷中,你告诉交换机将监控的流量复制到何处。这个小交换机现在将复制所有通过主 VLAN 的流量到监控端口。
一个能够导出流量的交换机应该足够大,以便你可以将其连接到所有主要服务器,这样所有关键流量都会通过这个大交换机,并且你的流量导出几乎可以捕获所有重要的信息。如果你使用几个较小的交换机而不是一个大交换机,请确保监控端口能够捕获所有关键服务器的流量。
注意
记住,任何留在机柜交换机上的流量都不会被捕获。你可以在每个交换机上部署流量传感器,但这很快就会变得繁琐。
传感器服务器设置
交换机不会在监控端口上接受常规流量,因此传感器机器不能使用监控端口进行网络流量。 (试试看。)嗅探器端口仅用于监视网络,而不是参与网络。您的传感器盒需要一个第二块网络卡进行常规网络活动。
在 Linux 和 BSD 系统上,您必须激活嗅探器接口,它才能检测流量。还明智地禁用接口上的 ARP(使用up和-arp命令),这样您的嗅探器接口甚至不会尝试参与网络。在这里,您启动接口 em0 并禁用其上的 ARP:
# `ifconfig`
`em0`
`up -arp`
将您的嗅探器接口替换为 em0,然后使用tcpdump验证您是否在嗅探器接口上看到网络流量。
# `tcpdump -n -i em0`
您应该看到流量记录在屏幕上流过。按ctrl-C 停止输出。
在收集器上运行传感器
如果您的收集器运行在高端硬件上且不需要很多传感器,您可能考虑在收集器机器上运行传感器。向机器添加另一个网络接口,让传感器在该接口上运行,然后配置传感器将数据传输到本地主机 IP(127.0.0.1)上的 UDP 端口,并让收集器只接受来自 127.0.0.1 的连接。
然而,这台机器的安全敏感性加倍。收集器不仅记录了您网络上的流量历史,还可以查看所有当前网络活动。确保这台机器的安全!
传感器:softflowd
再次,网络搜索将揭示许多不同的软件流量传感器,但我推荐使用来自www.mindrot.org/softflowd.html的softflowd。前往该网站以识别当前版本;如果您能找到适用于您的操作系统的当前软件包,请使用它。如果找不到软件包,请下载源代码,并手动安装程序。
检查softflowd的 README 文件以获取构建说明。与 flow-tools 类似,softflowd也有一个configure脚本。我更喜欢将我的附加软件安装在主系统之外的不同目录中,这样我可以轻松地将其保持独立。在这里,我在/usr/local/softflowd下安装softflowd:
# `configure --prefix=/usr/local/softflowd`
# `gmake`
# `gmake install`
这将安装两个程序(softflowd和softflowctl),每个程序都有一个手册页和一个 README 文件。
运行 softflowd
要运行softflowd,您必须知道softflowd将监听的接口、收集器的主机名或 IP 地址以及收集器运行的端口。在这里,我让softflowd监听 em0 端口并将数据传输到 10.10.10.10 的 5678 端口:
# `softflowd -i` `em0` `-t maxlife=300 -n` `10.10.10.10:5678`
命令中间的-t maxlife=300设置流量超时为 300 秒,即五分钟。
softflowd 比硬件流量传感器更灵活,这意味着你更有可能误配置它。手册页列出了你可以调整 softflowd 性能的所有方法,但大多数方法在大多数环境中并不实用。不过,有一个选项可能有所帮助,那就是改变 soft-flowd 在任何给定时间跟踪的流量数量的上限。
默认情况下,softflowd 一次最多跟踪 8,192 个流量,使用大约 800KB 的内存。这是大量的并发连接,但如果你正在监控高带宽链路,你可能需要提高这个数值。(下一节将展示如何查看 softflowd 在任何给定时间实际跟踪的流量数量。)使用 -m 标志来指定跟踪流量的上限。
# `softflowd -i` `em0` `-t 5m -m 16384 -n` `10.10.10.10:5678`
此示例跟踪的是正常流量数量的两倍。
监视 softflowd
softflowctl 程序允许网络管理员管理正在运行的 softflowd 进程。你可以用它来启动和停止收集流量,查看当前跟踪的流量,并将所有正在跟踪的流量刷新到收集器。softflowctl 的手册页提供了关于 softflowctl 所有功能的说明,但我会只介绍在正常情况下使用的功能。
简单的 softflowctl 命令有 shutdown 和 exit。要告诉 softflowd 将其当前跟踪的所有流导出到收集器并自行关闭,请使用 shutdown 命令。这是终止 softflowd 的推荐方法。
# `softflowctl shutdown`
如果你想让 softflowd 在不向收集器发送任何额外流的情况下自行关闭,请使用 exit 命令。你将丢失 softflowd 收集但尚未导出的任何数据。
# `softflowctl exit`
softflowctl 更有趣的功能包括查看当前跟踪的流量和查看 softflowd 对跟踪流量的内部统计信息的能力。
查看跟踪的流量
如果你想查看 softflowd 当前正在跟踪的流量,请使用 softflowctl 的 dump-flows 命令。每一行代表一个单独的流量。如果你看到流量,说明 softflowd 正在工作。
# `softflowctl dump-flows`
softflowd[61946]: Dumping flow data:
ACTIVE seq:84 [❶ 192.0.2.253]:❷ 4234 <> [❸ 239.255.255.250]:❹
1900 proto:❺17 octets>:314 packets>:1 octets<:0
packets<:0 start:2011-12-07T15:03:18.541 finish:2011-12-07T15:03:18
.541 tcp>:00 tcp<:00 flowlabel>:00000000 flowlabel<:00000000
EXPIRY EVENT for flow 84 now
...
此流量涉及一个 IP 为 192.0.2.253(❶)和端口 4234(❷)的主机,连接的另一端是 IP 为 239.255.255.250(❸)的主机,端口为 1900(❹)。此流量使用协议 17(❺),或 UDP。尽管你可以看到时间信息,但你还有其他更方便查看这些数据的方法。
查看流量统计
softflowd 在启动时立即开始跟踪流量。你可以使用 softflowctl 的 statistics 命令查询 softflowd 当前跟踪的流量特征,如下所示:
# `softflowctl statistics`
我会将此命令的冗长输出分成几个部分,以便更容易理解。
❶ softflowd[61946]: Accumulated statistics:
❷ Number of active flows: 16
❸ Packets processed: 11898
❹ Fragments: 0
❺ Ignored packets: 46 (46 non-IP, 0 too short)
❻ Flows expired: 759 (0 forced)
❼ Flows exported: 784 in 67 packets (0 failures)
❽ Packets received by libpcap: 12156
❾ Packets dropped by libpcap: 0
❿ Packets dropped by interface: 0
第一行❶包含一个有趣的数字:你查询的 softflowd 进程的进程 ID。如果你在一台机器上运行多个 softflowd 实例,这将帮助你验证你查询的是正确的实例。
在❷处的活动流数量告诉你softflowd认为有多少流正在进行。这不同于你当前网络上的活动连接数量。记住,传感器跟踪流,除非有理由认为流已结束或超时到期。来自 DNS 或 UDP NFS 请求的流将保留在softflowd跟踪流的列表中,直到超时到期,这可能会在相应的网络活动停止很久之后。
处理的数据包数量(❸)应该始终增加,而片段的数量(❹)可能也会增加,但增长速度较慢。
丢弃的数据包数量(❺)更有趣。每个网络都倾向于时不时地有“奇怪的东西”飘过。流管理只处理 TCP/IP 及其相关协议,包括 IPv6、SCTP 和其他高级协议。当softflowd遇到不属于 TCP/IP 的数据包时,例如 DECNet,它会计数但不会对其进行其他处理。丢弃的数据包可能来自不良硬件、混乱的 TCP/IP 堆栈、不寻常的网络协议或任何其他奇怪的错误。你可以尝试使用netstat -s来了解系统哪个部分正在丢弃数据包,以及原因。softflowd也会丢弃太短而无法包含实际数据的数据包。
你可以在❻处看到softflowd已过期的流数量,以及在❼处它导出到收集器的数量。这些数字不一定相等,因为前者是softflowd的内部统计。导出的流数量应该与收集器接收到的数量相匹配。如果你看到softflowd强制一些流过期,请使用-m来增加softflowd可能跟踪的流数量。
Libpcap 是softflowd使用的数据包捕获软件。在❽处,libpcap 接收到的数据包数量应该大致相当于softflowd处理的数据包数量。在❾处,libpcap 丢弃的数据包数量应该非常低,以确保正确的数据捕获。如果这个数字在增加,请调查。你的操作系统或硬件可能无法满足所施加的负载。
也可能你的网卡无法完成捕捉网络中所有数据的任务。最后,在❿处,接口计数器丢弃的数据包应该为零,或者至少非常低。
输出继续显示有关已过期流的信息。
Expired flow statistics: minimum average maximum
Flow bytes: ❶ 221 ❹ 263570 7564472
Flow packets: ❷ 1 345 9446
Duration: ❸ 0.00s ❺ 22.73s 307.47s
最小的流(❶)有 221 字节。一个流中最少的数据包数量(❷)是 1。最短的流(❸)持续不到一百分之一秒。
你可以根据这些数据进行一些猜测。例如,221 字节的流量很可能是一个单独的数据包,而且可能也是最短的。尽管如此,你可能有很多包含单个数据包中少量字节的流量,而且 221 字节的流量可能被分割成多个小数据包。要得出关于特定流量的任何结论,你必须进行更详细的分析。类似地对待最大值;字节最多的流量不一定是包数最多的流量。
平均流量(❹)为 263,570 字节,大约 257KB,持续了大约 22 秒(❺)。同样,你不能假设平均大小的流量与平均包数或平均持续时间的流量相同。
统计数据以softflowd过期和导出每个流的原因计数以及每个协议的统计列表结束。
Expired flow reasons:
tcp = 10 tcp.rst = ❶ 1 tcp.fin = ❷ 1
udp = 126 icmp = ❸ 0 general = 0
❹ maxlife = 5
❺ over 2Gb = 0
❻ maxflows = 0
❼ flushed = 0
Per-protocol statistics: Octets Packets Avg Life Max Life
tcp (6): 32994923 36899 195.36s 330.44s
udp (17): 46014 135 0.00s 0.03s
TCP 和 UDP 有自己的条目,包括流量过期具体原因。例如,如❶所示,TCP 流量可以通过指示端口已关闭的 TCP RST 来过期,或者通过标记正常会话结束的 TCP FIN(❷)。同样,向已关闭端口的 UDP 请求可以生成如❸所示的 ICMP 响应,或者它可能只是超时。
softflowctl还显示由于超时(❹)而过期的流量数量以及由于超过单个流的最大大小而过期的流量数量(❺)。
softflowd程序跟踪同时跟踪的最大流量数。如果softflowd检测到的流量超过其跟踪能力,它将使较旧的空闲流量过期,直到它有足够的容量来跟踪活动流量。如果 maxflows 数量(❼)开始上升,增加softflowd在任何时候可以跟踪的流量数量。
最后,清除条目(❽)显示了当管理员运行softflowctl expire-all时有多少流量已过期。
统计部分以每个协议的流量信息结束。
现在你已经收集了一些数据,你将学习如何在第三章中查看它。
第三章。查看流

你有传感器正在传输数据,你的收集器正在将数据写入磁盘。现在怎么办?Flow-tools 提供了几个程序来查看流数据、生成统计分析以及生成报告。你将从显示流文件中的数据开始。
使用 flow-print
流文件包含紧密打包的二进制数据,使用 cat 或 more 查看流文件会打乱你的终端。要查看流数据,你应该使用 flow-print。
每个流文件都包含标识导出数据的宿主、捕获时间等信息。当你需要查看多个流文件时,你应该在将数据传递给 flow-print 之前删除这些标题,以免干扰你查看实际流数据。这就是 flow-cat 的作用。你将使用 flow-cat 来连接多个流文件,并将干净的数据呈现给 flow-print。虽然使用 flow-cat 是可选的,但我建议你始终与 flow-print 一起使用,除非你专门检查标题数据。
要检查流文件,使用 flow-cat 将数据传递给 flow-print,然后将结果传递给分页器,以便你可以查看所有结果,如 示例 3-1 所示。
示例 3-1. 样本 flow-print 输出
# `flow-cat ft-v05.2009-12-01.171500-0500 | flow-print | less`
srcIP dstIP prot srcPort dstPort octets packets
36.85.32.9 158.43.192.1 17 2325 53 59 1
158.43.192.1 36.85.32.9 17 53 2325 134 1
36.85.32.37 83.243.35.204 6 25 4115 1035 14
83.243.35.204 36.85.32.37 6 4115 25 1527 12
...
示例 3-1 中的每一行代表一个流。第一列 srcIP 显示流的源 IP 地址,第二列(dstIP)显示目标地址。
prot 列显示此流的协议号。协议 17 是 UDP,协议 6 是 TCP。(表 3-1 在 常见协议和端口号分配 中描述了网络上最常见的协议,你将在你的收集器服务器上的 /etc/protocols 文件中找到这些协议号的完整列表。)
srcPort 列显示 TCP 或 UDP 流的源端口,dstPort 显示目标端口。最后,octets 列显示流中的字节数,packets 显示流中的数据包数。
示例 3-1 中的第一个流量来自地址 36.85.32.9。这是我的网络上的一个地址,它将数据发送到 IP 158.43.192.1。据我所知,我对这个地址一无所知,也不知道为什么我会与它通信,但我确实知道协议 17 是 UDP,源端口是 2325,目标端口是 53。端口 53 是为 DNS 事务保留的 UDP 端口,所以我知道这个流量代表了一个 DNS 查询,而且我也知道从“八位字节”列中,一个数据包发送了 59 字节。
现在看看示例 3-1 中的第二个流量。注意,源和目标 IP 地址与我们的第一个流量相反:远程端从端口 53 发送数据到我的端口 2325,这与第一个流量相反。响应,一个数据包 134 字节,几乎肯定是对第一个流量中发送的查询的 DNS 响应,但为了绝对确定,我需要查看时间信息。
第三种流量来自示例 3-1 中的不同 IP,并且将数据发送到与前两种流量中的任何一个 IP 都不同的远程 IP。这种流量代表了一个与前面两种流量分开且不同的 TCP/IP 事务。这个事务运行在协议 6(或 TCP)上,源端口为 25,目标端口为 4115。这很奇怪。TCP 端口 25 用于 SMTP,或电子邮件。你可能会期望电子邮件连接是到端口 25,而不是从端口 25。为什么网络事务会有一个源端口为 25?记住,每个网络事务都包括两个流量:一个是从客户端到服务器,另一个是从服务器到客户端。这个“源端口 25”的流量是服务器与客户端的通信。
现在看看第四个也是最后一个流量。这个流量是第三个流量的反向,代表了那个 SMTP 事务的另一部分。源端口是 4115,目标端口是 25,如果有人试图向电子邮件服务器发送邮件,这是有意义的。
如这两行所示,flow-print 并不一定按照流量发生的顺序打印流量。例如,如果两个主机之间有非常快的连接性,流量记录可能会显示同时启动的连接流量和响应该连接请求的流量。在这种情况下,flow-print 会按照它们在流量文件中记录的顺序显示流量。(我们稍后会从流量文件中提取实际的时间数据。)
位、字节和八位字节
大多数网络管理系统以比特的某个倍数(千比特、兆比特等)提供有关流量的信息,所有这些都在十进制基数下。然而,一些流量分析系统,如 flow-tools,提供以 八进制 为单位的流量信息,而不是比特甚至字节,因为字节并不总是 8 比特。
大多数计算专业人士都知道字节是 8 比特。但 非常 严格地说,大多数计算机专业人士是错误的。字节是在特定硬件平台上内存寻址的最小单位。英特尔 8086 CPU 及其后续产品,今天最常见的机器,拥有 8 比特的字节,许多其他平台将其作为方便的标准。市面上可用的硬件的字节大小从 5 比特到 12 比特不等,实验性硬件的字节大小几乎可以是任何大小。
八进制总是 8 比特,与正常字节的大小相同。如果你有字节不是 8 比特的系统,单词 字节 是模糊的。一些软件,如 flow-tools,明确使用八进制进行区分,因为几乎所有网络管理员都只有 8 比特字节的硬件。(我们大多数人没有奇数硬件。)你只需在看到八进制时识别它们,并感激一些网络管理员遭受的烦恼是你永远不需要应对的。
打印协议和端口号名称
你可能记得端口号 53 是用于域名系统,端口号 25 是用于电子邮件的 SMTP 协议,但大多数人并没有记住每个端口号的用途。同样,你可能记得协议号 6 是 TCP,17 是 UDP,但你不必费心记住所有其他协议号。文件 /etc/protocols 和 /etc/services 列出了端口号及其相关名称。使用 -n 标志让 flow-print 使用这些名称显示端口和协议,如下所示:
# `flow-cat ft-v05.2011-12-01.171500-0500 | flow-print -n | less`
srcIP dstIP prot srcPort dstPort octets packets
36.85.32.9 158.43.192.1 udp 2325 domain 59 1
158.43.192.1 36.85.32.9 udp domain 2325 134 1
36.85.32.37 83.243.35.204 tcp smtp 4115 1035 14
83.243.35.204 36.85.32.37 tcp 4115 smtp 1527 12
...
这些结果与 示例 3-1 相同,只是在 prot 列中 tcp 替换了 6,udp 替换了 17。同样,srcPort 和 dstPort 列中的数字已被替换为服务名称,如 domain 和 smtp。虽然使用端口号的名称是合理的,但使用主机名而不是 IP 地址引入了对网络的依赖。此外,获取数百或数千个 IP 地址的主机名可能需要非常长的时间。
并非所有 flow-print 格式都支持以名称输出。在这些输出格式中,flow-print 会忽略 -n 标志。
常见协议和端口号分配
一旦你与流量信息工作了一段时间,你将开始自动识别端口号和协议号。表 3-1 列出了一些你将在互联网上常见到的协议。
表 3-1. 常见协议号
| 号码 | 协议 |
|---|---|
| 1 | 因特网控制消息协议 (ICMP) |
| 6 | 传输控制协议 (TCP) |
| 17 | 用户数据报协议 (UDP) |
| 47 | 通用路由封装 (GRE) |
| 50 | 封装安全载荷 (ESP) |
| 51 | 认证头部 (AH) |
类似地,表 3-2 列出了内部和公共网络上常用的一些 TCP 和 UDP 端口分配。(对于更完整的列表,请参阅您的收集器主机上的 /etc/services。)
表 3-2. 常用 TCP 和 UDP 端口分配
| 编号 | 服务 |
|---|---|
| 20 | 文件传输协议 (FTP) 数据通道 |
| 21 | 文件传输协议 (FTP) 控制通道 |
| 22 | 安全壳 (SSH) |
| 23 | Telnet |
| 25 | 电子邮件(SMTP) |
| 53 | 域名系统 (DNS) |
| 80 | 超文本传输协议 (HTTP,Web) |
| 137 | NetBIOS 命名服务(Windows 文件共享) |
| 138 | NetBIOS 数据报服务(Windows 文件共享) |
| 139 | NetBIOS 会话服务(Windows 文件共享) |
| 161 | 简单网络管理协议 (SNMP) |
| 389 | 轻量级目录访问协议 (LDAP) |
| 443 | 安全超文本传输协议 (HTTPS) |
| 445 | 基于 TCP 的 SMB(Windows 文件共享) |
当然,您会发现更多这样的端口正在使用中,如果您发现某个端口不在这个列表中或不在 /etc/services 中,进行网络搜索应该可以识别它。尽管有些端口会顽强地抵抗网络识别:主机上的某个程序正在使用该端口,您需要使用该主机的本地工具来识别该程序。
端口与服务的比较
总是记住,端口分配并不能作为特定协议在该端口运行的结论性证据。系统管理员可以在任何端口上运行任何程序。例如,您可以在端口 25(电子邮件)上运行 Web 服务器或在端口 443(HTTPS)上运行 FTP 服务器。我的一个服务器在端口 23、25、53、80、443 等上运行 SSH,这让我可以绕过大多数简单的数据包过滤防火墙。如果您发现可疑流量,例如非常长的基于 TCP 的 DNS 请求,请记住,用户是狡猾的小东西,他们会尝试各种方法来规避您的访问控制。
使用 -p 查看流记录头部信息
每个流文件都包含头部数据,记录收集器主机名、时间信息和压缩信息,以及其他捕获数据。-p 标志会在任何流之前打印流文件的头部信息,以便您更容易地识别传感器主机、流的开始和停止时间、流的运行时长、flow-capture 认为在传输中丢失的流数量等。这些流数据并不常用,但如果您认为它们可能有所帮助,您可以看到它们。
记住,flow-cat 会特别移除这些头部数据以避免混淆其他流工具,这意味着您一次只能有效地检查一个流文件的头部,并且不能使用 flow-cat。
# `flow-print -p < ft-v05.2011-12-01.171500-0500 | less`
打印到宽终端
许多flow-print报告包含大量信息,因此列与列之间的空白不多。-w标志告诉flow-print你有宽终端,因此它可以在列之间添加额外的空间,以便更容易阅读输出。然而,如果你有一个非常宽的终端,我建议你查看格式 5。
标志位与控制位
TCP 协议包括标志位,也称为控制位。flow-print提供了 TCP 流的标志位字段,但这个字段对其他协议来说没有意义。我将用控制位这个名字来保持一致性。
使用-f设置flow-print格式
由于默认的flow-print输出可能不会包含你感兴趣的所有信息(而且它当然不会包含流文件中包含的所有信息),flow-print支持多种输出格式。你可以使用-f标志来设置flow-print的格式。
每个格式都有一个数字。例如,格式 3 是flow-print最常用的默认格式。(如果你使用 NetFlow 版本 8,flow-print可能会选择不同的默认格式。)你可以使用这些格式选项以最适合你的方式展示流数据,如下面的示例所示。我将只介绍最有用的那些,但你可以在flow-print的 man 页面上了解其他格式。
使用格式-f 0显示接口和端口的十六进制表示
如果你想要查看流经过的路由器接口,请使用格式 0,如下所示:
# `flow-cat ft-v05.2011-12-01.171500-0500 | flow-print -f 0 | less`
Sif SrcIPaddress Dif DstIPaddress Pr SrcP DstP Pkts Octets
0000 36.85.32.9 0000 158.43.192.1 11 915 35 1 59
0000 158.43.192.1 0000 36.85.32.9 11 35 915 1 134
0000 36.85.32.37 0000 83.243.35.204 06 19 1013 14 1035
0000 83.243.35.204 0000 36.85.32.37 06 1013 19 12 1527
...
这部分输出看起来与默认输出几乎相同,但请注意增加了Sif和Dif列。这些代表源(Sif)和目的(Dif)接口。流记录包括有关数据包进入哪个接口以及流离开哪个接口的信息。你可以将这些与路由器接口匹配,正如你将在第四章(使用 SNMP 识别接口号)中看到的。(在使用 SNMP 识别接口号中)。
然而,软件流传感器不会记录接口信息,因为它们无法访问。基于软件的传感器监听交换机上的监控端口,但它们看不到接口信息。对它们来说,接口号始终是 0。
格式0通过压缩其他一些列将接口号添加到流输出中。例如,协议列现在是Pr。但看看这些数字。第一个流是协议 11(或根据/etc/protocols的“网络语音协议”),源端口是 915,目的端口是 35。你几乎肯定不会在你的网络上运行 NVP!这里发生了什么?
发生的事情是这个格式通过以十六进制形式打印端口和协议信息来为接口编号留出空间。例如,11 是 17 的十六进制,或 UDP;915 是 2325 的十六进制;35 是 53 的十六进制。结果,这四个流与前面示例中显示的流完全相同,只是以十六进制形式打印,并增加了接口列。
注意
如果你在查看 ICMP 流,以十六进制形式打印端口号是有用的。如果你在查看带有端口和接口的 TCP 或 UDP 流,而这些端口和接口不在老式的 80 列终端上,请使用 132 列格式。
使用 -f 1 选项,两行显示时间、标志和十六进制端口
有一种更好的方法可以在标准宽度的屏幕上显示流的所有信息:将每个流分成两行。使用格式 1 来查看接口信息和时间。
# `flow-cat ft-v05.2011-12-01.171500-0500 | flow-print -n -f 1 | less`
Sif SrcIPaddress DIf DstIPaddress Pr SrcP DstP Pkts Octets
StartTime EndTime Active B/Pk Ts Fl
0000 36.85.32.9 0000 158.43.192.1 11 915 35 1 59
❶ 1201.17:09:46.750 1201.17:09:46.869 0.119 59 00 00
0000 158.43.192.1 0000 36.85.32.9 11 35 915 1 134
1201.17:09:46.750 1201.17:09:46.869 0.119 134 00 00
0000 36.85.32.37 0000 83.243.35.204 06 19 1013 14 1035
1201.17:09:46.912 1201.17:09:51.890 4.978 ❷73 00 1b
0000 83.243.35.204 0000 36.85.32.37 06 1013 19 12 1527
1201.17:09:46.912 1201.17:09:51.890 4.978 ❸127 00 1b
...
这些流与前面所有示例中出现的流相同,但看起来非常不同。每个流都在两行中显示,用空白行分隔单个流。此外,每行的条目略有偏移。这种两行格式一开始可能会让人困惑,尤其是因为它没有实际的列:标题显示了信息在每个流的两个行条目中的位置。每个流的第 1 行显示了源接口、源 IP 地址、目的接口、目的 IP 地址、协议、源和目的端口、数据包数量以及流中的字节数。(你之前都见过这些。)花点时间看看这些在四个样本流中的显示方式,然后你可以查看每个流第二行的新条目。
StartTime 和 EndTime 空间给出了连接开始和结束的时间。在这里,❶处的 1201 代表日期,12 月 1 日。接下来的三个值以 24 小时制给出时间:17:09:46 是下午 5:09:46。最后的分数是流开始时的毫秒数,或 .750 秒。(如果你需要比这更高的精度,你可能是在试图解决错误的问题。)
Active 列给出了流活跃的秒数,这样你就不必从 EndTime 减去 StartTime(对于前两个流来说很容易,但随着流的增长会稍微困难一些)。
B/Pk 空间表示每包的平均字节数。第一个流在 1 个数据包中有 59 字节,所以计算很简单,但在更大的流中会更困难。第三个流在❷的平均每包 73 字节,而第四个流在❸的平均每包 127 字节。
Ts 空间表示服务类型(ToS),这几乎总是 00,因为大多数 TCP/IP 网络不需要尊重 ToS 标志。通常,数据包中的 ToS 表示你在一个实验性网络中,或者你正在使用复杂的如 VoIP 或 MPLS 等服务,或者有人在玩愚蠢的小把戏。^([4)]
Fl空间给出流的标志,即 TCP 控制位。非 TCP 流,如前两个,总是显示为零的标志。第三和第四个示例是 TCP 流,标志显示为1b。参见 TCP 控制位和流记录以了解如何将1b转换为有意义的值。
打印 BGP 信息
与多个上游 ISP 使用边界网关协议(BGP)的路由器传输包含自治系统编号(ASNs)的流记录。格式 4 打印这些信息而不是端口号。否则,这个格式包括你在其他格式中看到的通常的源和目的地址、协议、字节数和包信息。
这些是示例 3-1 中使用的相同四个流,以格式 4 显示:
# `flow-cat ft-v05.2011-12-01.171500-0500 | flow-print -n -f 4 | less`
srcIP dstIP prot srcAS dstAS octets packets
36.85.32.9/0 158.43.192.1/0 udp 0 701 59 1
158.43.192.1/0 36.85.32.9/0 udp 701 0 134 1
36.85.32.37/0 83.243.35.204/0 tcp 0 4713 1035 14
83.243.35.204/0 36.85.32.37/0 tcp 4713 0 1527 12
...
注意在先前的列表中,每个流的源(srcAS)或目的 AS(dstAS)都是 0。这些流是本地生成的。流传感器不跟踪你的本地 AS。
如果你没有使用 BGP,这个格式对你来说无关紧要。
宽屏显示
如果你有一个足够宽的显示器,在 80 列工作是一种烦恼。为什么不只有一个非常宽的格式,可以在一行中显示最有用的信息呢?既然我们在这里,让我们去掉十六进制,并以十进制打印一切。这就是格式 5 的目的,这是我在检查网络问题时最频繁使用的格式。
就像一部夏季特效大片,这个格式在宽屏显示器上工作得很好,但在打印页面上则不太理想。但与其提供实际打印的样本,该样本会跨越书的两个对页或必须横向打印,不如让我们直接浏览这个格式显示的字段。
# `flow-cat ft-v05.2011-12-01.171500-0500 | flow-print -f 5 | less`
格式 5 生成Start、End、Sif、SrcIPaddress、SrcP、DstIPaddress、DstP、P、Fl、Pkts和Octets列。
Start和End以毫秒分辨率给出流的开始和结束时间,就像格式 1 一样。
然后是Sif(源接口)、SrcIPaddress(源 IP 地址)和SrcP(源端口),然后是DIf(目的接口)、DstIPAddress(目的 IP 地址)和DstP(目的端口)。在理解了前面的报告后,你应该没有阅读这些的困难。
P是协议号。
Fl给出以十进制打印的 TCP 控制位。
最后,Pkts给出流中的数据包数量,而Octets给出字节数。
TIMES VS. TIMES
流记录文件以它们在服务器上收集的时间命名。打印流时显示的时间是流传感器的时钟。如果你的收集器时钟和你的传感器时钟不匹配,你的流记录中显示的时间将不会与记录收集的时间相匹配。请同步你的时钟!
IP 计费格式
也许你有软件可以解释 Cisco IP 会计输出,或者你已经看了很长时间的输出,以至于可以不耗费宝贵的脑力来处理它。这里显示的格式 6 专门是为了让你高兴:
# `flow-cat ft-v05.2011-12-01.171500-0500 | flow-print -f 6 | less`
Source Destination Packets Bytes
36.85.32.9 158.43.192.1 1 59
158.43.192.1 36.85.32.9 1 134
36.85.32.37 83.243.35.204 14 1035
83.243.35.204 36.85.32.37 12 1527
...
例如,这里是以 Cisco 格式显示的四个示例流量。如果你按字节数排序这个输出,你应该能够轻松地识别交换最多流量的主机。
# `flow-cat ft-v05.2011-12-01.171500-0500 | flow-print -f 6 | sort -rnk 4 | less`
36.85.32.36 64.18.6.14 ❶ 12820 ❷ 19216320
36.85.32.36 64.18.6.13 12820 19216320
207.46.209.247 36.85.32.4 10977 16458558
84.96.92.121 36.85.32.37 6904 9671951
...
通过按发送的字节数对流量进行排序,你已经将流量从大到小进行了排名。是什么填满了你的电路?这里有一个快速的答案:第一行显示主机 36.85.32.36 向 64.18.6.14(❶)发送了 12,820 个包含(❷)19,216,320 字节的包。同一个主机 36.85.32.36 向 64.18.6.13 发送了相同数量的流量。进一步的过滤和报告可以识别这些最繁忙的主机之间的流量类型,正如你将在下一章中看到的。
现在你已经可以以任何你想要的方式查看流量,让我们更仔细地看看 TCP 和 ICMP 连接的一些复杂性。
警告:前方是十六进制数学!
网络是二进制的,其中很多都是以 16 进制为基础的。要理解 TCP 控制位和 ICMP 代码和类型,你需要使用基本的十六进制数学。记住,前缀 0x 表示一个数是十六进制的。
^([4]) 尽管服务类型/服务质量是值得探讨的话题,尽管 flow-tools 支持 ToS/QoS,但这些话题只被少数网络所需要。包括对这些话题的适当讨论会使这本书变得很长。一旦你了解了如何根据端口和地址搜索和报告流量,你将不会在处理基于 ToS 或 QoS 的流量时遇到任何麻烦。
TCP 控制位和流记录
每个 TCP 包都包含一个或多个控制位,这些是开/关开关,告诉连接参与者如何处理特定的包。流记录捕获每个 TCP 流使用的控制位。当连接正常工作时,这些控制位并不特别有用,但在识别问题时却非常有价值。如果你不熟悉 TCP 控制位,请阅读一本好的 TCP/IP 入门书籍,如 Charles A. Kozierok 的《TCP/IP 指南》(No Starch Press,2005)。
控制位之所以被称为控制位,是因为 TCP 为它们预留了六个位。这些位如下:
-
同步(SYN)位表示一个连接同步请求。它允许发送方和接收方同步 TCP 序列号,在每个端点分配一致的端口等。这个位在流中的第一个包上总是被设置。
-
确认(ACK)位表示一个包包含对特定先前包的接收确认。
-
推送(PSH)位在发送数据的端点希望客户端的网络堆栈立即将此数据推送到协议堆栈时被设置。这个位请求客户端清空所有硬件和内核缓冲区,并将所有数据交给客户端。
-
URG(紧急)位表示紧急指针字段包含需要解释的数据。用日常语言来说,这意味着这个数据包包含了接收方正确处理流中其他数据包所需的粘合剂。
-
RST(重置)立即终止连接。
-
最后,FIN(结束)位宣布该主机将不再发送数据,但它将继续监听来自另一端的数据。FIN 信号表示是时候断开连接了。
每个控制位都表示为一个十六进制数,如表 3-3 所示。
表 3-3. TCP 控制位十六进制值
| 标志 | 十六进制 |
|---|---|
| FIN | 0x01 |
| SYN | 0x02 |
| RST | 0x04 |
| PSH | 0x08 |
| ACK | 0x10 |
| URG | 0x20 |
许多人发现用图表表示更容易理解,例如图 3-1。

图 3-1. TCP 控制位
数据包中控制位的任何组合都可以表示为一个唯一的数字。如果设置了控制位,将该标志的数字加到数据包的总控制位数字上。如果你说一个数据包的控制位设置为 18,这表示一组精确的控制位。只有一种可能的控制位组合的总和为 18。(试试看,我会等着。)
例如,图 3-2 展示了如何表示一个典型的 SYN/ACK 数据包。

图 3-2. SYN/ACK 数据包中的 TCP 控制位
如图 3-2 所示,这个数据包的控制位 SYN(0x2)和 ACK(0x10)被标记,而所有其他控制位都没有被标记。现在把 0x2 和 0x10 加起来。十六进制 10 加十六进制 2 等于十六进制 12;我的计算器告诉我十六进制 12 是十进制 18。
要得到控制位值为 18 的数据包,只有当选择了 SYN 和 ACK,并且只有这两个控制位时才可能。
流不会跟踪单个数据包,那么流记录如何合理地跟踪 TCP 控制位呢?流传感器跟踪单个流中出现的所有控制位。例如,当一个主机在连接期间发送 SYN 和 ACK 时,你合理地期望看到,比如说,PSH 和 FIN。当这些标志中的任何一个出现在流中时,流传感器会记录它们的出现。图 3-3 展示了这在位图中会是什么样子。

图 3-3. 流中的 TCP 控制位(包含 SYN、ACK、PSH 和 FIN)
因此,我们有 0x1 + 0x2 + 0x8 + 0x10 = 0x1b,或者十进制 27。
回想一下本章早些时候对 TCP 标志的第一种视图(在使用-f 1 显示时间、标志和十六进制端口的两个行中,见使用-f 1 显示时间、标志和十六进制端口的两个行)。第三个和第四个样本流的Flags字段等于1b,这告诉你这个流包含了正常连接所需的全部 TCP 标志(SYN、ACK 和 FIN)。它还告诉你这个流包含了一个在正常连接中完全可接受的标志(PSH),并且没有包含表示问题的标志(RST)。这个连接几乎肯定成功了。在第四章中,你将搜索具有指示问题的控制位组合的流(见 TCP 控制位原语,见 TCP 控制位原语)。
将十六进制转换为十进制和二进制
Windows 中的计算器程序可以在三种进制之间进行转换。打开计算器,选择视图 ▸ 科学。你会看到十六进制(Hex)、十进制(Dec)、八进制(Oct)和二进制(Bin)的按钮。选择你想要转换的进制。输入该进制下的数字。选择你想要转换到的进制,计算器会为你转换。如果你不经常进行十六进制数学运算,你也可以使用计算器来学习。大多数类 Unix 桌面环境也包含十六进制/十进制计算器。
ICMP 类型和代码以及流记录
流记录还记录 ICMP 类型和代码,将它们显示为目标端口号。我将首先回顾 ICMP 类型和代码,然后讨论流记录如何表示它们。
ICMP 中的类型和代码
许多人将不同的 ICMP 请求心理上归入一个大篮子,并依靠诸如“ICMP 是 ping”这样的概括来应对。虽然这可能对普通用户来说足够了,但你不是普通用户,你需要对 ICMP 有更深入的理解才能管理网络。
ICMP 的类型是一类通用的 ICMP 请求,例如 ping 请求和 ping 回复。其他 ICMP 类型包括诸如“主机不可达”、“路由通告”、“traceroute 请求”、“路由重定向”等消息。一些 ICMP 类型会从接收方那里得到响应,而其他类型则无注释地接收。
一些 ICMP 类型还包括一个 ICMP 代码,允许 ICMP 消息提供更具体的响应。每个 ICMP 代码的意义随消息的 ICMP 类型而变化。例如,尽管 ICMP 类型 3、5 和 11 都提供 ICMP 代码 1,但该代码在每个类型中都有完全不同的意义。
互联网数字分配机构(IANA)分配 ICMP 类型和代码,并在www.iana.org/assignments/icmp-parameters/维护当前分配列表。这些分配很少改变,因此表 3-4 提供了最常见的 ICMP 类型和代码。尽管不同 ICMP 消息的意义最好留给 TCP/IP 方面的书籍(如前面提到的《TCP/IP 指南》)来解释,但此表提供了一个便捷的参考。
表 3-4. 十进制和十六进制表示的常见 ICMP 类型和相关代码
| 类型 | 代码 | 十进制 | 定义 |
|---|---|---|---|
| 0 | 0 | 0 | 回显应答 |
| 3 | 目标不可达 | ||
| 0 | 300 | 网络不可达 | |
| 1 | 301 | 主机不可达 | |
| 2 | 302 | 协议不可达 | |
| 3 | 303 | 端口不可达 | |
| 4 | 304 | 需要分片,但设置了不分片 | |
| 6 | 306 | 目标网络未知 | |
| 7 | 307 | 目标主机未知 | |
| 9 | 309 | 与目标网络通信管理上禁止 | |
| 10(a) | 310 | 与目标主机通信管理上禁止 | |
| 13(d) | 313 | 通信管理上禁止 | |
| 5 | 重定向 | ||
| 0 | 500 | 子网重定向 | |
| 1 | 501 | 主机重定向 | |
| 8 | 0 | 800 | 回显请求 |
| 11(b) | 时间超出 | ||
| 0 | 2816 | 转发中的生存时间超时 | |
| 1 | 2817 | 分片重组超时 | |
| 12(c) | 3072 | 参数问题 | |
| 13(d) | 3328 | 时间戳请求 | |
| 14(e) | 3584 | 时间戳应答 |
流和 ICMP 详细信息
流传感器将 ICMP 类型和代码编码在流的目标端口中。目标(和源)端口是两个字节。端口的第一个字节给出类型,第二个字节给出代码。因为 ICMP 没有源端口的观念,所以源端口始终为零。在以下示例中,我从我的测试数据中选取了一些 ICMP 流。
此示例使用一种打印格式,显示目标端口为十六进制。您可以使用显示端口的十进制格式的格式,但必须将目标端口从十进制转换为十六进制才能解释它。
# `flow-cat ft* | flow-print -f 0 | less`
Sif SrcIPaddress Dif DstIPaddress Pr SrcP DstP Pkts Octets
0000 80.95.220.173 0000 36.85.32.153 01 0 ❶800 2 122
0000 189.163.178.51 0000 36.85.32.130 01 0 ❷b00 1 56
0000 64.142.0.205 0000 36.85.32.5 01 0 ❸300 1 56
0000 201.144.13.170 0000 36.85.32.130 01 0 ❹303 1 144
0000 36.85.32.9 0000 194.125.246.213 01 0 ❺0 5 420
...
第一个流量来自地址 80.95.220.173 到 36.85.32.153,目标端口为十六进制 800 (❶)。尽管 flow-print 不打印前导零,但你可以将其视为 0800,就像你可以将端口 25 视为端口 025 一样。在这个例子中,ICMP 类型是 8,代码是 00。ICMP 类型 8 没有相关代码,所以 flow-print 将 ICMP 代码显示为 00。
查看第表 3-4 可知,ICMP 类型 8 是一个回显请求,也称为 ping 尝试。主机 80.95.220.173 正在尝试 ping 36.85.32.153。
第二个 ICMP 流量目标端口为 b00 (❷),或 ICMP 类型为 b 和 ICMP 代码为 00。ICMP 类型 b 是 "超时"。与 ICMP 类型 8 不同,这种 ICMP 类型有相关代码。代码 0 表示 "传输过程中生存时间超时"。在这种情况下,IP 189.163.178.51 正在通知 IP 36.85.32.130,到达特定地址的时间过长,这通常意味着客户端已断开连接。
第三个流量,从 64.142.0.205 到 36.85.32.5,目标端口为 300 (❸)。ICMP 类型 3 消息表示目标不可达。ICMP 类型 3 的代码 0 表示 "网络不可达"。在这种情况下,主机 36.85.32.5 尝试连接到另一个主机,而互联网上的一个路由器正在返回一个表示目标网络不可达的消息。
第四个流量目标端口为 303 (❹)。ICMP 类型 3 表示目标不可达,但代码 03 表示 "端口不可达"。当客户端向未打开的服务器端口发送 UDP 请求时,服务器会返回此 ICMP 消息。如果你要搜索这些流量记录,你会在这两个主机之间找到相反方向的 UDP 请求。
我们第五个流量目标端口为 0 (❺)。ICMP 类型 0 是一个回显响应,或对 ping 的响应。如果你搜索这些流量,你会找到相反方向的回显请求。
如你所见,ICMP 消息通常是其他类型网络请求的响应。它们通常会显示尝试连接时发生的确切错误类型。将这些消息与其它流量匹配通常需要搜索流量记录,这最好通过过滤来实现,正如你将在第四章中看到的。
第四章. 流量过滤

好消息是,您现在有了关于您网络的实际数据。坏消息是,您有关于您网络的大量数据。一个互联网 T1 可能在一天内生成数百万个流量记录,而一个繁忙的以太网核心可能生成数十亿或更多。您如何管理或评估这些数据?您必须过滤数据以仅显示有趣的流量。flow-nfilter程序允许您根据需要包含或排除流量。
您可以以几乎任何您能想象的方式过滤流量。例如,如果某个服务器表现异常,您可以基于其 IP 地址进行过滤。如果您对 HTTP 流量感兴趣,可以基于 TCP 端口 80 进行过滤。您可以将数据减少到只包含有趣的流量,这将有助于您评估和诊断问题。例如,如果您有一个大型内部企业网络,您可能只想查看与特定分支机构交换的流量,基于其所有网络地址进行过滤。
在第三章中,您通过运行flow-cat并将结果数据流传递给flow-print来查看流量信息。过滤发生在这两个过程之间:flow-nfilter接受来自flow-cat的数据流并检查每个流量。匹配过滤器的流量将传递到flow-print(或其他流量处理程序);不匹配过滤器的流量将从数据流中掉落。
过滤基础
在本章中,您将首先构建几个简单的过滤器。一旦您了解了过滤器构建的基本知识,您将深入探讨各种过滤器类型和功能。
注意
在文件filter.cfg中定义您的过滤器,该文件可能位于/usr/local/flow-tools/etc/cfg/filter.cfg或/usr/local/etc/flow-tools/filter.cfg,具体取决于您的操作系统和您安装 flow-tools 的方式。
常见原始
您将使用原始构建您的过滤器。原始是一个简单的流量特征,例如“端口 80”、“TCP”或“IP 地址 192.0.2.1”。例如,这三个原始可以组合成一个过滤器,该过滤器将所有 TCP 流量传递到端口 80 上的主机 192.0.2.1。
flow-nfilter支持十多种不同的原始,并且可以以二十多种不同的方式将它们与流量进行比较。原始看起来大致如下:
filter-primitive *`name`*
❶ type *`primitive-type`*
❷ permit *`value`*
第一行定义了一个过滤原始并将其分配给一个名称。
❶处的类型定义了您想要匹配的特征,例如 IP 地址、端口或时间。(我将介绍最常用的过滤器类型。)
❷处的许可语句定义了您要查找的值。默认情况下,原始拒绝一切,因此您必须明确声明您的过滤器允许的内容。或者,您可以使用deny语句创建一个匹配除您要查找之外所有内容的原始,并在末尾明确放置一个default permit语句。
例如,一个匹配 IP 地址 192.168.1.1 的完整原语看起来像这样:
filter-primitive ❶ 192.0.2.1
❷ type ip-address
❸ permit 192.0.2.1
在❶处,我根据它匹配的地址命名了我的原语。如果你愿意,可以使用任何有意义的单字名称,例如“mailserver”或“firewall”。❷处的ip-address原语匹配网络地址。最后,在❸处,这个原语匹配任何等于 192.0.2.1 的 IP 地址。如果你将这个原语包含在过滤器中,它只会将流量传递到或从这个 IP 地址。
类似地,以下原语定义了端口 25:
filter-primitive ❶ port25
type ❷ ip-port
permit 25
虽然我可以将这个原语命名为25,但在❶处我使用了名称port25,以使其绝对清楚这个原语匹配一个端口,因为数字 25 本身可能是一段时间、每秒的字节或数据包计数、自治系统、楼层号等等。(IP 地址是独一无二的,所以使用地址作为名称可能不会让你混淆。)
❷处的ip-port原语是另一个常用的过滤器组件。将此原语包含在过滤器中意味着该过滤器只会通过端口 25 的流量。
默认的*filter.cfg*包括一个用于 TCP 流量的原语,如下所示:
filter-primitive ❶ TCP
type ❷ ip-protocol
permit ❸ tcp
你不太可能将❶处的名称 TCP 误认为是除了协议以外的任何东西,但❷处的ip-protocol原语允许你为任何 TCP/IP 协议创建一个原语。当然,如果你有晦涩的网络协议,你可能需要创建额外的协议原语,并且你的许可语句❸可以使用来自/etc/protocols的协议号或协议名称。
每个原语只能包含一种匹配类型。例如,以下是不合法的:
filter-primitive bogus-primitive
❶ type ip-port
permit 25
❷ type ip-address
permit 192.0.2.1
此原语尝试在端口号(❶)和 IP 地址(❷)上进行匹配。原语不能这样做。要过滤掉端口 25 上连接到 IP 地址 192.0.2.1 的连接,你必须从多个原语中组装一个过滤器。
现在你已经有一些原语了,你可以创建你的第一个过滤器。
使用条件和原语创建简单过滤器
使用filter-definition关键字将原语组合成过滤器,如下所示:
❶ filter-definition *`name`*
❷ match *`condition primitive1`*
match *`condition primitive1`*
...
每个过滤器都以filter-definition(❶)和一个名称开始。过滤器可以与原语共享名称,但不能与其他过滤器定义共享名称。
过滤器包含一系列match关键字(❷),后面跟着条件和原语。match关键字指定了该条目检查的流量部分以及与之比较的原语。
条件包括诸如 IP 地址、端口、协议、服务类型等内容。所有列出的条件都必须匹配,才能使过滤器匹配一个流量。例如,以下过滤器结合了TCP原语和port25原语:
filter-definition TCPport25
❶ match ip-protocol TCP
❷ match ip-source-port port25
此过滤器允许所有来自 TCP 端口 25 的流量通过。任何不是来自 TCP 端口 25 的流量都不会通过过滤器。
虽然基本元素和条件看起来很相似,但它们的名称可能不同。例如,过滤条件和使用ip-protocol关键词(❶)的过滤基本元素都使用。然而,在匹配端口时,基本元素使用ip-port关键词(❷),但过滤定义使用ip-source-port和ip-destination-port关键词。
注意
过滤错误最常见的原因是使用不正确的关键词。仅在过滤器中使用过滤关键词,仅在基本元素中使用基本关键词。
过滤器和基本元素的命名约定
仔细为您的过滤器和基本元素命名。如果您最初选择了模糊或令人困惑的名称,当您有数十个或数百个过滤器时,您可能会遇到麻烦!使您的名称易于识别,并且目的明确无误。
基本元素可以与过滤器共享名称。例如,你可以将一个基本元素命名为 TCP 和一个过滤器命名为 TCP,但你不能将两个基本元素都命名为 TCP 或两个过滤器都命名为 UDP。此外,过滤器和基本元素的名称不区分大小写。你不能将一个基本元素命名为tcp而另一个基本元素命名为 TCP。
使用您的过滤器
使用flow-nfilter的-F选项和过滤器名称来仅传递匹配您过滤器的流量。例如,在这里我正在打印仅匹配TCPport25报告的流量:
# `flow-cat * | flow-nfilter -F TCPport25 | flow-print | less`
srcIP dstIP prot srcPort dstPort octets packets
192.0.2.37 216.82.253.163 6 25 62627 1294 12
192.0.2.36 81.30.219.92 6 25 63946 1064 15
203.16.60.9 192.0.2.36 6 25 1054 1628 31
...
在这个例子中,您只能看到协议为 6(TCP)且源端口为 25 的流量。如果您正在调查邮件问题,这个过滤器将非常有用。过滤器显示邮件服务器从端口 25 发送了流量,因此邮件系统的网络层正在运行。
有用的基本元素
现在您已经了解了基本元素和过滤器是如何一起工作的,我将深入讨论基本元素。flow-nfilter支持许多不同的基本元素,但在这里我将只介绍最常用的几个。flow-nfilter的手册页包括完整的元素列表,但本书包含了我在多年的流量分析中使用过的每一个。
协议、端口和控制位基本元素
在网络协议和端口信息上过滤是减少流量记录列表到仅包含有趣流量的一种最常见方式。
IP 协议基本元素
您之前看到了一个基本的 IP 协议基本元素,但您可以检查除 TCP 之外的其他协议。例如,如果您使用 IPSec、OSPF 或其他在 IP 上运行但不在 TCP 或 UDP 上运行的网络协议,您最终需要单独查看它们。通过协议过滤是区分共享端口号的网络应用程序(如 syslog(UDP/514)和 rsh(TCP/514))的唯一方法。
当定义协议过滤器时,你可以使用来自/etc/protocols的协议号或名称。我更喜欢使用数字,这样/etc/protocols的变化就不会干扰流量分析。例如,OSPF 在协议 89 上运行,所以这里有一个匹配它的过滤器:
filter-primitive OSPF
type ip-protocol
permit 89
类似地,IPSec 使用两种不同的协议:ESP(协议 50)和 AH(协议 51)。以下原语匹配所有 IPSec 流量。(用逗号分隔多个条目。)
filter-primitive IPSec
type ip-protocol
permit 50,51
虽然 IPSec 协议没有端口号,但 flow-nfilter 可以显示任意两点之间的 IPSec VPN 使用的带宽以及 VPN 客户端的连接位置。
注意
默认的 filter.cfg 包含了 TCP、UDP 和 ICMP 的原语。
端口号原语
大多数网络应用程序运行在一个或多个端口上。通过过滤你的输出,只包括你感兴趣的网络的端口,你可以简化故障排除。为此,使用你之前看到的 ip-port 原语。
filter-primitive port80
type ip-port
permit 80
一个原语可以包括多个端口,用逗号分隔,如下所示:
filter-primitive webPorts
type ip-port
permit 80,443
如果你有一长串的端口列表,你可以为每个端口单独一行,并添加注释。此示例包括通过 TCP(telnet 和 POP3)以及 UDP(SMB)运行的服务。
filter-primitive unwantedPorts
type ip-port
permit 23 #telnet
permit 110 #unencrypted POP3
permit 138 #Windows SMB
...
你也可以为端口范围创建原语。
filter-primitive msSqlRpc
type ip-port
permit 1024-5000
IP 端口号原语可以使用来自 /etc/services 的名称,但我建议使用数字来保护你免受该文件中更改或错误的干扰。flow-print 和 flow-report 在必要时可以执行数字到名称的转换。
TCP 控制位原语
通过 TCP 控制位进行过滤可以识别异常网络流量。使用 ip-tcp-flags 原语通过控制位进行过滤。(参见 TCP 控制位和流量记录。)
filter-primitive syn-only
type ip-tcp-flags
permit 0x2
此原语匹配只包含 SYN 控制位的流,也称为 只包含 SYN 的流。服务器可能从未响应请求,防火墙阻止了连接请求,或者目标地址不存在服务器。
这些流量在裸露的互联网上相当常见,病毒和自动端口扫描器不断探测每个互联网地址,但在你的内部网络上应该相对不常见。内部网络上的大量只包含 SYN 的流通常表明软件配置错误、病毒感染或实际入侵者的探测。
类似地,你可以过滤只包含 RST 的流。只包含 RST 的流表示收到了连接请求并被立即拒绝,通常是因为主机请求在未打开的 TCP 端口上提供服务。例如,如果你在主机不运行 Web 服务器时请求该主机的网页,你可能会收到 TCP RST。
filter-primitive rst-only
type ip-tcp-flags
permit 0x4
虽然这种活动的一定程度是正常的,但确定只包含 SYN 和 RST 流的峰值发送者可以缩小性能问题和不必要的网络拥塞的范围。
要识别设置了多个控制位的流,请将控制位相加。例如,只包含 SYN 和 RST 控制位的流表明系统存在问题。要识别这些流,请编写一个匹配 SYN+RST 数据包的过滤器。
filter-primitive syn-rst
type ip-tcp-flags
permit 0x6 # 0x2 (SYN) plus 0x4 (RST)
一旦你开始在小型网络上检查 TCP 控制位,你会发现各种问题,并迅速破坏你快乐的无知。
ICMP 类型码原始数据类型
不同的 ICMP 类型码消息可以阐明网络活动。虽然你可以根据 ICMP 类型码和代码过滤流量,但这并不容易做到。
流将 ICMP 类型码编码为目标端口。匹配特定类型和代码的原始数据类型使用 ip-port 原始数据类型。ICMP 类型码通常以十六进制表示,但 ip-port 接受十进制值。(使用 Table 3-4 中的 Types and Codes in ICMP 识别适当的十进制值。)
例如,假设你正在寻找发送 ICMP 重定向的宿主机。重定向是 ICMP 类型 5,有两种代码,0(重定向子网)和 1(重定向宿主机)。以十六进制表示,这些是 500 和 501。表 3-4 Table 3-4 显示它们的十进制值为 1280 和 1281,因此可以编写如下原始数据类型:
filter-primitive redirects
type ip-port
permit 1280-1281
default deny
仅使用此原始数据类型进行过滤时,它会通过 ICMP、TCP 和 UDP 流。当你创建实际过滤器时,使用此原始数据类型和 ICMP 原始数据类型以仅查看 ICMP 重定向。
IP 地址和子网原始数据类型
通过地址和子网过滤流量可以让你缩小数据到感兴趣的宿主机和网络。
IP 地址
IP 地址的原始数据类型使用 ip-address 类型。将原始数据类型命名为它们匹配的 IP 地址是合理的,因为 IP 地址与其他类型的过滤原始数据类型难以混淆。
filter-primitive 192.0.2.1
type ip-address
permit 192.0.2.1
一个原始数据类型可以包含任意数量的地址。
filter-primitive MailServers
type ip-address
permit 192.0.2.10
permit 192.0.2.11
类似于这个 MailServers 示例的原始数据类型让你可以匹配执行特定功能的多台宿主机,例如“所有 Web 服务器”、“所有文件服务器”等等。
子网原始数据类型
原始数据类型也可以使用 ip-address-mask 和 ip-address-prefix 原始数据类型匹配子网。Flow-tools 提供了两种不同的子网格式,ip-address-mask 和 ip-address-prefix,以匹配两种常见的表示子网的记法。
ip-address-mask 原始数据类型期望一个完整的 IP 网络地址,其中子网掩码以十进制形式表示,如下所示:
filter-primitive our-network
type ip-address-mask
permit 192.0.2.0 255.255.255.0
此原始数据类型匹配 IP 地址在 192.0.2.0 和 192.0.2.255 之间的所有宿主机。
ip-address-prefix 原始数据类型使用前缀(斜杠)记法。
filter-primitive our-network
type ip-address-prefix
permit 192.168.0/24
permit 192.168.1/24
你可以在子网原始数据类型中包含多个子网,每个子网占一行,并且子网掩码或前缀不必在所有条目中相等。例如,以下是一个完全有效的原始数据类型:
filter-primitive mixed-netmasks
type ip-address-prefix
permit 192.168.0/23
permit 192.168.2/24
此原始数据类型匹配介于 192.168.0.0 和 192.168.2.255 之间的任何 IP 地址。
时间、计数器和双原始数据类型
你可以根据一天中的时间或任意的计数器值过滤流量。
原语中的比较运算符
时间和计数器原语使用逻辑比较运算符,如表 4-1 所示。
表 4-1. 时间和计数器比较运算符
| 运算符 | 比较 | 时间 |
|---|---|---|
gt |
大于 | 晚于 |
ge |
大于或等于 | 这个时间或之后 |
lt |
小于 | 早于 |
le |
小于或等于 | 早于或等于 |
eq |
等于 | 正好是这个时间 |
这些比较运算符 仅 用于时间和计数器原语,而不是在过滤器定义中使用。
时间原语
要根据流量开始或停止的时间进行过滤,请使用 time 原语。例如,这里,你正在寻找在早上 8:03 am 的分钟内停止或开始的流量。
filter-primitive 0803
type time
permit eq 08:03
注意
记住,流量记录使用 24 小时制时钟,所以晚上 8:03 pm 被过滤为 20:03。
你甚至可以进一步缩小时间范围。例如,如果你知道你感兴趣的流量在早上 8:03:30 am 的第二秒开始和结束,你可以为这个时间编写一个原语。
filter-primitive 0803
type time
permit eq 08:03:30
你不能根据毫秒时间间隔进行过滤。然而,传感器和收集器很少能精确到毫秒。
要定义一个时间间隔,请使用其他比较运算符。例如,假设你知道某件事发生在你的网络上的 7:58 am 到 8:03 am 之间。要过滤这段时间内的流量,定义一个从 7:58 到 8:03 的时间窗口,包括 8:03,使用ge和lt运算符,如下所示:
filter-primitive crashTime
type time
permit ge 07:58
permit le 08:03
虽然你可以通过选择要分析的流量文件来控制你报告的数据,但使用时间可以帮助进一步缩小搜索范围。这在检查大文件时非常有价值,并且证明了在网络上准确时间的需求。
注意
flow-nfilter 还支持用于特定日期和时间的 time-date 原语,例如 2011 年 1 月 20 日早上 8:03 am。然而,如果你对特定日期感兴趣,分析该日期的流量文件会更好。流量文件以它们的创建年份、月份、日期和时间命名是有原因的。
计数器原语
counter 原语允许你创建如“超过 100 字节”或“在 500 到 700 个数据包之间”的过滤器。在创建此类过滤器时,使用一个或多个整数比较运算符定义计数器,如下所示:
filter-primitive clipping
type counter
permit gt 10000
这个特定的过滤器会通过任何超过你试图测量的 10,000 个内容的流量。作为另一个例子,假设你只想查看持续 1,000 毫秒(1 秒)或更长的流量。以下是你可以这样做的方法:
filter-primitive 1second
type counter
permit ge 1000
或者,也许你只想过滤 1KB 或更大的流量。
filter-primitive 1kB
type counter
permit ge 1024
你可以在计数器中使用多个比较。例如,这里,我允许大于 1,000 且小于 2,000 的所有内容:
filter-primitive average
type counter
permit gt 1000
permit lt 2000
注意
当使用counter原语时,请记住,计数器仅在基于字节、数据包和/或持续时间进行过滤时才起作用。计数器不会匹配 TCP 端口或 IP 地址。
双重原语
不,double原语并不比 flow-tools 中的其他原语简单两倍。double原语是一个带有小数点的counter。它可以匹配每秒数据包数或每秒比特数。
例如,假设你想忽略每秒发送 100 个或更多数据包的所有连接。你需要一个原语来定义其中的 100 部分。
filter-primitive lessThan100
type double
permit lt 100.0
你将看到如何在过滤器定义中将它与每秒数据包数联系起来,但这个原语定义了过滤器的“小于 100”部分。
与counter原语一样,double不能匹配任意数据。它只能匹配字节、数据包和持续时间。
接口和 BGP 原语
从路由器导出的流量记录包括路由信息,但其中大部分信息仅在你使用动态路由,如边界网关协议(BGP)时才有用。如果你不使用 BGP 或其他动态路由协议,你可以跳过这一部分。
使用 SNMP 识别接口数字
大多数路由器配置接口(如 Cisco 的命令行)给每个路由器接口一个人类友好的名称,例如 FastEthernet0 或 Serial1/0。内部,路由器通过数字识别每个接口。路由器在流量记录中使用接口数字,而不是人类友好的名称。
获取接口名称及其对应数字的最简单方式是通过简单网络管理协议(SNMP)。如果你使用多个互联网服务提供商,你几乎肯定拥有某种 SNMP 功能。大多数类 Unix 系统都包括 net-snmp 软件包,所以我会以它为例。其他 SNMP 浏览器应该会呈现类似的结果。
记住,SNMP 以层次树的形式呈现信息。要获取网络接口列表,请检查 SNMP 树中的RFC1213-MIB::ifDescr分支。要查看接口名称和数字,请使用snmpwalk查询路由器的RFC1213-MIB::ifDescr值。如果你的 MIB 浏览器不支持人类友好的名称,RFC1213-MIB::ifDescr等同于.1.3.6.1.2.1.2.2.1.2。
# `snmpwalk -v` ❶ ``*`2`*`` `-c` ❷ ``*`community`*`` ❸ ``*`router`*``
`RFC1213-MIB::ifDescr`
RFC1213-MIB::ifDescr.❹1 = STRING: ❺ "FastEthernet0/0"
RFC1213-MIB::ifDescr.2 = STRING: "FastEthernet0/1"
RFC1213-MIB::ifDescr.4 = STRING: "Null0"
RFC1213-MIB::ifDescr.5 = STRING: "T1 0/0/0"
RFC1213-MIB::ifDescr.6 = STRING: "T1 0/0/1"
RFC1213-MIB::ifDescr.7 = STRING: "Serial0/0/0:0"
RFC1213-MIB::ifDescr.8 = STRING: "Serial0/0/1:1"
RFC1213-MIB::ifDescr.9 = STRING: "Tunnel1"
在前面的示例中,在❶处,你使用 SNMP 版本 2 查询路由器,使用其社区名称(❷)和路由器的主机名或 IP 地址(❸)。作为回应,你得到一个路由器接口名称列表。
SNMP 索引是路由器接口的内部编号。例如,在❹处,接口 1 被命名为FastEthernet0/0(❺)。接口 7 被命名为Serial0/0/0:0,依此类推。
网络工程师应该注意,在列出的八个接口中,接口 4(null0)是一个逻辑接口,永远不会看到任何流量。同样,接口 5 和 6 不是真实接口;它们是支持接口 7 和 8 的接口卡。只有五个接口中的八个会传递流量。
默认情况下,Cisco 路由器可以在重启时更改其接口编号,这防止了在添加或删除接口时接口编号出现空缺。然而,接口编号任意更改会真正混淆长期报告。我建议您的路由器在重启之间保持一致的接口编号。诚然,这会在接口列表中留下空缺;请注意示例路由器上接口 3 的缺失。另一方面,接口 7 始终是 Serial 0/0/0:0,即使多年以后也是如此。通过配置选项snmp-server ifindex persist告诉 Cisco 设备保持接口编号不变。
此外,请注意,如果您有多个路由器向单个收集器导出数据,您必须分离数据以获取有意义的接口信息。例如,路由器 A 上的接口 8 可能是一个本地以太网接口,而路由器 B 上的接口 8 可能是一个上游 T1 接口。您可以通过导出器 IP 地址过滤数据,但这会创建一个额外的过滤层需求。
我将在接下来的示例中使用之前的接口列表。接口 1 和 2 是本地以太网端口,接口 7 和 8 是连接到两个不同互联网服务提供商的 T1 电路,而接口 9 是一个 VPN 隧道。其他接口不应该看到流量。
接口编号原语
通过接口进行过滤只传递通过该接口的流量。为此,请使用ifindex原语。
filter-primitive vpnInterface
type ifindex
permit 9
接口 9 是 VPN 接口。对其过滤只会显示通过 VPN 的流量。
(您可以在一行上列出多个接口。)
filter-primitive localEthernet
type ifindex
permit 1,2
通过接口进行过滤让您能够关注特定网络段之间的流量流动。
自治系统原语
自治系统(AS)是 BGP 路由的核心,具有 BGP 对等体的路由器在其流量导出中包含 AS 编号信息。您可以使用as原语提取特定 AS 编号的流量,如下所示:
filter-primitive uunet
type as
permit 701
您可以在一行上列出多个 AS 编号,用逗号分隔,或者甚至可以列出 AS 编号的范围。当然,您也可以在单独的行上添加多个 AS 编号。(ARIN、RIPE 和其他 AS 注册机构经常以块的形式向大型组织颁发 AS 编号,因此您可能需要创建这样的过滤器。)
filter-primitive uunet
type as
permit 701-705
您还可以使用ip-address-prefix-len原语编写用于路由公告前缀长度的过滤器。我没有找到一种过滤器,它说“显示我们正在获取的所有/25 或更长的路由”,但运营商和转接提供商可能发现识别试图宣布小型网络的客户端很有用.^([5])
^([5]) 如果你不是转接提供商,但正在尝试宣布小型网络,你应该从中学到的教训是:小型路由公告不会起作用,如果它们确实起作用,它们可以找到你。
过滤匹配语句
要将原语组装成过滤器,请使用match语句。flow-nfilter会将每个数据流与过滤器中的每个match语句进行比较,如果数据流符合每个match语句,则数据流通过。如果数据流不符合每个match语句,则数据流将从数据流中移除。
许多匹配类型的名称与其相关原语相似。例如,ip-protocol原语有一个相应的ip-protocol匹配。其他原语没有单一的匹配条件。例如,ip-port原语可以匹配ip-source-port原语或ip-destination-port原语。如果您在配置中使用了错误的match语句,flow-nfilter将带错误退出。
过滤器定义支持许多不同类型的匹配条件。flow-nfilter的手册页有完整的列表,但这里描述了我认为有用的那些。
协议、端口和控制位
匹配协议和端口是非常常见的。控制位和 ICMP 类型和代码则不太常见,但以不同的方式强大。
网络协议过滤器
使用ip-protocol匹配类型来检查每个数据流是否与ip-protocol原语匹配。
我之前定义了一个 OSPF 原语。现在,我正在使用这个原语来仅允许 OSPF 流量通过:
filter-definition OSPF
match ip-protocol OSPF
在过滤器中列出多个协议原语将导致没有数据包匹配。毕竟,非常少的数据流既是 TCP 又是 UDP。
源或目的端口过滤器
flow-nfilter对源端口(ip-source-port)和目的端口(ip-destination-port)有单独的匹配。这些匹配与ip-port原语。在这里,我正在使用之前定义的port80原语来过滤发送到 Web 服务器的流量:
filter-definition port80
match ip-destination-port port80
要匹配一个服务的多个端口,定义一个包含该服务所有端口的原语。例如,之前我定义了一个webTraffic原语,用于端口 80 和 443。
filter-definition webTraffic
match ip-destination-port webTraffic
类似地使用ip-source-port。例如,为了捕获离开您的 Web 服务器的流量,过滤掉 80 和 443 端口的流量。(您将在过滤器定义中的逻辑运算符中看到如何编写匹配到达和离开流量的报告。逻辑运算符在过滤器定义。)
filter-definition webTraffic
match ip-source-port webTraffic
TCP 控制位过滤器
使用ip-tcp-flags关键字来匹配 TCP 控制位原语。例如,我之前定义了一个rst-only原语,它匹配只包含 TCP 重置的数据流。
filter-definition resets
match ip-tcp-flags rst-only
此过滤器仅显示匹配rst-only原语的流量。您不需要指定协议,因为流量记录仅包含 TCP 流量的控制位。您可以使用非常相似的过滤器来匹配其他 TCP 控制位原语。
ICMP 类型和代码过滤器
记住,流记录了 ICMP 类型和代码在 ICMP 流的目标端口字段中。然而,与仅在 TCP 流记录中出现的 TCP 控制位不同,目标端口出现在 TCP、UDP 和 ICMP 流中。为了特定地匹配 ICMP 类型和代码,你的过滤器必须包括目标端口和协议,如下所示:
filter-definition redirects
❶ match ip-destination-port redirects
❷ match ip-protocol ICMP
我之前在❶处定义了一个redirects原始过滤器,它匹配 ICMP 重定向类型中的所有代码。在这里,我添加了一个匹配(❷)用于ICMP协议原始过滤器。此过滤器仅传递包含 ICMP 重定向的流。
地址和子网
flow-nfilter支持两种 IP 地址匹配类型:源地址(ip-source-address)或目标地址(ip-destination-address)。这些匹配类型可以在三个 IP 地址原始过滤器中的任何一个上工作:ip-address、ip-address-mask或ip-address-prefix。
你可以在一行上匹配源地址,在另一行上匹配目标地址。例如,假设你有一个用于你的客户端网络的ip-address-prefix原始过滤器,另一个用于你的 Web 服务器。以下定义传递来自你的客户端到你的 Web 服务器的流量:
filter-definition clientsToWeb
match ip-destination-address webServers
match ip-source-address clientNetwork
你不能在单个过滤器中列出同一类型的多个匹配项,因为单个流不能有多个源或目标地址!要从多个源或目标地址传递流量,请使用包含所有所需地址的原始过滤器。
下一个过滤器捕获来自 Web 客户端的服务器数据。你需要一个相应的报告来捕获来自你的 Web 服务器到客户端网络的流量(或者一个稍微复杂一些的过滤器来捕获双向移动的流量,正如你将在过滤器定义中的逻辑运算符中看到的)。因为你只想看到 Web 流量,所以你也使用 Web 流量和 TCP 的原始过滤器进行过滤。
filter-definition clientsToWebHttpTraffic
match ip-port webTraffic
match ip-protocol TCP
match ip-destination-address webServers
match ip-source-address clientNetwork
你将在使用多个过滤器中看到其他实现相同效果的方法,在下一跳地址过滤器。
通过传感器或导出器进行过滤
多个流量传感器可以导出到单个收集器,但有时你只想看到来自特定传感器的流。你可以使用ip-exporter-address匹配与任何 IP 地址原始过滤器一起创建一个过滤器,该过滤器仅传递来自特定传感器的流,如下所示:
filter-primitive router1
type ip-address
permit 192.0.2.1
filter-definition router1-exports
match ip-exporter-address router1
此特定过滤器仅传递从 192.0.2.1 路由器导出的流。
时间过滤器
start-time和end-time匹配类型允许你使用time原始过滤器根据流的开始和结束时间进行过滤。例如,以下示例使用之前定义的0803时间原始过滤器捕获所有在特定分钟内发生的流:
filter-definition 0803
match start-time 0803
match end-time 0803
你可以定义一个过滤器,以匹配任何可以用原语表达的时间开始或结束的流量。
在大多数情况下,你不会有关于问题的准确时间信息。人类的时间感非常模糊:“几分钟前”可能从 30 秒到一小时不等,几天后甚至那个时间也不可靠。记住,每个流量文件覆盖了五分钟的时间段。大多数时候,你最好在整个流量文件中搜索问题,而不是尝试根据时间进行过滤。我发现,只有在非常大的流量文件上,并且只有当你从流量文件本身获得精确的时间信息时,根据时间进行过滤才有用。一个人说网站在早上 8:15 am 崩溃是不可靠的。然而,如果你的流量记录显示你在早上 8:15 am 有异常流量,你可能想看看那一分钟内还发生了什么。在这种情况下,根据时间进行过滤可能会有用。
剪裁级别
剪裁级别 是你开始忽略数据的那一点。例如,你可能不关心包含极小数据量的流量,或者你可能只想看到极小的流量。为了剪裁数据,你可以在传输流量量、连接速度和连接持续时间上设置剪裁级别。
字节、数据包和持续时间过滤器
使用 counter 原语根据每个流中的字节数、每个流中的数据包数或流的持续时间进行过滤。例如,我之前定义了一个 1KB 或更大的原语。现在让我们使用这个原语来从流量数据中移除微小的连接。
filter-definition 1kBplus
match octets 1kB
同样,你为总计 1000 个或更多的情况创建了一个原语,称为 1second。你可以编写一个使用此原语的过滤器,以允许只有 1000 毫秒(1 秒)或更长的流量。
filter-definition over1second
match duration 1second
计数器是任意数字,可以应用于字节数、数据包数或持续时间。例如,如果你想有一个只包含 1,024 个或更多数据包的流量过滤器,你可以很容易地重复使用 1kB 原语。
filter-definition 1024plusPackets
match packets 1kB
尽管你可以这样做,但我尽量避免以这种方式重复使用原语。你从未听说过千字节的数据包!这样的过滤器让我感到困惑。在尝试识别网络问题时感到困惑并不是好事。⁶]
每秒数据包或比特过滤器
也许你对连接移动的速度感兴趣,或者你只对非常快或非常慢的连接感兴趣。如果是这样,你可以使用 double 原语根据每秒的数据包数或比特数进行过滤。
例如,你之前定义了一个小于 100 的 double 原语。你可以用它来过滤每秒的数据包数或比特数。
filter-definition lessThan100pps
match pps lessThan100
filter-definition lessThan100bps
match bps lessThan100
在这个特定情况下,我不介意重复使用 lessThan100 原语,因为这个名字并没有与特定数据类型紧密相关。
BGP 和路由过滤器
你可以根据流量记录中包含的路由信息来过滤流量。(如果你没有使用 BGP,可以跳过这一节。)
自治系统编号过滤器
source-as和destination-as匹配类型允许你基于 AS 号码进行匹配。例如,这个过滤器允许你查看你接收到的流量(来自之前是 UUnet 网络的流量)使用之前定义的uunet AS 原始指令:
filter-definition uunet
match source-as uunet
你也可以反过来创建一个过滤器,允许发送到 UUnet 系统的流量。
下一跳地址过滤器
下一跳是路由器发送流量的 IP 地址。这通常是 ISP 电路远程端的 IP 地址(对于出站流量)或你的防火墙的外部地址(对于入站流量)。路由器在流量记录中包含下一跳地址。然而,像softflowd这样的软件流量传感器对远程主机的接口或数据包的路由方式一无所知,因此从软件流量传感器导出的流量不包含下一跳地址。
现在假设你其中一个互联网服务提供商的下一步 IP 地址是 61.118.12.45。为了过滤通过该 ISP 离开你网络的全部流量,你可以使用一个原始的定义,如下所示:
filter-primitive ispA
type ip-address
permit 61.118.12.45
filter-definition ispA
match ip-nexthop-address ispA
ip-nexthop-address匹配类型与ip-address、ip-address-mask和ip-address-prefix原始指令一起工作。
接口过滤器
另一种按提供商或网络段过滤的方法是通过路由器接口进行过滤。匹配类型input-interface和output-interface允许你根据到达或离开你的路由器的流量进行过滤。
你之前为路由器接口 9 定义了一个原始指令。这里我在一个过滤器中使用它:
filter-definition vpn
match input-interface vpnInterface
这显示了进入此接口的路由器上的流量。
^([6]) 我不需要浪费时间称自己为傻瓜,因为我给一个过滤器起了一个模糊的名字。很多人因为各种原因都乐于称我为傻瓜。
使用多个过滤器
假设你想识别两台机器之间的所有流量。你可以为这两个主机定义原始指令,然后编写一个特别定义这些主机的过滤器。然而,这种常见情况会让你非常忙碌地编写新的过滤器。相反,我发现定义较小的过滤器并在命令行上连接它们要容易得多。
你可以在单个命令中重复调用flow-nfilter。找到你感兴趣的时段的流量文件,对第一个主机进行过滤,然后对第二个主机进行第二次过滤。
# `flow-cat ft-* |` ❶ `flow-nfilter -F host1 |` ❷
`flow-nfilter -F host2 | flow-print | less`
第一个flow-nfilter调用❶只允许包含来自host1的流量的流量。第二个❷只允许包含来自host2的流量的流量。
类似地,你可以为某些协议编写单独的过滤器,比如所有 Web 流量。你之前创建了一个名为webTraffic的过滤器,用于所有 HTTP 和 HTTPS 流量。
# `flow-cat ft-* |` ❶ `flow-nfilter -F host1 |` ❷
`flow-nfilter -F webTraffic | flow-print | less`
第一个过滤器❶只允许对感兴趣的主机的流量,第二个(❷)只允许 HTTP 和 HTTPS 流量。
你可以为你网络中的重要主机和子网创建简单的过滤器。例如,如果你有一个报告无法访问你网站的客户的案例,你可以为你的网站编写一个流量过滤器,并为客户的地址编写一个,然后使用这两个过滤器来查看你网络之间传递的流量。然后你可以查找表示问题的 SYN-only 或 RST-only 流量。或者,你可能发现来自客户网络的流量根本无法到达你。在任何情况下,这两个过滤器都会告诉你网络上出现了什么流量以及它的行为方式。
通过在命令行上组合过滤器,你会编写更少的过滤器,并更充分地利用你创建的过滤器。
过滤器定义中的逻辑运算符
当你在过滤器定义中放入多个匹配条件时,flow-nfilter会在它们之间放置一个逻辑“与”。例如,以下过滤器显示所有运行在 TCP 上且源端口为 25 的流量。这通过连接传递电子邮件服务器的响应。
filter-definition TCPport25
match ip-protocol TCP
match ip-source-port port25
你可以使用其他逻辑运算符来构建非常复杂的过滤器。
逻辑“或”
当我尝试分析一个连接问题时,我通常想看到对话的双方。我需要一个可以显示到端口 25 的连接以及从端口 25 的连接的过滤器。为此,使用以下or运算符:
filter-definition email
match ip-protocol TCP
match ip-source-port port25
❶ or
❷ match ip-protocol TCP
❸ match ip-destination-port port25
在❶处的or语句之后,开始了一个全新的过滤器定义。尽管我在第一个过滤器中列出了TCP,如果你对第二个过滤器中的 TCP 感兴趣,你必须重复在❷处的 TCP 匹配,然后你可以添加❸处的新的match语句来捕获结束于端口 25 的流量。现在,如果你将此过滤器应用于你的流量数据,你会看到如下内容:
# `flow-cat ft-v05.2011-12-20.12* | flow-nfilter -F email | flow-print | less`
srcIP dstIP prot srcPort dstPort octets packets
❶ 217.199.0.33 192.0.2.37 6 5673 25 192726 298
❷ 192.0.2.37 217.199.0.33 6 25 5673 8558 181
206.165.246.249 192.0.2.37 6 38904 25 13283 22
192.0.2.37 206.165.246.249 6 25 38904 1484 16
...
❶处的第一个流量是从远程 IP 地址到本地电子邮件服务器的地址,目标端口为 25。这是一个传入的邮件传输。❷处的第二个流量是从邮件服务器到相同的远程 IP 地址;它来自端口 25。这是对第一个流量的响应。
我可以使用更复杂的flow-print格式来更详细地查看这些信息,运行flow-report来检查错误,或者添加另一个过滤器来特别指出电子邮件流中的 TCP 错误。这个简单的检查显示邮件服务器在 TCP 端口 25 上交换了大量的流量。我会告诉我的邮件管理员检查日志以查找错误或提供更多信息。
过滤器反转
有时候编写一个过滤掉你不感兴趣的流量会更容易。例如,假设你想查看所有不是电子邮件的到或从你的电子邮件服务器的流量。虽然你可以编写包含所有端口号除了电子邮件端口的原始代码,但这很烦人且繁琐。
相反,使用invert关键字来反转过滤器的含义,如下所示:
filter-definition not-email
❶ invert
match ip-protocol TCP
match ip-source-port port25
or
match ip-protocol TCP
match ip-destination-port port25
通过在❶的报告中添加invert,你可以传递所有不匹配定义的过滤器的内容。在这个例子中,我正在传递所有不涉及 TCP 端口 25 的网络事务。
但这个过滤器有一个问题:它会匹配你捕获数据的所有主机上的所有非电子邮件流量。然而,你只需要查看你的电子邮件主机的流量。
为了解决这个问题,你可以将你的电子邮件服务器添加到not-email过滤器中,但电子邮件服务器既发送也接收电子邮件。你需要为连接到你的邮件服务器的远程服务器定义一个部分,为你的服务器对那些远程服务器的响应定义一个部分,为你的邮件服务器连接到远程邮件服务器定义一个第三部分,以及为远程服务器对你的服务器请求的响应定义一个第四部分。这看起来相当糟糕。
定义一个单独的过滤器,将流量数据简化到仅包含电子邮件服务器,然后将这两个过滤器连接起来,会更简单,如下所示:
❶ filter-primitive emailServers
type ip-address
permit 192.0.2.37
permit 192.0.2.36
❷ filter-definition emailServers
match ip-source-address emailServers
or
match ip-destination-address emailServers
emailServers 原语在❶中包含了所有邮件服务器的 IP 地址。接下来,在❷我创建了一个过滤器定义来匹配所有离开或前往这些服务器的流量。然后,为了查看所有非电子邮件流量到或来自我的电子邮件服务器,我这样做:
# `flow-cat * |` ❶ `flow-nfilter -F emailServers |` ❷
`flow-nfilter -F not-email | flow-print | less`
在❶的emailServers过滤器中,只传递涉及我的电子邮件服务器的流量。在❷的not-email过滤器中,只传递不是 SMTP 的流量。通过结合这两个过滤器,我只看到有趣的流量。我可能需要进一步调整过滤器以删除其他不感兴趣的流量,例如到 DNS 服务器的 DNS 查询,但我几乎做到了。
当然,在审查过滤后的流量后,我可以去问我的电子邮件管理员为什么他在邮件服务器上运行自己的 DNS 服务器而不是使用公司名称服务器,以及为什么他从那些机器上浏览网页而不是使用代理服务器及其成人内容过滤器。7]
^([7]) 是的,我可以直接去人力资源部门,但人力资源部门不会洗车和打蜡。
过滤器和变量
Flow-tools 还包括可以在命令行上配置的过滤器,这对于非常简单的过滤器很有用,例如识别来自特定 IP 地址的流量。使用这些过滤器的默认过滤器相当有限,但它们足以进行简单的流量分析。编写自己的变量驱动报告也很容易。
使用变量驱动过滤器
命令行上可配置的过滤器使用三个变量:ADDR(地址)、PORT(端口)和PROT(协议)。这些支持五个报告,让你可以根据协议以及源地址和端口进行过滤:ip-src-addr、ip-dst-addr、ip-src-port、ip-dest-port和ip-prot。
假设你的老板给你打电话。她正在某个不方便的城市的一个随机开放的无线热点连接,无法进入公司的 VPN 集中器。你可以通过询问她或者通过访问系统日志查看她的来源来获取她的 IP 地址。为了查看所有来自她 IP 地址的网络流量,而不需要编写自定义过滤器,你可以使用该时间窗口的流文件上的命令行变量。例如,如果她的 IP 地址是 192.0.2.8,你会使用如下命令:
# `flow-cat * | flow-nfilter -F ip-src-addr` ❶ `-v ADDR=192.0.2.8 | flow-print`
-v参数❶告诉flow-nfilter你正在为一个变量分配值。在这个例子中,我已将值 192.0.2.8 分配给变量ADDR。你将看到所有从这个 IP 地址起源的流量。
何时使用变量驱动过滤器?
对于单个主机和端口的简单过滤器,使用变量驱动过滤器。如果你必须过滤多个主机或端口的范围,请在filter.cfg中定义原语和过滤器。
定义您自己的变量驱动过滤器
变量驱动过滤器利用了在filter.cfg中定义的原语VAR_ADDR(地址)、VAR_PORT(端口)和VAR_PROT(协议)。例如,以下是一个默认的变量驱动过滤器,它使用ADDR变量。这看起来就像一个标准的报告,除了它使用变量名而不是原语。
filter-definition ip-src-addr
match ip-source-address VAR_ADDR
使用这些变量来定义你自己的变量驱动过滤器。例如,我喜欢看到所有来自和到一个感兴趣的主机的流量。编写这个报告的命令行版本很容易。
filter-definition ip-addr
match ip-destination-address VAR_ADDR
or
match ip-source-address VAR_ADDR
同样,我更喜欢同时查看到和来自端口的全部流量。
filter-definition ip-port
match ip-destination-address VAR_PORT
or
match ip-source-address VAR_PORT
使用这些报告,我可以动态地实时过滤任何单个主机或端口。
创建您自己的变量
VAR_ADDR、VAR_PORT和VAR_PROT不是硬编码在flow-nfilter中的魔法变量;它们在filter.cfg中定义。以下是VAR_PORT的定义:
filter-primitive VAR_PORT
type ip-port
permit ❶ @{PORT:-0}
大多数这个原语看起来像任何其他端口号的原语,但permit语句❶非常不同。这个例子将命令行上定义的变量PORT转换为一个数字。这个工作原理的具体细节并不重要,但你可以用这个样本作为你自己的原语的模型。
现在再举一个例子。我经常与 BGP 打交道,所以我需要一个 AS 号原语。
❶ filter-primitive VAR_AS
❷ type as
❸ permit @{AS:-0}
我已将这个原语命名为VAR_AS❶,以与现有的变量名对应,并已将其分配为as类型❷。permit语句❸是从VAR_PORT原语复制的,用变量名AS代替了端口。现在我可以使用这个变量创建一个过滤器。
filter-definition AS
❶ match source-as VAR_AS
or
❷ match destination-as VAR_AS
这与之前基于自定义变量的过滤器非常相似,因为你传递的是前往指定 AS(❶)和来自该 AS 的流量。现在你可以使用这个过滤器来获取特定自治系统的流量。
`# flow-cat * | flow-nfilter -F as-traffic -v AS=701 | flow-print -f 4 | less`
当你应用这个过滤器时,你将只看到涉及 AS 号 701 的流量。
到目前为止,你应该能够以任何你喜欢的任何方式过滤流量。现在让我们对那些数据进行分析。
第五章. 报告和后续分析

能够查看通过网络传输的确切流量是一种强大的工具,但任何人都能用这些数据做什么呢?毕竟,很少有人能目测一份包含 15,000 个流程的列表,并识别出最活跃的 10 个主机、最常见的端口号,甚至按 IP 进行排名。仔细选择要检查的流程文件并过滤其内容可以减少你必须阅读的流程数量,但这仍然让你面对一个巨大的数据集,即使在小型网络上也需要整合、汇总和分析。你需要一个工具来汇总流量数据、对其进行排序并显示累积结果。
flow-report程序读取流程并生成总计、排名、每秒和每接口计数以及其他报告。你可以创建精心定制的报告,反复运行,或者使用内置的报告来执行临时分析。flow-report允许你快速回答基本问题,例如“哪个 Web 服务器发送的流量最多?”和“哪个主机正在散播病毒?”在本章中,你将了解如何使用flow-report的许多选项,以及如何快速回答你关于网络的最重要的疑问。
默认报告
flow-report生成的所有内容都在文件stat.cfg中配置。默认配置包括一个通用报告,提供了在命令行上覆盖许多设置的选项,就像flow-nfilter允许你在命令行上配置过滤一样。你将从默认报告开始,看看你能将其扩展到什么程度。
首先,你将使用没有任何配置的默认报告。这将生成摘要-详细报告,这是对流程数据的通用统计分析。摘要-详细报告相当长,所以我将把它分成几个部分。
# `flow-cat * | flow-report`
# --- ---- ---- Report Information --- --- ---
# build-version: flow-tools 0.68.4
❶ # name: default
❷ # type: summary-detail
❸ # options: +header,+xheader,+totals
❹ # fields: +other
❺ # records: 0
# first-flow: 1322715601 Thu Dec 1 00:00:01 2011
# last-flow: 1322719199 Thu Dec 1 00:59:59 2011
# now: 1325460205 Sun Jan 1 18:23:25 2012
#
# mode: streaming
# compress: off
# byte order: little
# stream version: 3
❻ # export version: 5
#
❼ # ['/usr/local/bin/flow-rptfmt', '-f', 'ascii']
每一行以井号开始的都是关于报告如何准备或关于实际流程文件注释的信息。这些信息包括 flow-tools 使用的版本、流程文件中第一个和最后一个流程的日期和时间、当前日期和时间等。
在❶处,你可以看到报告的名称,这是在报告配置文件中定义的。我还没有创建任何自定义报告,因此我生成了默认报告。
报告类型(❷)决定了流程数据如何排列、搜索、排序和展示。报告类型包括“最常见的端口号”和“最常见的地址”等。我将在本章中介绍它们中的大多数。这个特定的报告是摘要-详细报告。
报告选项(❸)告诉flow-report在报告中包含什么内容。例如,+header和+xheader选项告诉flow-report包含你现在正在查看的报告元信息。你可以在命令行上覆盖默认选项或在自定义报告中设置它们。
字段设置(❹)告诉flow-report在报告中包含哪些信息。字段是报告中的列,正如您稍后将在其他报告类型中看到的那样。同样,您可以在命令行上覆盖默认字段或在自定义报告中设置它们。
记录字段(❺)显示flow-report是否将其输出限制在特定行数。您可以在命令行或报告定义中设置最大行数。如果您想了解例如前 10 个生成某种类型流量的主机,这个功能很有用。
了解流版本(❻)在流文件中告诉您报告包含哪些信息。例如,您不会从 NetFlow 版本 1 中获得 BGP 信息。
最后,在❼中,您可以看到用于格式化报告的命令。flow-report程序仅生成逗号分隔值(CSV)报告,并依赖于外部程序(flow-rptfmt)来创建格式化文本或 HTML。
时间和总计
下一个部分包括关于流记录内部数据的详细信息。前六行仅在报告定义包括+totals选项时显示。
❶ Ignores: 0
Total Flows: 54286
Total Octets: 633669712
Total Packets: 996238
❷ Total Duration (ms): 884588200
❸ Real Time: 1322719199
❹ Average Flow Time: 16294.000000
❺ Average Packets/Second: 636.000000
Average Flows/Second: 11672.000000
Average Packets/Flow: 18.000000
❻ Flows/Second: 0.042795
Flows/Second (real): 0.000044
flow-report(❶)忽略零包的流。零包流通常是错误,但在其他计算中包含它们将使平均值失真。
然后您可以看到这些流中的总流数、字节数和包数。我捕获了 54,286 个流,或 633Mb,在 996,238 个包中。
总持续时间(❷)是流持续的总时间的总和,以毫秒为单位。例如,10 个一秒的流将给出总持续时间为 10 秒,或 10,000 毫秒,即使这些流是同时运行的。
剩余信息都是默认的摘要-详细报告的一部分。
实时标题(❸)告诉流数据何时在 Unix 纪元时间结束。1322719199 是 2011 年 12 月 1 日星期四 00:59:59 EST,或者接近凌晨 1 点。
平均流时间(❹)是平均流持续时间,以毫秒为单位。
然后您有❺中的平均每秒包数、每秒流数和每流包数。
❻处的两个每秒流数值可能会令人困惑。第一个每秒流数通过将流数除以样本中的秒数来给出您期望的每秒流数。每秒流数(实际)值的计算基于纪元时间,对于大多数网络管理目的并不有用。
数据包大小分布
摘要-详细报告的下一段,数据包大小分布,显示了这些流中数据包的大小占所有数据包的比例。
❶ 1-32 ❸64 96 128 160 192 224 256 288 320 352 384 416 448 480
❷ .000 ❹.232 .443 .067 .157 .045 .008 .005 .004 .003 .011 .003 .002 .001 .002
512 544 576 1024 1536 2048 2560 3072 3584 4096 4608
.001 .001 .001 .006 .008 .000 .000 .000 .000 .000 .000
第一个条目在❶显示了这些流中数据包的大小在 1 到 32 字节之间的比例;在这种情况下,没有,正如您在❷中看到的。
这些流中略少于四分之一的包(❹中显示为.232)是 64 字节长(❸中显示)。(我从使用率很高的 DNS 服务器所在的网络段中提取了这些样本,因此我预计会有很多小流。)几乎一半的包是 96 字节。
每个流量的数据包数量
摘要-详细报告的下一部分是每个流量的数据包数量,格式与数据包大小分布表类似。
❶ 1 2 4 ❸ 8 12 16 20 24 28 32 36 40 44 48 52
❷ .307 .051 .135 .235 .072 .041 .032 .023 .019 .013 .012 .006 .004 .004 .003
60 100 200 300 400 500 600 700 800 900 >900
.005 .013 .013 .003 .002 .001 .001 .000 .000 .000 .003
在这里您可以看到 ❷ 中 0.307,或大约 31%,的流量只包含一个数据包(如 ❶ 所示)。如您之前所见,一个数据包的流量通常是 ICMP 请求或 UDP,例如简单的 DNS 查询。几乎四分之一的流量包含每个流量五到八个数据包(如 ❸ 所示)。其余的流量在数据包数量上分布广泛。
每个流量的八位字节
摘要-详细报告的下一部分会告诉您每个流量中有多少个八位字节。
❶ 32 64 128 256 512 1280 2048 2816 3584 4352 5120 5888 6656 7424 8192
❷ .000 .070 .173 .129 .097 .208 .115 .029 .028 .016 .017 .023 .011 .009 .005
8960 9728 10496 11264 12032 12800 13568 14336 15104 15872 ❹ >15872
.004 .004 .003 .003 .003 .002 .002 .002 .002 .001 ❸ .043
如您所见 ❷,此文件中的所有流量都不只包含 32 个八位字节(如 ❶ 所示)。(记住,即使是 ping 数据包通常也是 64 字节。)流量的最常见大小为 513 到 1280 个八位字节,其中 0.208 大约代表 20% 的流量。尽管大流量很少见,但您可以看到 ❸ 中 0.043,或大约 4% 的流量,其大小超过 15,872 个八位字节(如 ❹ 所示)。
流量时间分布
摘要-详细报告的最后部分,流量时间分布,会告诉您流量持续多长时间(以毫秒为单位)。
❷ 10 50 100 200 500 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000
❶ .158 .100 .088 .084 .157 .085 .036 .019 .017 .010 .009 .007 .007 .010 .009
12000 14000 16000 18000 20000 22000 24000 26000 28000 30000 >30000
.014 .008 .006 .008 .007 .005 .003 .003 .004 .004 ❸ .141
如您所见 ❶,0.158,或大约 16%,的流量持续时间在 10 毫秒或更短(如 ❷ 所示)。查看数据表明,这是最常见的流量持续时间。在这个网络中,一般而言,短流量比长流量更常见:持续时间较长的流量在最后(如 ❸ 所示)突出。
你如何使用摘要-详细报告?
如果您收到有关您的网络行为异常的投诉,将今天的流量与上周或去年的流量进行比较,以快速查看异常。如果您发现网络问题期间流量的大小、持续时间或数量发生了变化,您知道某些东西发生了变化。根据这些特征进行过滤,以识别已更改的主机或连接。
修改默认报告
与 flow-nfilter 类似,您可以从命令行修改 flow-report 的行为。程序支持五个变量:TYPE、SORT、FIELDS、OPTIONS 和 RPTOPT。我将在本章后面用示例说明每个变量。现在,让我们简要地看看每个变量:
-
TYPE告诉flow-report要运行哪个报告。flow-report支持超过 70 种报告类型。本章的大部分内容是对我认为最有用的报告的讨论。flow-report的手册页包含完整的列表。 -
SORT控制数据显示顺序。您可以根据报告中的任何字段对大多数报告进行排序。 -
FIELDS允许您调整报告中显示的字段。 -
OPTIONS激活或停用各种报告范围功能。 -
RPTOPT提供了传递给报告格式化程序flow-rptfmt的选项。
要设置变量,使用 -v 和变量名。例如,要设置 TYPE 变量,请使用以下命令:
# `flow-cat * | flow-report -v TYPE=```*`yourtype`*``
I'll use variables throughout the rest of this section to modify reports and then explore the different report types.
Using Variables: Report Type
One question you might hear from an interested manager^([8]) is "What computer talks the most?" The report type ip-source-address displays how much traffic each host puts on the network.
# `flow-cat * | flow-report -v TYPE=ip-source-address`
...
# ['/usr/local/bin/flow-rptfmt', '-f', 'ascii']
ip-source-address 流量 八位字节 数据包数量 持续时间
192.0.2.37 12163 107898108 204514 159749392
158.43.128.72 16389 1962766 16711 49357139
192.0.2.4 54280 127877204 785592 831419980
198.6.1.1 7627 970898 7992 26371278
...
With this report you get a list of IP addresses and the number of flows, octets, and packets sent by that host, as well as the total duration of all flows to this host in milliseconds. The data in this report is presented, in no particular order, as a list of IP addresses and traffic measurements, which demonstrates that you must know exactly what you mean by "busiest host." Is it the host that sends the greatest amount of traffic (octets)? Is it the host involved in the greatest number of connections (flows)? Or is it the host that sends the greatest number of individual packets?
Using Variables: SORT
Scrolling through a long report in search of the host that sends the most traffic isn't terribly effective. Instead, use the SORT variable to tell flow-report how to order the data.
You can assign SORT the value of the name of any field in a report. However, the fields are not necessarily the same as the names of the columns. The report header contains the fields entry, which lists the valid fields in the report type in the order they appear in the report. Here's the header information on fields from the ip-source-address report:
# 字段: +key,+flows,+octets,+packets,+duration,+other
The actual report includes the columns ip-source-address, flows, octets, packets, and duration, as shown here:
IP 源地址 流量 字节 数据包 持续时间
192.0.2.4 54280 127877204 785592 831419980
...
Note that the list of fields starts with an entry named key and follows that with entries called flows, octets, packets, duration, and other. The actual report starts with a column called ip-source-address and follows that with the fields flows, octets, packets, and duration. flow-report calls the field it's reporting on the key. I ran the ip-source-address report, so the key is the ip-source-address field. (This report has no other column, despite its presence in the list of fields.)
To sort by a column in descending order, assign the SORT variable the field name with a leading plus sign. To sort by a column in ascending order, assign the SORT variable the field name with a leading minus sign.
I'm interested in the host that creates the greatest number of connections, or flows, so I'll assign SORT the value +flows to sort the data by flows in descending order, like so:
# `flow-cat * | flow-report -v TYPE=ip-source-address -v SORT=+flows`
...
# ['/usr/local/bin/flow-rptfmt', '-f', 'ascii']
IP 源地址 流量 字节 数据包 持续时间
❶ 192.0.2.4 54280 127877204 785592 831419980
158.43.128.72 16389 1962766 16711 49357139
192.0.2.37 12163 107898108 204514 159749392
198.6.1.5 8826 1425518 11339 24124445
192.0.2.36 8786 21773315 38616 44443605
198.6.1.1 7627 970898 7992 26371278
...
The host 192.0.2.4 (❶) has sent 54,280 flows, almost four times as many as the next highest host.
At first glance, it might appear that sorting by flows also sorts by bytes (octets) to a certain degree, but that's illusionary. Here I report on the same data sorted by octets:
# `flow-cat * | flow-report -v TYPE=ip-source-address -v SORT=+octets`
...
# ['/usr/local/bin/flow-rptfmt', '-f', 'ascii']
IP 源地址 流量 字节 数据包 持续时间
207.46.209.247 25 131391013 90275 2967322
192.0.2.4 54280 127877204 785592 831419980
192.0.2.37 12163 107898108 204514 159749392
192.0.2.7 116 72083511 55415 15057488
192.0.2.130 145 49604492 74852 36232749
192.0.2.8 88 48766466 36166 7181558
...
When you compare the list of hosts that send the greatest number of octets to the list of hosts that send the greatest number of flows, notice that four of the top six hosts on each list don't even appear in the other list!
^([8]) The quickest way to make your manager lose interest is to answer this question in appalling detail. This might seem cruel, but it's best for everyone involved.
Analyzing Individual Flows from Reports
Look back at the ip-source-address report from in Using Variables: SORT in Using Variables: Report Type. Notice how the host 207.46.209.247 used the most bandwidth, 131,391,013 octets. That's 131,391,013 divided by 1,024, which is about 128,312KB, or 125MB. The obvious question is "What did that host send in all those octets with but so few flows?"
To find out, use flow-nfilter to answer that question. Because this is a one-off query that probably won't be repeated, just configure the filter on the command line.
# `flow-cat * | flow-nfilter -F ip-src-addr -v ADDR=207.46.209.247 | flow-print`
源 IP 目的 IP 协议 源端口 目的端口 字节 数据包
207.46.209.247 192.0.2.4 ❶ 6 ❷ 80 51538 16499752 11018
207.46.209.247 192.0.2.4 6 80 51540 16104523 10756
207.46.209.247 192.0.2.4 6 80 53410 20798 17
...
Thanks to this report, you can see that this connection ran over TCP (❶) and that it came from port 80 to a high-numbered port (❷). This is obviously a response from a web server. In this case, the destination IP happens to be my main proxy server. I can search my proxy logs and probably identify this traffic more exactly.
Unfortunately, web traffic isn't quite that simple. People frequently browse and click through many pages on a website, perhaps downloading data from many different places on the site or maybe downloading a single large file. How can you know whether this data represents a single large download or a bunch of smaller requests? There's no way to be certain, but one way to check is to compare the connections coming from that address to the connections going to that address.
To do so, you can change the filter to check for flows going to 207.46.209.247. You'll need the start and stop times for each flow to see whether new connections are starting or whether each flow is an independent request. flow-print format 5 displays timing information with each flow, so I use that to display my filtered data. (I've removed several irrelevant fields, such as the protocol, interface, packets, and octets, from this example to make the output fit on the page.)
# `flow-cat * | flow-nfilter -F ip-dst-addr -v ADDR=207.46.209.247 | flow-print -f 5`
开始 时间 结束 时间 源 IP 地址 源端口 目的 IP 地址 目的端口
❶ 1201.11:58:00.409 1201.12:01:55.917 192.0.2.4 51538 207.46.209.247 80
❷ 1201.11:58:00.451 1201.12:02:05.769 192.0.2.4 51540 207.46.209.247 80
❸ 1201.12:03:00.506 1201.12:04:10.916 192.0.2.4 53410 207.46.209.247 80
1201.12:03:00.505 1201.12:04:16.805 192.0.2.4 53409 207.46.209.247 80
❹ 1201.12:08:00.457 1201.12:09:25.912 192.0.2.4 55190 207.46.209.247 80
1201.12:08:00.457 1201.12:09:26.775 192.0.2.4 55191 207.46.209.247 80
❺ 1201.12:13:00.519 1201.12:14:11.891 192.0.2.4 57581 207.46.209.247 80
1201.12:13:00.520 1201.12:16:30.907 192.0.2.4 57580 207.46.209.247 80
...
The first flow (❶) starts at 1201.11:58:00.409, or 11:58 am and .409 seconds, on December 1, and ends at 12:05:55.917. A second request at ❷ begins milliseconds later and ends at about the same time. These are clearly two separate HTTP requests.
What makes this output interesting is the timing of the other requests. Two more requests begin at ❸ exactly five minutes after the first two, and two more begin at ❹ five minutes after that. By viewing the requests rather than the responses to the requests, it becomes very obvious that something on your network is accessing this site (❺) every five minutes. People do not behave in such a mechanistic manner. The sensible assumption is that a piece of software is responsible for this traffic.
This report gives exact timestamps for when these repeating, high-bandwidth HTTP requests begin and end, which is all you need in order to find the site in your proxy logs. (In this particular case, this turned out to be clients downloading patches from Microsoft instead of using the corporate update server.)
Note
If you have no proxy server, you aren't logging Internet usage. You can do flow analysis on your internal network to identify the specific workstations that were making these requests and see what those workstations have in common, but that's all. If the activity is ongoing, use your packet sniffer to identify what site the workstations are trying to reach.
Other Report Customizations
Just as the SORT variable adjusts data display, other variables further change a report's format, allowing you to create a report that contains exactly the information you need, presented in the most usable manner. I'll modify the ip-source-address report I ran earlier this chapter to demonstrate exactly how each of these variables changes a report.
Choosing Fields
Perhaps you specifically want to know the number of bytes (or packets) sent by a host, and you don't care about the other information provided by a report. The FIELDS variable lets you select the columns to include in a report.
For example, the ip-source-address report includes five fields: address, flows, octets, packets, and duration. Say you want to remove the duration column from your report. To do so, give the FIELDS variable the value of the field you want to remove, with a leading minus sign, as shown here with -duration:
# `flow-cat * | flow-report -v TYPE=ip-source-address`
`-v SORT=+octets -v FIELDS=-duration`
...
IP 源地址 流量 字节 数据包
207.46.209.247 25 131391013 90275
192.0.2.4 54280 127877204 785592
192.0.2.37 12163 107898108 204514
...
To remove multiple FIELDS values, separate each with commas. Here I've removed everything except the IP address and the number of octets:
# `flow-cat * | flow-report -v TYPE=`
`ip-source-address -v SORT=+octets -v FIELDS=-duration,-packets,-flows`
...
IP 源地址 字节
207.46.209.247 131391013
192.0.2.4 127877204
192.0.2.37 107898108
...
If extraneous data confuses your audience, consider trimming unneeded fields.
Displaying Headers, Hostnames, and Percentages
The OPTIONS variable controls miscellaneous report settings. flow-report supports five options, but not all report types support all options, and not all options make sense for every report type. The effect of different options varies with the type of report being run. The report header shows the options used in a report.
# options: +percent-total,+header
-
The
headeroption tellsflow-reportto include the generic informational header consisting of the name of the report type, the time of the last flow in the data, and so on. You saw an example of a flow report header in Default Report in Default Report. -
The
xheaderoption tellsflow-reportto provide extra header information. Not all report types have extra header information. In some reports, the extra header information is identical to the regular header information. Try this option to see what it does with a given report type. -
With the
totalsoption,flow-reportincludes the total values of the information being reported on. Not all reports include this, because not all information can be totaled. (You cannot sensibly add IP addresses together, for example!) -
The
percent-totaloption provides the information as a percentage of the total rather than an absolute amount. For example, in thesource-ip-addressreport, the flows from a particular host would appear as a percentage of the total number of flows rather than the actual number of flows. -
Finally, the
namesoption tellsflow-reportto use names rather than numbers. This option makesflow-reportperform a DNS query for each IP address in the report, which makes reports with IP addresses run extremely slowly. Reports with a limited number of hosts can run reasonably quickly, however, and pulling information from static files such as /etc/protocols and /etc/services is very quick.
To remove options from an existing report, put a minus sign (-) before the option name in the OPTIONS variable. In the following example, I've removed all header information from the ip-source-address report and am presenting only the report data:
# `flow-cat * | flow-report -v TYPE=ip-source-address -v SORT=+octets -v`
❶ `OPTIONS=-header`
The minus sign before header at ❶ tells flow-report to remove this value from the list of options.
Adding options is a little more complicated. Once you start adding options, flow-report assumes that you will list all desired options. The default report includes the options header, xheader, and totals. To retain all of these and add the percent-total option, list them all on the command line, separated by commas, as shown here:
# `flow-cat * | flow-report -v TYPE=ip-source`
`-address -v SORT=+octets -v OPTIONS=+percent-total,+header,+xheader,+totals`
Note
If I were to include only the +percent-total option, flow-report would not use any other options even though they are the default.
Presenting Reports in HTML
flow-report formats its output through an external program, flow-rptfmt. Most of flow-rptfmt's features overlap flow-report functions, such as setting sorting order or choosing fields to display, but you can have flow-rptfmt create HTML with the -f html flag. Use the RPTOPT variable to pass commands to flow-rptfmt.
# `flow-cat * | flow-report -v TYPE=ip-source-address -v RPTOPT=-fhtml`
You'll consider flow-rptfmt further when I show how to create customized reports.
Useful Report Types
flow-report supports more than 70 types of reports and lets you analyze your traffic in more ways than you may have thought possible. In this section, I'll demonstrate the most commonly useful report types. Read the flow-report man page for the complete list.
Note
Many of these reports are most useful when presented in graphical format or when prepared on a filtered subset of data. You'll look at how to do both of these later in this chapter.
IP Address Reports
Many traffic analysis problems focus on individual IP addresses. You've already spent some quality time with the ip-source-address report. These reports work similarly, but they have their own unique characteristics.
Highest Data Exchange: ip-address
To report on all flows by host, use the ip-address report. This totals both the flows sent and the flows received by the host. Here, you look for the host that processed the largest number of octets on the network. You lose the data's bidirectional nature, but this report quickly identifies your most network-intensive host.
# `flow-cat * | flow-report -v TYPE=ip-address -v SORT=+octets`
ip-address flows octets packets duration
192.0.2.4 107785 995021734 1656178 1659809423
192.0.2.37 24294 347444011 456952 322712670
207.46.209.247 50 134705214 151227 5934644
...
Flows by Recipient: ip-destination-address
This is the opposite of the ip-source-address report I used as an example report throughout the beginning of this chapter. It reports on traffic by destination address.
# `flow-cat * | flow-report -v TYPE=ip-destination-address`
ip-destination-address flows octets packets duration
158.43.128.72 16478 1090268 16816 49357139
192.0.2.37 12131 239545903 252438 162963278
198.6.1.1 7630 588990 7997 26371278
...
In this example, the host 158.43.128.72 has received 16,478 flows in 1,090,268 octets. Lots of people transmitted data to this host. You don't know whether this data is the result of connections initiated by this host or whether many hosts are connecting to this host. To answer that, you have to look at the actual connections. Use flow-nfilter to trim your data down to show only the flows involving this host, and use flow-print to see the data.
Most Connected Source: ip-source-address-destination-count
Many worms scan networks trying to find vulnerable hosts. If you have a worm infection, you'll want to know which host sends traffic to the greatest number of other hosts on the network. The ip-source-address-destination-count report shows exactly this.
# `flow-cat * | flow-report -v TYPE=ip-source-address-destination-count`
ip-source-address ip-destination-address-count flows octets packets duration
❶ 192.0.2.37 ❷ 1298 12163 107898108 204514 159749392
158.43.128.72 5 16389 1962766 16711 49357139
192.0.2.4 2016 54280 127877204 785592 831419980
...
This report shows you that the host 192.0.2.37 (❶) sent flows to 1,298 (❷) other hosts, as well as the number of flows, octets, and packets of these connections.
Most Connected Destination: ip-destination-address-source-count
You can also count the number of sources that connect to each destination. This is similar to the previous report but will contain slightly different data. Some flows (such as broadcasts and some ICMP) go in only one direction, so you must consider destinations separately from sources.
# `flow-cat * | flow-report -v TYPE=ip-destination-address-source-count`
ip-destination-address ip-source-address-count flows octets packets duration
158.43.128.72 5 16478 1090268 16816 49357139
192.0.2.37 1303 12131 239545903 252438 162963278
198.6.1.1 2 7630 588990 7997 26371278
...
The ip-source-address-destination-count and ip-destination-address-source-count reports give additional insight into the key servers, resources, and users on your network, even when you don't have problems.
REPORTS THAT DON'T SORT BY EVERYTHING
Some reports don't offer the opportunity to sort by every field. For example, the two interconnectedness reports cannot sort by the number of hosts an address connects to. This is annoying, especially because this is precisely what you're interested in if you're running this report! On most flavors of Unix you can sort by a column by piping the output through sort -rnk columnnumber, as shown here:
flow-cat | flow-report | sort -rnk 2
Network Protocol and Port Reports
These reports identify the network ports used by TCP and UDP flows or, on a larger scale, just how much traffic is TCP, UDP, and other protocols.
Ports Used: ip-port
Forget about source and destination addresses. What TCP and UDP protocols are the most heavily used on your network? The ip-port report tells you.
# `flow-cat * | flow-report -v TYPE=ip-port -v SORT=+octets`
ip-port flows octets packets duration
❶ 80 ❹ 63344 877141857 1298560 1444603541
❷ 25 8903 361725472 475912 139074162
❸ 443 10379 136012764 346935 324609472
...
This looks suspiciously like assorted Internet services. Port 80 (❶) is regular web traffic; port 25 (❷) is email; and port 443 (❸) is encrypted web traffic. You can see how much traffic involves each of these ports, but it's a combination of inbound and outbound traffic. For example, you know that 63,344 (❹) flows either started or finished on port 80. These could be to a web server on the network or web client requests to servers off the network. To narrow this down, you really must filter the flows you examine, run a more specific report, or both. Still, this offers a fairly realistic answer to the question "How much of the traffic is web browsing or email?" especially if you use the +percent-total option.
Flow Origination: ip-source-port
To see the originating port of a flow, use the ip-source-port report. Here I'm sorting the ports in ascending order:
# `flow-cat * | flow-report -v TYPE=ip-source-port -v SORT=-key`
ip-source-port flows octets packets duration
❶ 0 215 4053775 23056 21289759
22 111 1281556 15044 4816416
25 4437 10489387 181655 69456345
49 19 3922 79 5135
...
Flows with a source port of zero (❶) are probably ICMP and certainly not TCP or UDP. It's best to filter your data to only TCP and UDP before running this report. Although ICMP flows use a destination port to represent the ICMP type and code, ICMP flows have no source port.
Source ports with low numbers, such as those in the previously shown report snippet, are almost certainly responses to services running on those ports. In a normal network, port 22 is SSH, port 25 is SMTP, and port 49 is TACACS.
Flow Termination: ip-destination-port
The report ip-destination-port identifies flow termination ports.
# `flow-cat * | flow-report -v TYPE=ip-destination-port -v SORT=-key`
ip-destination-port flows octets packets duration
0 91 3993212 22259 14707048
22 231 26563846 22155 5421745
25 4466 351236085 294257 69617817
49 19 6785 101 5135
...
These look an awful lot like the source ports. What gives? Because a flow is half of a TCP/IP connection, the destination port might be the destination for the data flowing from the server to the client. A report on the same data should show just roughly as many flows starting on a port as you terminate on that port. Sorting the report by port makes this very obvious.
Individual Connections: ip-source/destination-port
Part of the identifying information for a single TCP/IP connection is the source port and a destination port. The ip-source/destination-port report groups flows by common source and destination ports. Here, I'm reporting on port pairs and sorting them by the number of octets:
# `flow-cat * | flow-report -v TYPE=ip-source/destination-port -v SORT=+octets`
ip-source-port ip-destination-port flows octets packets duration
❶ 80 15193 3 62721604 43920 620243
❷ 4500 4500 115 57272960 101806 30176444
❸ 14592 25 2 28556024 19054 480319
...
The first connection at ❶ appears to be responses to a web request, coming from port 80 to a high-numbered port. Three separate flows used this combination of ports. Then at ❷ there is IPSec NAT-T traffic on port 4500 and then transmissions to the email server at ❸.
I find this report most useful after I prefilter the data to include only a pair of hosts, which gives me an idea of the traffic being exchanged between the two. You might also use this report to identify high-bandwidth connections and filter on those ports to identify the hosts involved, but if you're interested in the hosts exchanging the most traffic, the ip-address report is more suitable.
Network Protocols: ip-protocol
How much of your traffic is TCP, and how much is UDP? Do you have other protocols running on your network? The ip-protocol report breaks down the protocols that appear on your network. In this example, I'm using the +names option to have flow-report print the protocol name from /etc/protocols rather than using the protocol number. Looking up names in a static file is much faster than DNS resolution.
# `flow-cat * | flow-report -v TYPE=ip-protocol -v OPTIONS=+names`
ip-协议 流量 字节 数据包 持续时间
icmp 158 75123 965 6719987
tcp 83639 1516003823 2298691 1989109659
udp 76554 69321656 217741 296940177
esp 34 3820688 18720 8880078
vrrp 12 151708 3298 3491379
As you can see, clearly TCP and UDP are our most common protocols, but there is also an interesting amount of ESP traffic. ESP is one of the protocols used for IPSec VPNs.
REPORTS COMBINING ADDRESSES AND PORTS
flow-report also supports reports that provide source and destination addresses and ports together, in almost any combination. Read the flow-report manual page for the specific names of these reports. I find flow-print more useful for that type of analysis.
Traffic Size Reports
Has the number of large data transfers increased on your network over the past few days? If so, flow-report lets you dissect your traffic records and identify trends. These reports are most useful when graphed and compared to historical traffic patterns.
Packet Size: packet-size
How large are the packets crossing your network? You're probably familiar with the 1,500-byte limit on packet size, but how many packets actually reach that size? The packet-size report counts the packets of each size. Here I'm running this report and sorting the results by packet size:
# `flow-cat * | flow-report -v TYPE=packet-size -v SORT=+key`
数据包大小/流量 流量 字节 数据包 持续时间
1500 ❶ 5 ❷ 2776500 ❸ 1851 1406780
1499 2 14717980 9816 390603
1498 5 60253559 40207 999167
...
As you can see at ❶, 1,500-byte packets have been seen in five flows, containing a total of 2.7 million bytes (❷). You've seen 1851, (❸) of these 1,500-byte packets. Sorting by packets would identify the most and least common packet size.
Bytes per Flow: octets
How large are your individual flows? Do you have more large network transactions or small ones? To answer this, report on the bytes per flow with the octets report.
# `flow-cat * | flow-report -v TYPE=octets -v SORT=-key`
字节/流量 流量 字节 数据包 持续时间
46 ❶ 367 ❷16882 367 1214778
48 ❸ 59 2832 ❹ 59 272782
...
168 ❺ 496 83328 ❻ 1311 5819361
...
This network had 367 46-octet flows (❶), for a total of 16,882 (❷) octets.
In a small flow, the number of flows (❸) probably equals the number of packets (❹), and each of these tiny flows has only one packet. When flows contain more data, each flow (❺) contains multiple packets (❻).
Packets per Flow: packets
The number of packets in a flow offers an idea of what kind of transactions is most common on your network. The sample DNS queries you looked at in Chapter 1 had only one packet in each flow, while long-running FTP sessions might have thousands or millions of packets. The packets per flow report packets tells you how many flows have each number of packets, as shown here:
# `flow-cat * | flow-report -v TYPE=packets -v SORT=-key`
数据包/流量 流量 字节 数据包 持续时间
1 ❶ 74213 6978064 74213 19224735
2 3411 551388 6822 190544194
3 4764 2033952 14292 37130046
...
As you can see at ❶, this data contains 74,213 one-packet flows, carrying almost 7 million octets. (That sounds so much more impressive than 6.5MB, doesn't it?)
Traffic Speed Reports
I've had managers ask "How fast is the network?" so often that I've given up telling them that the question is meaningless. Saying that you have a gigabit Ethernet backbone sounds good, but it's like saying that your car's speedometer goes up to 120 miles per hour without mentioning that the engine starts making a sickly ratcheting cough at 40 miles per hour. Here are some ways to take a stab at answering that question in something approaching a meaningful way.
NETWORK SPEED CAVEATS
Remember, a long-running connection can pass traffic at different speeds through its lifetime. You've probably seen this yourself when downloading a CD or DVD image from the Internet. The connection might start off very quick, become slower partway through for any number of reasons, and accelerate again later. Flow records include only average speed information. For example, to determine how many packets a flow passed in a second, flow-report divides the number of seconds the flow lasted by the number of packets in the flow. This is good enough for most purposes, however, and it's certainly better than you'll get with anything short of packet capture.
Many of these reports are not terribly informative to the naked eye. When you're looking at a list of TCP ports that accepted connections, you can quickly say that, for example, ports 80 and 25 received 75 percent of your traffic. These reports are not so readily interpreted, though they do make good fodder for graphs. I've written these descriptions assuming you'll be feeding the results into a graphing program such as gnuplot or OpenOffice.org Calc. Those of you who can interpret these results without further processing can congratulate yourself on being either much smarter or much dumber than myself.
Counting Packets: pps
Another critical measure of network throughput is packets per second (pps). Many network vendors describe the limits of their equipment in packets per second. The pps report, much like the bps report, shows how many flows travel at the given number of packets per second.
# `flow-cat * | flow-report -v TYPE=pps -v SORT=+key`
pps/flow 流量 字节 数据包 持续时间
❶ 3000 1 231 ❷ 3 ❸ 1
1000 70 4192 70 70
833 1 403 5 6
...
Wow! One flow went at 3,000 packets per second (❶)? Yes, technically, but note that it contained only three packets (❷) and lasted for one millisecond (❸). Multiplying anything by a thousand exaggerates its impact.
Again, this report isn't terribly useful to the naked eye but can be interesting when graphed.
Traffic at a Given Time: linear-interpolated-flows-octets-packets
The linear-interpolated-flows-octets-packets report averages all the flows fed into it and lists how many flows, octets, and packets passed each second. I find this the most useful "speed" report.
# `flow-cat * | flow-report -v TYPE=linear-interpolated-flows-octets-packets`
秒数 流量 字节 数据包
1334981479 35.605553 35334.016293 96.820015
1334981480 63.780553 62865.828793 184.570015
1334981481 38.702116 69297.703533 192.235604
...
The first column gives the time, in Unix epochal seconds: 1334981479 is equivalent to Saturday, April 21, 2012, at 11 minutes and 19 seconds after midnight, EDT. Each row that follows is one second later. In this second, I passed 35.6 flows, 35334 octets, and 96.8 packets.
This report is ideal for answering many frequently asked questions, such as "How much traffic goes between our desktops and the domain controllers at remote sites?" Take the flow data from your internal connection, run it through flow-nfilter once to reduce it to traffic from your desktop address ranges, and then run it through again to trim that down to traffic with your remote domain controllers. Finally, feed the results into flow-report, and use the resulting report to generate graphable data.
A little creativity will give you data on things you never expected you could see. For example, TCP resets are a sign of something being not quite right; either a client is misconfigured, a server daemon has stopped working, or a TCP connection has become so scrambled that one side or the other says "Hang up, I'm done."
You can use flow-nfilter to strip your flows down to TCP resets. (One TCP reset is one packet.) Run this report with -v FIELDS=-octets,-flows to display only the number of TCP resets in a given second, and you'll then have graphable data on TCP resets on your network.
Note
Although the quality of a network administrator's work is difficult to measure, I suggest offering "before" and "after" pictures of TCP reset activity during your performance reviews.^([9])
Routing, Interfaces, and Next Hops
Flow records include information on which interfaces a packet uses. In simple cases, this information isn't terribly useful: If you have a router with one Internet connection and one Ethernet interface, you have a really good idea how packets flowed without any fancy network analysis. A router using BGP, with multiple Internet providers, will distribute outgoing traffic to all Internet providers based on its routing information. Most people use traceroute to identify which path the router takes to a particular destination. BGP routing is dynamic, however; the path a packet takes now might not be the path it took five minutes ago or during an outage. Routers that support NetFlow version 5 or newer include interface information with each flow, however, so you can retroactively identify the route a flow used. (Remember, software flow sensors, such as softflowd, do not have access to interface information.)
Interfaces and Flow Data
In Chapter 4, you filtered on router interfaces. Reporting on interfaces is the natural extension.
Remember, each router represents its interfaces with numbers. You might think of a router interface as Serial 0, but the router might call it Interface 8. A Cisco router might renumber its interfaces after a reboot, unless you use the snmp ifIndex persist option.
I'm using the router from Chapter 4 as a source of flow information. On this router, interfaces 1 and 2 are local Ethernet ports, and interfaces 7 and 8 are T1 circuits to two different Internet service providers.
The First Interface: input-interface
To see which interface a flow entered a router on, use the input-interface report. Here, I'm adding a filter to report on data only for a single router:
# `flow-cat * | flow-nfilter -F router1-exports | flow-report -v TYPE=input-interface`
输入接口 流量 字节 数据包 持续时间
1 22976 136933632 306843 58766984
2 320 182048 1307 3214392
7 4934 59690118 165408 46161632
8 1316 7386629 11142 7592624
Most of these flows start on interface 1, with the fewest on interface 2.
The Last Interface: output-interface
To show the interfaces that are being used to leave a router, use the output-interface report.
# `flow-cat * | flow-nfilter -F router1-exports | flow-report -v TYPE=output-interface`
输出接口 流量 字节 数据包 持续时间
❶ 0 1765 447958 5043 3599588
1 5057 66979701 175073 52900988
2 17545 20507633 56531 9440036
7 111 43079633 34710 8266712
8 5068 73177502 213343 41528308
The first thing I notice in this output is the sudden appearance of interface 0 at ❶. This is a list of valid router interfaces, and 0 isn't one of them. What gives?
These are flows that arrived at the router and never left. The appearance of interface 0 prompted me to more closely scrutinize my flow data, and I found flows that appeared to come from IP addresses reserved for internal, private use. Closer inspection of the firewall revealed several rules that allowed internal traffic to reach the Internet-facing network segment without address translation, but the router dropped all traffic from these internal-only RFC1918 addresses. I also found quite a few traffic streams from the public Internet that were sourced from these private IP addresses, but the router dropped them too, as I would expect.
The lesson to learn is, of course, that proper reporting will do nothing but make more work for you. But at least you'll be able to identify and fix problems before an outsider can use those problems against you.
The Throughput Matrix: input/output-interface
Putting the input/output-interface reports together into a matrix showing which traffic arrived on which interface can be illuminating. Use the input/output-interface report for this. Here, I'm sorting the output by the number of flows so you can easily tell which pairs of interfaces see the greatest number of connections.
# `flow-cat * | flow-nfilter -F router1-exports`
`| flow-report -v TYPE=input/output-interface -v SORT=+flows`
输入接口 输出接口 流量 字节 数据包 持续时间
❶ 1 ❷ 2 17539 20507195 56522 9438220
❸ 1 8 4801 73147574 212806 41001424
7 1 3888 59604956 164102 45390152
8 1 1169 7374745 10971 7510836
7 0 1040 84724 1297 769664
1 0 525 199230 2805 60628
2 8 267 29928 537 526884
8 0 147 11884 171 81788
1 7 111 ❹ 43079633 34710 8266712
2 0 53 152120 770 2687508
7 2 6 438 9 1816
The busiest connection is between interface 1 (FastEthernet0/0) and interface 2 (FastEthernet0/1), shown at ❶ and ❷. This might or might not make sense, depending on your network topology. In mine, it's expected. You then route traffic out one of the Internet circuits at ❸.
This report clearly indicates the difference between flows and bytes. As you can see at ❹, one of the connections with a relatively few flows is actually pushing a comparatively large amount of traffic.
Note the absence of flows between interfaces 7 and 8. This indicates traffic entering on one of the Internet circuits and leaving by the other. You would have become a transit provider, carrying Internet traffic from one network to another. This would happen if, say, you sold a T1 to a third party and they sent their traffic through you to the Internet. If you're not an Internet backbone, this would be a serious problem.
The Next Address: ip-next-hop-address
Reporting by interface gives you a good general idea of where traffic is going, and reporting by IP address offers a detailed view. For an intermediate view, use the ip-next-hop-address report. You do not need to filter this report by the router offering the flows, because the report doesn't confuse the results with interface numbers. This report effectively tells you where the network traffic is going, both for your local hosts and for your upstream providers. I've sorted this report by octets so that the highest-bandwidth next hops appear first.
# `flow-cat * | flow-report -v TYPE=ip-next-hop-address | -v SORT=+octets`
ip-next-hop-address 流量 字节 数据包 持续时间
❶ 192.0.2.4 2490 154742050 174836 31131852
❷ 95.116.11.45 5068 73177502 213343 41528308
192.0.2.37 5944 65552868 73357 13692932
❸ 12.119.119.161 111 43079633 34710 8266712
192.0.2.13 2370 21382159 21595 4996548
192.0.2.194 17545 20507633 56531 9440036
❹ 66.125.104.149 17534 20506982 56521 9447180
...
As you can see in this report at ❶, the most heavily used next hop is the proxy server. This isn't a great surprise.
The second most heavily used next hop isn't even an address on my network. It's the ISP's side of one of my T1 circuits, as shown at ❷. This hop represents traffic leaving my network. I also have IP addresses for the second (❸) and third ISPs (❹).
Where Traffic Comes from and How It Gets There: ip-source-address/output-interface
flow-report includes reports based on IP addresses and interfaces. Because these reports are so similar, I'll cover two in detail, and I'll let you figure out the rest.
The ip-source-address/output-interface report shows the source address of a flow and the interface the flow left the router on. If you filter your underlying flow data by an individual host of interest and run that data through this report, you'll get information on how much traffic this one host sent to each of your Internet circuits as well as information on how much data that host received from each remote host. In the following report, I'm filtering by the router exporting the flows to avoid interface number confusion and by the IP address of my main external NAT address:
# `flow-cat * | flow-nfilter -F router1-exports`
`| flow-nfilter -F ip-addr -v ADDR=192.0.2.4 | flow-report -v`
`TYPE=ip-source-address/output-interface`
ip-source-address 输出接口 流量 字节 数据包 持续时间
❶ 192.0.2.4 2 3553 422428 5849 1881348
❷ 192.0.2.4 8 324 3826147 69225 2851980
❸ 198.22.63.8 1 137 56475 762 915472
...
❹ 192.0.2.4 7 2 124 2 0
...
The first entry at ❶ gives the proxy server itself as a source address and shows that I sent many flows out interface 2. That's an Ethernet to another local network segment. You also see at ❷ that the proxy sent large amounts of traffic out interface 8, one of the Internet connections.
You'll see entries at ❸ for remote IP addresses that send a comparatively small number of flows.
The surprising entry here is at ❹ where the proxy server sends a really small amount of traffic out interface 7, the other Internet circuit. Measurements show that this other circuit is consistently heavily used. Whatever is using this circuit isn't the main proxy server, however. I could identify the traffic going out over this circuit by removing the filter on the main proxy server and adding a filter for interface 7. I'll do that with a different report.
Where Traffic Goes, and How It Gets There: ip-destination-address/input-interface
After viewing the results of the previous report, I'm curious about what hosts exchange traffic over interface 7. In Chapter 4, I created a filter that passed all traffic crossing interface 7. You'll use that filter on traffic from this router together with a flow report to see what's happening. Rather than reporting on the source address and the output interface, you'll use ip-destination-address/input-interface to see where traffic arriving on a particular interface is going. The resulting command line might be long enough to scare small children, but it will answer the question.
# `flow-cat * | flow-nfilter -F router1-exports`
`| flow-nfilter -F interface7 | flow-report -v TYPE=ip-dest`
`ination-address/input-interface -v SORT=+octets`
ip-source-address 输入接口 流量 字节 数据包 持续时间
192.0.2.7 7 2 27347244 22122 3601016
69.147.97.45 1 2 19246168 12853 232400
192.0.2.8 7 2 15442834 11779 3600988
76.122.146.90 1 2 14113638 56214 3601884
...
Remember, I designed the filter interface7 so that it matched traffic either entering or leaving over interface 7. That's why this report includes both output interfaces 1 and 7.
Two local hosts, both web servers, receive most of the traffic sent to you over this router interface. More investigation shows that the Internet provider for this line has good connectivity to home Internet providers, such as Comcast and AT&T. The other provider has better connectivity to business customers. (How do you know what kind of connectivity your providers have? You can extract this information from the BGP information in flow records.)
Other Address and Interface Reports
Flow-report includes two more reports for interfaces and addresses, ip-source-address/input-interface and ip-destination-address/output-interface. After the previous two examples, you should have no trouble using or interpreting these reports.
Reporting Sensor Output
If you have multiple sensors feeding a single collector, you might want to know how much data each sensor transmits. Use the ip-exporter-address report to find that out.
# `flow-cat * | flow-report -v TYPE=ip-exporter-address`
ip-exporter-address 流量 字节 数据包 持续时间
192.0.2.3 29546 204192427 484700 115735632
192.0.2.12 36750 202920788 231118 39230288
As you can see in this report, records from the first router included fewer flows but more octets than those from the second router. Your results will vary depending on the throughput of each of your routers, the kind of traffic they carry, and their sampling rate.
BGP Reports
Flow records exported from BGP-speaking hardware include Autonomous System (AS) information. Reporting on this information tells you which remote networks you are communicating with and even how you reached those networks. If your network does not use BGP, these report types are of no use to you, and you can skip the rest of this chapter.
Flow-tools includes many reports and tools of interest to transit providers, but few if any readers of this book are transit providers. BGP-using readnsers are probably clients of multiple ISPs and use multiple providers for redundancy. I'll cover flow BGP information from the BGP user's perspective. Transit providers reading this book^([10]) are encouraged to read the flow-report manual page for a complete list of reports involving AS numbers.
Using AS Information
What possible use can this type of AS information be for a network engineer? Knowing who you exchange traffic with might have little impact on day-to-day troubleshooting, but it has a great impact on who you purchase bandwidth from.
When the time comes to choose Internet providers, run reports to see who you consistently exchange the most traffic with. If you know that you consistently need good connectivity to three particular remote networks, use them as bullet points in your negotiations with providers. If you don't make bandwidth purchasing decisions, provide the decision maker with this information. The statement "40 percent of our Internet traffic goes to these three companies" is much more authoritative than "I worked with company X before, and they were pretty good."
Traffic's Network of Origin: source-as
The source-as report identifies the AS where flows originated. I'll sort this report by octets, because that's how I pay for bandwidth.
# `flow-cat * | flow-nfilter -F router1-exports`
`| flow-report -v TYPE=source-as -v SORT=+octets`
源 AS 流量 字节 数据包 持续时间
❶ 0 23024 137077373 307572 61361020
❷ 14779 2 19246168 12853 232400
33668 136 15664027 64345 14486504
21502 2 5087464 3450 47692
...
The invalid AS 0 appears first at ❶. When traffic originates or terminates locally, flow sensors do not record an AS number for the local end of that traffic, which means that your local AS number will never appear in a flow report. The source AS of traffic you transmit shows up as 0, and the destination address of traffic you receive is also shown as 0. The only time you will see both a source and a destination AS number in a flow record is if the exporter is a transit provider, such as an Internet backbone. Traffic coming from AS 0 is the total of all traffic sourced by your network and transmitted to other networks. You might want to filter out all flows with a source AS of 0 from your data before running the report to remove the information about the data that your network transmits.
In the hour shown in the earlier report, the largest amount of traffic originated from AS 14779 (Inktomi/Yahoo!, shown at ❷), but it included only two flows. I suspect that if you were to filter this same data on AS 14779 and run flow-print against it, you'd see that someone had downloaded a file, and I would further guess that the proxy logs would show that someone needed printer software. You can repeat this exercise for each of the AS numbers in the list.
Destination Network: destination-as
To see where you're sending traffic to, use the destination-as report. For a slightly different view of traffic, sort by the number of flows.
# `flow-cat * | flow-nfilter -F router1-exports`
`| flow-report -v TYPE=destination-as -v SORT=+flows`
目的地 AS 流量 字节 数据包 持续时间
❶ 702 11834 767610 11869 23248
❷ 0 6828 67428097 180125 56502392
❸ 701 4154 459973 6372 1893152
3209 397 553003 9751 1220164
...
As you can see at ❶, you sent more flows to AS 702 than you received from everybody else combined (shown at ❷). Also note at ❸ that AS 701 belongs to the same organization as AS 702, but flow-report does not aggregate them. Different autonomous systems within one organization almost certainly have slightly different routing policies, despite the best efforts of their owner to coordinate their technical teams.
BGP Reports and Friendly Names
The BGP reports can use friendly names, which will save you the trouble of looking up the owner of interesting AS numbers. Although whois is a fast command-line tool for checking the ownership of AS numbers and you can look up AS information on any number of registry websites, none of these interfaces is suitable for automation. flow-tools gets around this by keeping a static list of AS assignments in the file asn.sym. Registries are continuously assigning and revoking AS numbers, however, so the list included with flow-tools will quickly become obsolete. To get the best information on AS names, you must update flow-tools' list of AS numbers.
To update the list of AS numbers, first download the latest list of ARIN assignments from ftp://ftp.arin.net/info/asn.txt, and save it on your analysis server.
Flow-tools includes gasn, a small script to strip out all of ARIN's comments and instructions and convert ARIN's list to a format it understands. The standard flow-tools installation process doesn't install this rarely used program in one of the regular system program directories, but you can probably find it under /usr/local/flow-tools/share/flow-tools if you installed from source. Use locate gasn to find the program if you installed from an operating system package.
Here, you feed ARIN's asn.txt in the current directory to the gasn script located in /usr/local/flow-tools/share/gasn and produce a new file, newasn.sym:
# `cat asn.txt | perl /usr/local/share/flow-tools/gasn > newasn.sym`
Take a look at your newasn.sym file. The contents should resemble these:
0 IANA-RSVD-0
1 LVLT-1
2 DCN-AS
3 MIT-GATEWAYS
...
As of this writing, this file contains more than 64,000 AS numbers, each on its own line.
Your system should already have an existing asn.sym file, possibly in /usr/local/etc/flow-tools/ or /usr/local/flow-tools/etc/sym/. Replace that file with your new file. When you add the +names option to flow-report, you should see the current AS names.
# `flow-cat * | flow-nfilter -F router1-exports`
`| flow-report -v TYPE=source-as -v SORT=+octets -v OPTIONS=+names`
源 AS 流量 字节 数据包 持续时间
IANA-RSVD-0 23024 137077373 307572 61361020
INKTOMI-LAWSON 2 19246168 12853 232400
MICROSOFT-CORP---MSN-AS-BLOCK 64 4669359 3259 106792
GOOGLE 130 4052114 3184 616152
...
Not all AS numbers have sensible names, especially those that are acronyms or words in foreign languages, but you can easily pick out some of the obvious ones and identify the others with whois.
^([9]) Remember that a certain level of TCP reset activity is normal, and much of it is caused by buggy or graceless software. Do not let your boss give you a goal of "zero TCP resets" during your performance review.
^([10]) Both of you.
Customizing Reports
I use command-line reports for occasional analysis on an ad hoc basis, such as when I'm trying to find patterns in problematic traffic. If you're going to regularly use a report with a long command line, I recommend creating a customized report. Writing truly custom detailed reports of the type I've been demonstrating requires programming, but flow-report lets you highly customize existing reports.
The stat.cfg file contains flow report definitions. You'll probably find this file in /usr/local/flow-tools/etc/cfg or /usr/local/etc/flow-tools, depending on how you installed flow-tools. The only report that comes in stat.cfg is the default report. Don't touch it; it's what makes the various command-line reports function. Add your custom changes below it.
Setting variables on the command line does not work in customized reports because the reason to customize a report is to avoid typing all those command-line variables. You can create a report that will accept command-line modifications, but to do so, you'll need to understand how to write basic reports first. To create such a report, study the default report in stat.cfg.
Custom Report: Reset-Only Flows
I frequently use flow-report to create graphable data on flows that contain only TCP resets. These flows can indicate misconfigured software, network equipment, or general system cussedness. Some of the best graphable data comes from the liner-interpolated-flow-octets-packets report. Let's create such a report. My goal is to be able to run the report very simply, like this:
# `flow-cat * | flow-report -S resets-only`
Use -S to tell flow-report that you're running a customized report. The new report will be named resets-only.
A minimal report in stat.cfg looks like this:
❶ stat-report 数据包统计
❷ type 线性插值流量字节数据包
❸ 输出
❹ stat-definition resets-only
报告数据包
Much like a flow-nfilter filter, a customized flow report has two main components: the stat-report and the stat-definition. The stat-report at ❶ is somewhat like a filtering primitive. This customized stat-report is called packets, for reasons that will become clear later.
The stat-report needs to know what type of flow-report it is based on, as shown at ❷. The resets-only report starts life as the linear-interpolated-flows-octets-packets report. At ❸ we tell the resets-only report to produce output.
The stat-definition at ❹ lets you aggregate multiple stat-reports into a single report. This definition includes only a single report, named resets. Even with this minimal definition, you can already run the resets-only report. The resulting numbers will be identical to setting TYPE=linear-interpolated-flows-octets-packets on the command line even though it appears slightly different.
# `flow-cat * | flow-report -S resets-only`
# recn: unix-秒*,flows,octets,packets
1228150499,35.605553,35334.016293,96.820015
1228150500,63.780553,62865.828793,184.570015
1228150501,38.702116,69297.703533,192.235604
...
The first thing you'll notice in the previous report is that flow-report creates comma-separated value (CSV) reports by default. This is perfectly fine if you're going to feed the results to a graphing program, but CSV data gives me a headache when I have to read it. A graphing program can read tab-delimited data just as easily as CSV, so let's make the report produce human-friendly output.
Report Format and Output
flow-report uses the external program flow-rptfmt to improve the output's appearance. Let's direct the output into flow-rptfmt.
stat-report 数据包统计
type 线性插值流量字节数据包
输出
❶ 路径 |/usr/local/bin/flow-rptfmt
The path variable at ❶ tells flow-report where to send the output. By using a path that starts with a pipe symbol (|), you tell flow-report to feed its output to a program, just like a pipe on the command line. Everything after the pipe is run as a command. Here I'm using the standard report formatting software, flow-rptfmt. Adding a formatting program to the report produces this output:
# ['/usr/local/bin/flow-rptfmt']
unix-秒 流量 字节 数据包
1228150499 35.605553 35334.016293 96.820015
1228150500 63.780553 62865.828793 184.570015
1228150501 38.702116 69297.703533 192.235604
...
You'll learn more about using flow-rptfmt and other output options in Customizing Report Appearance in Customizing Report Appearance.
Removing Columns
You're interested in counting the number of TCP resets that occur over time. (One TCP reset is one packet.) The octets and packets columns are irrelevant, so remove them.
stat-report 数据包统计
type 线性插值流量字节数据包
输出
❶ 字段 -字节,-流量
路径 |/usr/local/bin/flow-rptfmt
This works exactly like removing fields on the command line. The fields header at ❶ tells flow-report which columns to remove. Removing the octets and flows fields from this report gives you output much like the output shown next, and you now see only the data of interest:
# ['/usr/local/bin/flow-rptfmt']
unix-秒 数据包
1228150499 96.820015
1228150500 184.570015
1228150501 192.235604
...
Applying Filters to Reports
The report lists times and the number of packets, so you're headed in the right direction. But it's listing the total number of packets in the flow file, not just the TCP resets. You need to add a filter to strip away everything except the data you're interested in. You could use a filter on the command line, of course, but the purpose of a customized report is to reduce the amount of typing you do.
flow-report lets you add a filter in either the stat-report or the stat-definition. I define my filter in the stat-definition. Recall from Chapter 4 that you configured the rst-only filter to pass only TCP resets.
stat-definition reset-only
过滤器 rst-only
报告数据包
The report output now looks like this:
unix-秒 数据包
1228150595 0.068702
1228150596 0.068702
1228150597 0.068702
...
This network has a low number of TCP resets, but if you page through the results, you'll see peaks and valleys of reset-only flows. You'll use this data, among others, to create graphs in Chapter 8.
Combining stat-reports and stat-definitions
If you can use filters in either a stat-report or a stat-definition, why did I put the filter in my stat-definition?
Look at the packets stat-report. I wrote it to display reset-only TCP flows, but it is really just a linearly interpolated packet count. You can use this same stat-report elsewhere to create customized reports on data filtered differently. For example, if you had a filter to show all your SYN-only flows, you could use the packets stat-report to create data for both.
stat-definition reset-only
过滤器 rst-only
报告数据包
stat-definition syn-only
过滤器 syn-only
报告数据包
Both the reset-only and syn-only reports format and present their results identically. The only difference is the filter applied to create each report.
More Report Customizations
Any customization you can perform on the command line will also work in a customized report, but the configuration file supports additional features as well.
Reversing Sampling
Some flow sensors sample flows only, sending just a fraction of their data to the flow collector (see Chapter 2). This is better than having no flow data but can confuse reporting. To improve this situation, you can tell flow-report to scale up its output to compensate for sampling. For example, if your router samples at a rate of 1:10, you can scale up the output by a factor of 10 to get traffic volumes roughly comparable to the original. The report here scales the source and destination IP addresses:
stat-report 子网统计
type ip-source/destination-address
❶ 缩放 10
输出
路径 |/usr/local/bin/flow-rptfmt
stat-definition 子网定义
报告子网
The scale keyword at ❶ defines a scaling multiplier. Take a look at the output from this report:
# `flow-cat * | flow-report -S subnets`
# ['/usr/local/bin/flow-rptfmt']
IP 源地址 IP 目的地址 流量 字节 数据包 持续时间
192.0.2.37 158.43.128.72 8702 5760730 88840 30096122
158.43.128.72 192.0.2.37 8649 10405130 88280 30096122
192.0.2.4 198.6.1.1 7625 5886410 79920 26370707
...
I've copied this report to subnets-unscaled and removed the scale command. Let's compare the output.
# `flow-cat * | flow-report -S subnets-unscaled`
# ['/usr/local/bin/flow-rptfmt']
IP 源地址 IP 目的地址 流量 字节 数据包 持续时间
192.0.2.37 158.43.128.72 8702 576073 8884 30096122
158.43.128.72 192.0.2.37 8649 1040513 8828 30096122
192.0.2.4 198.6.1.1 7625 588641 7992 26370707
...
The source and destination addresses are unchanged, as is the number of flows, but the octet and packet counts have increased tenfold in the scaled report. This gives you a mostly accurate view of the amount of traffic passing through your network. Although you're still entirely missing data on some flows, this is about as close to reality as you can get from sampled data.
Filters in stat-report Statements
To use a filter in a stat-report statement, you must place it before the output definition. For example, the following filter statement applies the specified filter to your data before reporting:
stat-report 子网统计
type ip-source/destination-address
`filter` 网络流量
输出
路径 |/usr/local/bin/flow-rptfmt
Reporting by BGP Routing
Perhaps you're interested in internetwork connectivity rather than connectivity between individual IP addresses. If your flow records include BGP information, you can have flow-report generate reports using network block data. To do so, set the ip-source-address-format and ip-destination-address-format options to prefix-len, and flow-report will print the netmask with each entry.
stat-report 子网统计
输入 IP 源/目的地址
❶ IP 源地址格式 前缀长度
❷ IP 目的地址格式 前缀长度
输出
路径 |/usr/local/bin/flow-rptfmt
Here you've told flow-report to include the netmask in the source (❶) and destination (❷) addresses. The report now looks like this:
IP 源地址 IP 目的地址 流量 字节 数据包 持续时间
63.125.104.150/12 87.169.213.77/10 9 1008 18 23760
❶ 192.0.2.37/25 158.43.128.72/16 8233 537169 8233 4
192.0.2.4/25 ❷ 198.6.1.1/16 6634 485854 6658 168412
...
You can see at ❶ that 192.0.2.37 is routed as a /25 network. Although a /25 is too small to be announced on the public Internet, these addresses are local. The router had better know the netmask of directly attached networks! You also see that, for example, the address 198.6.1.1 at ❷ is announced as a /16.
To have flow-report aggregate data by network, set the address format to prefix-mask. Here's the same report on the same data, using the prefix-mask format:
IP 源地址 IP 目的地址 流量 字节 数据包 持续时间
❶ 63.112/12 87.128/10 15 1792 32 58384
❷ 192.0.2/25 158.43/16 23663 1532256 23707 17372
192.0.2/25 198.6/16 8299 915307 12698 3711276
...
Now you no longer see individual IP addresses. Instead, you see source address blocks as they are routed. You're sending traffic from some addresses inside the 63.112/12 range (❶) to addresses inside 87.128/10. flow-report has aggregated all the individual connections from one block to another.
Look at the second line of each of these reports. The first report shows that you sent 8,233 flows from the address 192.0.2.37 to the address 158.43.128.72. The report with the address mask set says that you sent 23,663 flows (❷) from addresses inside the block 192.0.2/25 to addresses inside 158.43/16. This line on the second report includes all the flows from the entry you checked in the first report, plus other flows that fit within those address blocks. They've been aggregated.
Customizing Report Appearance
flow-report supports many options for customizing presentation. Use these options in the stat-report definition only beneath the word output. Using them earlier will generate an error.
flow-rptfmt Options
Remember, setting path to a pipe followed by a program name tells flow-report to feed its output into that program. Everything after the pipe is executed as a regular shell command. This means you can do things such as redirect the output to a file.
路径 |/usr/local/bin/flow-rptfmt > /tmp/resets.txt
The previous line would have the report appear in the file /tmp/resets.txt rather than on the screen.
If you prefer, flow-rptfmt can produce a very simple HTML table of its output by adding the -f html arguments to activate this function, as shown next. ( You'll probably want to redirect the output to a file under your web server's root directory.)
路径 |/usr/local/bin/flow-rptfmt -f html > /var/www/resets/today.html
Of course, dumping regularly produced reports to a single file probably isn't useful. What you really need is a way to send the output to a file based on timing information.
Dump CSV to a File
Although flow-rptfmt is the standard tool for formatting reports, you might decide that the plain-text CSV works better for some purposes, such as for automated graph creation. If you set path to a filename, flow-report will dump raw CSV text straight to that file, which is most useful if you automatically process the data.
路径 /tmp/reset.csv
Using Time to Direct Output
A stat-report definition can create and use timing information when saving CSV files using the time option and special characters in the path setting.
Before using this definition, decide which time you want flow-report to use. Do you want to use the current time or the time in the flow files? If the time in the flow files, do you want the time when the flows begin or end? Control this with the time option using one of four different time values: now (the time when the report is run), start (the time the first flow begins), end (the time the last flow ends), or mid (the average of the start and end times, the default). For most uses, the default is fine.
The path value can accept variables from the strftime library. Table 5-1 lists the most common ones. If you need a time representation that isn't listed in this table, such as the day of the year, the day of the week as a numerical value, or the current time zone as expressed as minutes offset from universal time, read the manual page.
Table 5-1. Some strftime Variables for flow-report
| Variable | Replaced with |
|---|---|
%a |
Abbreviated day name (Mon, Tue, and so on) |
%b |
Abbreviated month name (Jan, Feb, and so on) |
%d |
Day of the month as a number (131) |
%H |
Hour as per 24-hour clock (00–23) |
%M |
Minutes (0–59) |
%m |
Month (1–12) |
%Y |
Four-digit year (0–9999) |
%y |
Two-digit year (00–99) |
flow-report can use the strftime variable values to direct output. For example, suppose you want to have the report output directed into a file with a name based on the time, in a directory hierarchy based on the year, month, and day. Use the strftime variables to name the file and to choose a directory to place the file, as shown here:
stat-report 子网
类型 ip-source/destination-address
输出
❶ 时间结束
❷ 路径 /tmp/%Y/%m/%d/%H/%M-report.csv
This report uses the time the last flow ends (❶). As shown at ❷, the results will appear in a file under a directory named for the year, month, day, and hour, and they use the last time in the file for the filename. For example, if I'm reporting on flow data from December 1, 2011, between 8 am and 8:59 am, the results would appear in the directory /tmp/2011/12/01/08.
Note
Although flow-report will expand strftime variables and hand the correct numbers to flow-rptfmt, flow-rptfmt cannot create missing directories.
The following report places HTML reports in a directory under the web root, using filenames based on the year, month, day, and hour of the data you're reporting on:
stat-report 子网
类型 ip-source/destination-address
输出
时间中间
路径 |flow-rptfmt -f html > /var/www/reports/report-%Y-%m-%d-%H-report.html
Set Sorting Order
Use the sort output option to control which column the report sorts on. This works the same as if you changed sorting on the command line. Use any column name in the report as the value for sort. A leading plus sign says start with the largest value and go down; a leading minus sign means start with the smallest and go up. The following example stat-report tells you what remote address ranges your network communicates with most because you list the highest traffic networks first by sorting on octets.
stat-report 子网
类型 ip-source/destination-address
ip-source-address-format 前缀长度
ip-destination-address-format 前缀长度
输出
`sort +octets`
路径 |flow-rptfmt
Cropping Output
Flow reports can run to hundreds or thousands of lines. Often you don't want the entire report and instead want merely the first entries, whether that's the first five or the first 500, but there's no sense in creating the 50,000-line report just to get those few entries. The records option gives the maximum number of results to show. Here, I'm adding a records entry to the previous report:
输出
`records 5`
排序 +字节数
路径 |flow-rptfmt
The report is no longer a list of all the networks you communicate with. Instead, it's the top five networks you communicate with.
Other Output Options
You might or might not want header information, percentages, and so on, in your customized report. Control these with the options keyword. (I discussed these options in Displaying Headers, Hostnames, and Percentages in Displaying Headers, Hostnames, and Percentages.) Here I'm turning off the informational headers:
输出
`options +header`
路径 |flow-rptfmt
Alternate Configuration Files
As you proceed, you might find yourself with an increasing number of customized reports used by more and more people. Reports, like filters, will not work if the configuration file is not parseable. As more people and processes run reports, you might find it difficult to develop new reports without annoying other system users or interrupting scheduled jobs. If so, tell flow-report to use a different configuration file than the default with the -s flag.
# `flow-report -s` ``*`test-stat.cfg`*`` `-S` ``*`newreport`*``
在配置文件的副本上创建、编辑和删除报告。当你的更改按预期工作后,只需将你的新配置复制到旧配置上。除非你更改了他们正在使用的报告,否则用户不会注意到。
现在你可以根据自己的喜好报告流量,你将创建图形报告,甚至在第六章(ch06.html "第六章。PERL、FLOWSCAN 和 CFLOW.PM")中编写自己的流量分析软件。
第六章。PERL、FLOWSCAN 和 CFLOW.PM

欢迎来到 flow-tools 实现中最麻烦的部分:Perl 模块。Perl 因其快速创建报告工具和网页界面而受到欢迎。最用户友好的流量报告工具之一,FlowScan,是基于 Perl 构建的,但不幸的是,用于处理流量文件的 Perl 模块 Cflow.pm 安装起来非常困难。这并不是因为 Perl,而是因为流量收集器在磁盘上的存储格式各不相同。你的 Cflow.pm 安装必须知道如何读取 flow-tools 流量文件。
Cflow.pm 以已废弃的流量收集器 cflowd 命名。当 cflowd 项目关闭时,cflowd 的作者建议迁移到 flow-tools。Cflow.pm 被修改以包含对 flow-tools 的可选支持。许多邮件列表存档消息和大量文档都提到了 cflowd 和 Cflow.pm,并且不一定区分两者。你需要 Cflow.pm,而不是 cflowd。
安装 Cflow.pm
历史上,正确安装 Cflow.pm 一直是任何流量分析实现中最困难且令人烦恼的部分。网络搜索会发现各种文章和邮件列表存档讨论 Cflow.pm 安装问题,包括作者的一系列文章。新的 flow-tools 版本为安装 Cflow.pm 提供了特定的过程。使用推荐的过程,并在安装后立即测试你的 Cflow.pm。如果你的 Cflow.pm 安装没有给出合理的结果,请不要继续进行。
测试 Cflow.pm
Cflow.pm 套件包括一个用于访问流量文件的命令行工具,flowdumper。它不如 flow-tools 中包含的工具强大或灵活,但它确实测试 Cflow.pm。如果 flowdumper 正确打印了你的流量文件内容,那么你的 Cflow.pm 安装正在正常工作。只需运行 flowdumper -s,并给它一个流量文件的名称。
# `flowdumper -s ft-v05.2011-12-14*`
2011/12/16 23:59:42 69.134.229.81.51459 -> 192.0.2.37.443 6(PUSH|ACK) 1 81
2011/12/16 23:59:43 192.0.2.4.10690 -> 198.6.1.1.53 17 1 81
2011/12/16 23:59:43 192.0.2.37.443 -> 69.134.229.81.51459 6(ACK) 1 40
...
-s 参数告诉 flowdumper 在一行中打印每个流量的摘要。每一行代表一个流量。你会看到源地址和目标地址以及端口、协议号、TCP 标志、数据包数量和八位字节数量。
如果你的 Cflow.pm 安装有误,flowdumper 会静默返回或返回错误。在你解决任何错误之前,你不能继续使用 Perl 模块或 FlowScan。
失败隐患在此
正确安装 Cflow.pm 似乎是流量管理项目失败的最常见原因。在 flowdumper 给出正确答案之前,不要继续使用任何使用 Cflow.pm 的软件。你已经收到警告。
从操作系统包安装
一些操作系统供应商包括可能包含 flow-tools 支持的 Cflow.pm 软件包。安装该软件包,并测试 flowdumper。如果它不起作用,在继续之前先卸载该软件包。
从源安装
从 net.doit.wisc.edu/~plonka/Cflow/ 获取 Cflow.pm 源代码,Cflow-1.053.tar.gz,并提取它。但是不要遵循 Cflow.pm 源代码中包含的构建说明。自从 Cflow.pm 发布以来,Flow-tools 已经发生了变化,要构建它请使用 flow-tools 的 contrib/README 文件中的说明。
进入提取的 Cflow.pm 源代码并运行
# `perl Makefile.PL CCFLAGS='-DOSU' LIBS='-lft'`
# `make`
# `make install`
立即测试 flowdumper。如果它不起作用,请继续下一节。
使用大锤从源代码安装
如果你的默认源安装失败,这应该会起作用。(Unix 和 Perl 纯粹主义者可能会在道德上表示愤怒,他们欢迎修复真正的问题。)
在 Cflow-1.053 源代码目录中,使用文本编辑器打开 Makefile.PL 文件。找到以下代码段:
sub find_flow_tools {
my($ver, $dir);
my($libdir, $incdir);
❶ if (-f '../../lib/libft.a') {
...
❶ 对 libft.a 的引用是所有麻烦的源头。如果所有其他方法都失败了,请将 libft.a 的路径硬编码。我的测试系统有 /usr/local/lib/libft.a,所以我将更改此源代码如下:
if (-f '/usr/local/lib/libft.a') {
然后按照前面 从源代码安装 部分所示构建和安装 Cflow.pm。现在 flowdumper 将显示数据。
如果这些方法对你都不起作用,请将你的问题的完整描述发送到 flow-tools 邮件列表,包括失败的构建输出。
flowdumper 和完整流量信息
虽然 flowdumper 通常不如 flow-print 有用,但它有一些独特的功能。你已经使用了摘要功能(-s)来测试 Cflow.pm。(flowdumper 也可以在命令行接受 Perl 指令,但如果你足够熟练地使用 Perl 来做这件事,你可以阅读 flowdumper 的手册页面。)
如果你没有使用摘要功能,flowdumper 会打印出每个流量文件包含的所有信息。
# `flowdumper ft-*`
FLOW
index: 0xc7ffff
❶ router: 192.0.2.12
❷ src IP: 158.43.128.72
dst IP: 192.0.2.37
input ifIndex: 9
output ifIndex: 1
src port: 53
dst port: 34095
pkts: 1
bytes: 130
❸ IP nexthop: 192.0.2.37
start time: Sat Dec 31 23:54:42 2011
end time: Sat Dec 31 23:54:42 2011
protocol: 17
tos: 0x0
❹ src AS: 702
dst AS: 0
src masklen: 16
dst masklen: 25
TCP flags: 0x0
engine type: 0
engine id: 0
...
你之前已经看到了大部分的流量信息,但这里有趣的是 flowdumper 显示了流量记录中的所有内容,包括在大多数环境中无关的数据字段。你会看到传感器地址(❶)、源地址和目标地址(❷)等等。你还会看到传感器正在导出诸如下一跳数据(❸)、BGP 路由数据(❹)等信息。尽管你通常不会想要尝试使用完整的 flowdumper 输出进行日常管理,但它让你验证你的系统是否收集了你认为应该收集的所有数据。然而,对于日常报告来说,更有用的系统是 FlowScan。
FlowScan 和 CUFlow
尽管第五章中展示的基于文本的流量报告显然很有用,即使是非技术人员也容易理解流量的视觉表示。第七章和第八章展示了任意数据的绘图,但很多时候绘制非任意数据就足够了。每个网络管理员都已经对他们的网络中最常见的流量有相当好的了解。例如,如果你运行一个 Web 农场,你可能更关心 HTTP 和 HTTPS 流量,而不是其他服务的流量。如果你管理一个办公网络,你可能非常关心 CIFS 和打印机流量。很多时候,你可以通过绘制你所知道的内容,并将你不知道的内容归入“其他”类别来获得足够的结果。这就是 FlowScan 的作用。
FlowScan 是一个提取和汇总流量数据的引擎。它提供了一个网络界面,显示网络管理员之前认为有趣的网络流量图表。这些图表适合向用户、员工和客户展示,他们可能会被更详细的流量报告所困惑。
FlowScan 建立在Cflow.pm之上,并使用轮询数据库(RRD),就像 MRTG 和 Cacti 一样。RRD 是一个固定大小的数据库,通过压缩和平均较旧的条目来保留长期数据。换句话说,RRD 提供了对最近流量的良好视图,对几个月前的流量的合理视图,以及去年流量的高级视图。然而,这比你想象的要常见得多。大多数用户想知道为什么过去一小时互联网速度慢,或者今天的流量与去年的流量相比如何。FlowScan 将回答这些问题,尽管它不能解释为什么一年前的 10 月 3 日下午互联网速度慢。
FlowScan 的模块化框架允许网络管理员从各种报告方法中进行选择。其中,我将介绍流行的 CUFlow 模块。
FlowScan 先决条件
FlowScan 有以下要求:
-
Web 服务器,例如任何 Apache 的最新版本
-
Perl
-
Korn shell 或 pdksh (
www.cs.mun.ca/~michael/pdksh/) -
RRDtool (
oss.oetiker.ch/rrdtool/)带有 Perl 共享模块支持 -
Boulder::Stream Perl 模块
-
ConfigReader::DirectiveStyle Perl 模块
-
HTML::Table Perl 模块
-
Net::Patricia Perl 模块
-
Cflow.pm
你可以从操作系统包中安装这些中的大多数。尽管 FlowScan 文档中包括有关安装 RRDtool Perl 模块RRDs.pm的警告,但 RRDTool 已经包含了这个模块一段时间了。
注意
在开始使用 FlowScan 之前,务必测试你的Cflow.pm安装。
安装 FlowScan 和 CUFlow
FlowScan 最初是为了与已废弃的 cflowd 收集器一起使用而编写的。如果你从操作系统包中安装 FlowScan,该包可能会想要安装 cflowd 及其废弃的编译器库,以及其他依赖项。有时,操作系统提供商已经编辑了 FlowScan 软件,以便最常见的用法更容易,但更不寻常的用法则更困难。出于这些原因,我建议手动安装 FlowScan。要这样做,请按照以下步骤操作:
-
从其作者的网站
net.doit.wisc.edu/~plonka/FlowScan/下载 FlowScan。 -
从
net.doit.wisc.edu/~plonka/list/flowscan/archive/att-0848/01-FlowScan.pm或通过在 Google 中搜索 flowscan.pm 1.6 下载 FlowScan Perl 模块的版本 1.6 或更高版本。 (你还可以检查本书网站上的链接部分。) -
解压 FlowScan 的 tarball,然后进入构建目录。
-
FlowScan 的作者建议将 FlowScan 安装在你保存流量文件的目录中。将此目录用作
configure命令中的prefix。(如果你没有选择位置,FlowScan 将在/usr/local/bin中安装目录、配置文件和 Perl 模块,这并不理想。)# `cd FlowScan-1.006` # `./configure --prefix=/var/db/flows/test` # `make install`现在目录 /var/db/flows/test/bin 应该包含你的 FlowScan 软件。
-
你还需要 FlowScan 的一个小型配置文件,flowscan.cf,它不会自动安装。它在解压后的 FlowScan 源代码的 cf 目录中。将此模板复制到 FlowScan bin 目录。
-
最后,升级现有的 FlowScan.pm 文件。FlowScan 附带的版本 1.5 只支持 cflowd,但版本 1.6 及更高版本可以读取
flow-capture文件。将版本 1.6 直接覆盖到 bin/FlowScan.pm。
FlowScan 用户、组和数据目录
安装 FlowScan 后,创建一个名为 flowscan 的用户,专门用于 FlowScan,并授予该用户对 FlowScan bin 目录的所有权。同时,在目录上设置组权限,以便网络管理员可以编辑 FlowScan 配置文件,而无需输入 root 密码。
FlowScan 需要在 bin 目录同一级别的两个目录:一个名为 flowscandata,用于接收流量数据文件;另一个名为 flowscanrrd,用于流量 RRD 记录。将这些目录的粘性位设置为如下:
# `chown -R flowscan:flowscan bin`
# `chmod g+w bin`
# `chmod g+ws flowscandata`
# `chown flowscan:flowscan flowscandata flowscanrrd`
# `chmod g+ws flowscandata/ flowscanrrd/`
现在将你的网络管理员添加到 flowscan 组,以便他们可以在无需 root 权限的情况下配置 FlowScan。
FlowScan 启动脚本
你的操作系统可能包含自己的 FlowScan 启动脚本。如果是这样,检查脚本的说明以了解如何配置它。如果没有,FlowScan 在 rc 目录中包含了 Linux 和 Solaris 的启动脚本。在本节中,我将展示如何配置 Linux 脚本。(Solaris 脚本非常相似,并且这些脚本应该可以在任何现代操作系统上稍作修改后使用。)文件的顶部包括四个你需要设置的变量。
❶ bindir=/var/db/flows/test/bin
❷ scandir=/var/db/flows/flowscandata
❸ logfile=/var/log/flowscan.log
❹ user=flowscan
bindir 目录(❶)包含 FlowScan 文件和 flowscan.cf。
scandir 目录(❷)是 FlowScan 检查新数据文件的地方。
将 logfile 目录(❸)放在你喜欢的任何位置。我更喜欢将所有日志放在 /var/log。在运行 FlowScan 之前,你必须 touch 日志文件,并给 flowscan 用户更改文件的权限,
最后,告诉 FlowScan 哪个用户(❹)将运行 flowscan。
该文件的第二部分包含各种标准命令的路径。这些对于大多数类 Unix 系统应该是正确的,但如果你有麻烦,请单独验证每个路径。
一旦你做了更改,让系统启动脚本以 /bin/sh 的参数运行 FlowScan 启动脚本。(根据你的系统启动过程,你可能需要在脚本顶部添加一行 #!/bin/sh。)
配置 FlowScan
flowscan.cf 文件只有四个配置值:FlowFileGlob、ReportClasses、WaitSeconds 和 Verbose。
FlowFileGlob 告诉 FlowScan 要处理哪些文件。使用它来告诉 FlowScan 要检查的目录和要尝试处理的文件类型。在这里,我正在检查目录 /var/db/flows/test/flowscandata 中的任何 flow-capture 文件:
FlowFileGlob /var/db/flows/test/flowscandata/ft-v*[0-9]
ReportClasses 列出了你正在使用的所有报告模块。FlowScan 随带两个模块,CampusIO 和 SubNetIO。这些模块不太可配置,并且并不真正代表现代流量模式,所以你会使用 CUFlow。
ReportClasses CUFlow
现在告诉 FlowScan 多久检查一次目录中的文件。CUFlow 模块假定 FlowScan 每五分钟运行一次。不要更改此设置;只需使用默认值。
WaitSeconds 300
最后,详细的日志记录在设置过程中可能会有帮助。一旦 FlowScan 运行起来,就将此设置为 0。现在,设置为 1。
Verbose 1
你已经完成了 FlowScan 的配置,但除非你设置了报告模块,否则它不会做任何事情。让我们设置 CUFlow,然后返回到 FlowScan。
配置 CUFlow: CUFlow.cf
CUFlow 比 FlowScan 的默认模块更可配置,但它假定它处理的全部流量要么进入要么离开你的网络。这使得 FlowScan 适用于在边界路由器、站点 MPLS 路由器等设备上使用,但不适用于监控在你的网络上开始和结束的流量。中转运营商对 CUFlow 的使用将有限,但即使是大型 ISP 也有一些本地网络。
要安装 CUFlow,从www.columbia.edu/acis/networks/advanced/CUFlow/CUFlow.html下载它,然后提取并复制文件CUFlow.cf和CUFLow.pm到您的 FlowScan bin目录。
CUFlow.cf包含各种语句,以告诉 FlowScan 要查找哪些数据以及如何处理这些数据。根据您的网络编辑这些语句,如下所示。
子网
子网语句告诉 CUFlow 您的本地网络上的地址。CUFlow 使用此信息来确定流量是入站还是出站。源在此网络上的流量被视为出站,而目标在此网络上的流量被视为入站。
Subnet 192.0.2.0/24
根据需要,您可以拥有多个子网语句。
网络
网络语句包括您想要单独跟踪的主机和范围。您可以拥有任意数量的网络语句,一个地址可以出现在多个网络语句中。列出单个主机或使用斜杠表示子网掩码的网络。务必为每个网络提供一个单词名称。
Network 192.0.2.4 proxy
Network 192.0.2.128/26 dmz
Network 192.0.2.36,192.0.2.37 mailservers
输出目录
OutputDir指令告诉 CUFlow 在哪里存储其 RRD 数据文件。不要将您的记录存储在 Web 可访问的位置或您的flow-capture日志目录中。相反,将它们存储在您为这些记录创建的bin目录旁边的flowscanrrd目录中。
OutputDir /var/db/flows/test/flowscanrrd
每个 FlowScan 模块都必须有自己的输出目录。如果您选择运行多个 FlowScan 模块,根据需要创建额外的 RRD 目录。
计分板
CUFlow 还可以计算流文件中最活跃的站点,并展示通过最多流、字节和包的主机地址的计分板。Scoreboard选项接受三个参数:您的“最活跃”列表中的地址数量、存储这些列表的目录以及最新列表的文件名,如下所示:
Scoreboard ❶ 10 ❷ /var/www/flowscan/topten ❸ /var/www/flowscan/topten/topten.html
在这里,计分板计算前 10 名主机(❶),将旧数据存储在目录/var/www/flowscan/topten/(❷),并将最新数据放入文件/var/www/flowscan/topten/topten.html(❸)。您必须创建Scoreboard目录,将目录所有权赋予 flowscan 用户,并配置您的 Web 服务器以允许访问当前和历史页面。
注意
不要将您的计分板文件放在与您的流文件相同的目录中。您的流文件不应靠近由 Web 服务器提供的文件。
聚合评分
CUFlow 还可以使用AggregateScore跟踪一段时间内最活跃的主机。配置AggregateScore选项与Scoreboard选项类似,包括要显示的主机数量、存储长期总量的文件以及用于结果的网页,如下所示。(请确保将聚合数据文件存储在您的 Web 服务器无法访问的地方,例如您的 RRD 数据目录。)
AggregateScore ❶ 10 ❷ /var/db/flows/test/
flowscanrrd/agg.dat ❸ /var/www/flowscan/overall.html
在这里,我展示了流量历史中前 10 个最繁忙的主机(❶),将长期数据存储在目录/var/db/flows/test/flowscanrrd/agg.dat(❷)中,并在/var/www/flowscan/overall.html(❸)中展示前 10 个 HTML 页面。
再次强调,你必须事先创建目录,并且 FlowScan 必须拥有在这些目录中写入文件的权限。
路由器
如果你有多台流量传感器向同一收集器发送数据(例如 BGP/HSRP 集群中的两个路由器),你可以使用如这里所示的路由器语句来识别不同的传感器。CUFlow 可以分离来自不同传感器的数据,这样你就可以看到每个传感器处理了多少流量。
Router 192.0.2.2 rocky
Router 192.0.2.3 bullwinkle
在这里,你通过 IP 地址识别每个路由器,并给它一个便于理解的名字。友好的名字将出现在 Web 界面中。
服务
服务语句定义了你想要单独跟踪的 TCP/IP 端口。CUFlow 将为每个由服务语句跟踪的端口或端口集生成一个单独的 RRD 文件,每个文件在 Web 界面中都以不同的颜色显示。
注意
增加服务语句的数量会增加 CUFlow 消耗的处理能力和磁盘 I/O CU,所以不要只是复制/etc/services到这里!
CUFlow.cf包含一些示例,你可以编辑以适应你的需求。例如,我网络上的用户不允许使用 Gnutella 或 eDonkey,所以我将它们从文件中注释掉。以下是一些示例服务语句:
Service 20-21/tcp ftp
Service 22/tcp ssh
Service 53/udp,53/tcp dns
第一个服务语句,FTP,使用两个 TCP 端口。第二个要简单得多,只使用一个 TCP 端口。第三个同时运行在 TCP 和 UDP 上。
如果你不确定要跟踪哪些端口,运行一些命令行报告以确定你网络上使用最频繁的端口。
协议
协议语句与服务语句非常相似,只是它在第 3 层而不是第 4 层。
Protocol 1 icmp
Protocol 6 tcp
Protocol 17 udp
如果你使用 IPSec VPN,你可能想跟踪协议 50-51(ESP 和 AH)。PPTP 用户可能对协议 47(GRE)感兴趣。
AS
基于 BGP 的站点可能对通过 AS 号跟踪特定网络流量的流量感兴趣。同样,这里的每个 AS 条目都会消耗处理时间。不要只是将 AS 分配的完整列表放在这里!
AS 7853,13385,36377,16748,33542,36196,14668 Comcast
AS 65535 Lucas
AS 701-705 UUnetLegacy
软件流量传感器(如softflowd)不导出 BGP 信息,因此在使用软件传感器时,不要麻烦进行 AS 分析。
现在你已经配置了 CUFlow,让我们给它一些数据。
轮转程序和 flow-capture
FlowScan 会检查单个目录中的流文件:/var/db/flows/flowscandata。如果 FlowScan 找不到任何文件,它将返回休眠五分钟。这个flow-capture系统将数据记录到存储在目录层次结构中的文件中。例如,2011 年 2 月 17 日的文件存储在目录/var/db/flows/test/2011/2011-02/2011-02-17中。你如何将这些文件放入你的/var/db/flows/flowscandata目录中?你可以使用一个flow-capture日志轮转脚本。
flow-capture 的 -R 选项在流量文件关闭并创建新临时文件时运行脚本。例如,为了在每个新日志文件上运行脚本 /usr/local/bin/flow-rotate.sh,你应该这样运行 flow-capture:
# `flow-capture -p /var/run/flow-capture.pid -R /usr/local/bin/flow-rotate.sh -n 287 \`
`-w /var/db/flows -S 5 10.10.10.10/172.16.16.16/5678`
flow-capture 给旋转程序一个参数:相对于流量目录的关闭日志文件的名称。例如,在我写这篇文章的时候,我的测试实验室中的 flow-capture 正在将文件 tmp-v05.2011-02-17.152001-0500 写入今天的目录。在下午 3:25 pm,flow-capture 将关闭这个临时文件,将其重命名为 ft-v05.2011-02-17.152001-0500,并创建一个新的 tmp- 文件。此时,flow-capture 将运行由 -R 指定的任何脚本,并带有当前文件的路径。这就像你在每个日志文件关闭后立即运行这个命令一样。
# `flow-rotate.sh 2011/2011-02/2011-02-17/ft-v05.2011-02-17.152001-0500`
你的脚本需要接受这个名称并对流量数据文件执行任何必要的后处理。首先,你想要将流量文件复制到你的数据目录。以下是一个 shell 脚本示例:
#!/bin/sh
cp $1 /var/db/flows/test/flowscandata/
第二,一旦你有了文件名,将文件复制到 flowscan 数据目录就很简单了。
现在将这个脚本作为 flow-capture -R 的参数传递,然后验证流量文件是否已复制到 FlowScan 数据目录。
注意
让你的旋转脚本非常简单。记住,这个脚本每五分钟就会运行一次,如果它生成大量的日志或发送电子邮件,你每天会收到这些消息 288 次。
运行 FlowScan
现在是时候通过运行其启动脚本来启动 FlowScan。FlowScan 的日志文件应该有如下条目:
2011/02/17 17:29:07 working on file ❶ /var/db/flows/test/
flowscandata/ft-v05.2011-02-17.172501-0400...
2011/02/17 17:29:10 flowscan-1.020 CUFlow: Cflow::find took
❷ 3 wallclock secs (3.36 usr + 0.00 sys = 3.36 CPU) for
❸ 615816 flow file bytes, ❹ flow hit ratio: 31593/31599
2011/02/17 17:29:12 flowscan-1.020 CUFlow: report took
❺ 1 wallclock secs (0.00 usr 0.00 sys + 0.12 cusr 0.04 csys = 0.16 CPU)
❻ Sleep 300...
在这个输出中,FlowScan 开始(❶)处理你的日志轮转程序复制到数据目录中的文件。你可以看到 ❷ FlowScan 搜索文件以查找数据花费了多长时间,以及 ❸ 文件大小。
然而,这里最有趣的是 ❹ 处的流量命中比率。这个比率告诉你文件中有多少流量匹配你的 Subnet 语句。你应该有压倒性的匹配数量。在这里,我在文件中匹配了 31,593 个流量中的 31,599 个,这是可以接受的。(广播流量和配置错误的设备可能解释了少量不匹配的流量。)你还可以看到 ❺ FlowScan 写入 RRD 文件花费了多长时间。
最后,在 ❻ FlowScan 处理完所有文件后,它会进入休眠状态五分钟。当它醒来时,它会处理数据目录中找到的任何文件。
注意
如果你的日志消息看起来不像这样,你就犯了错误。检查你的权限,然后谷歌搜索错误。几乎可以肯定,之前有人犯过同样的错误。他们总是这样。
FlowScan 文件处理
当 FlowScan 完成处理文件后,它会删除流量文件。当你将文件复制到 FlowScan 特定的数据目录时,这是一种理想的行为,因为尽管现在磁盘空间很便宜,但保存每个流量文件的副本有点过多!
如果您不希望 FlowScan 删除已处理的文件,在 FlowScan 数据目录中创建一个 saved 目录,FlowScan 将将处理过的文件移动到这个目录。然而,这种保留不是分层的:您将每天向此目录添加 288 个文件,每周添加 2,016 个文件,每年添加 104,832 个文件。过了一段时间后,简单的 ls 命令将需要很长时间才能完成。我建议您让 FlowScan 抛弃已处理的文件,并依赖您的原始文件。
显示 CUFlow 图
CUFlow 包含一个用于显示图表的 CGI 脚本,称为 CUGrapher.pl。此脚本将 RRD 数据转换为图表。要使用此脚本,将其复制到您的 Web 服务器 CGI 目录,然后在脚本顶部附近设置两个变量以生成以下图表:
-
将
$rrddir变量设置为存储您的 FlowScan RRD 文件的目录。my $rrddir = "/var/db/flows/test/flowscanrrd"; -
使用
$organization变量设置站点或公司名称。my $organization = "Obey Lucas in All Things"; -
现在,将您的网络浏览器指向 CGI 脚本,您应该会看到类似于 图 6-1 的内容。
![初始 CUFlow 菜单]()
图 6-1. 初始 CUFlow 菜单
在“所有服务”下方勾选复选框,并在最右侧勾选“总计”复选框,如图 图 6-1 所示。这将显示该网络上使用的所有 TCP/IP 服务的 FlowScan 图,类似于 图 6-2。
在 CUFlow.cf 中定义的每个协议都有自己的颜色,如图表底部的图例所示。图 6-2 中的示例图例显示了分配给 RTSP、HTTP、SMTP 等的颜色。空白区域表示在 CUFlow.cf 中未列为服务的流量。在每个颜色旁边,您将看到该协议的总流量量。

图 6-2. CUFlow 中的服务
此外,正数表示离开您网络的数据流量,负数表示进入网络的数据流量。例如,在此图表的起始位置(在最左侧),有 140Kbps 的数据流量离开网络,80Kbps 的数据流量进入。大部分出去的流量由已知服务组成。进入流量中的大量空白区域包括 CUFlow 尚未告知分类的流量。要识别这些空白区域中的流量,请检查流量文件本身。
CUFlow 允许您在各个时间段内生成协议、网络和服务的图表,但它一次只会报告一个协议、网络或服务。此外,CUFlow 会将您的所有选择相加。例如,如果您从协议列中选择 TCP,从服务列中选择 HTTP,从网络列中选择您的 Web 服务器,结果将是一个没有意义的图表,它包括所有 TCP 流量、所有 HTTP 流量和您 Web 服务器的所有流量。要创建一个更具体的图表,例如特定服务器的所有 HTTP 流量,您必须使用更灵活的工具,如 FlowViewer (第七章)。或者,如果您需要反复检查此图表,请拆分您的流量记录,并运行多个 FlowScan 和 CUFlow 实例。
流量记录拆分和 CUFlow
CUFlow 是一个用于绘制最常见网络情况的有用工具,但它有其局限性。例如,您不能从多个列中选择,比如查看您的 Web 服务器发送了多少 HTTP 流量;您只能看到 HTTP 流量的总量或 Web 服务器流量的总量。此外,您不能使用 CUFlow 进行真正的即兴报告,但您可以配置它来表示关于您网络的常见问题。
在某些环境中,CUFlow 的局限性尤为明显。曾经我管理过一个数据中心,它通过私有 MPLS 网络为远程站点提供服务。每个工厂都有一个 T1 或 E1,而数据中心有一个 DS3。每个站点都从主数据中心获得所有服务。我在总部 DS3 上有流量导出和 CUFlow,它报告了流向中央邮件服务器、文件服务器、代理服务器等流量,我想提供管理访问以显示每个工厂使用的流量以及该流量是什么。然而,大多数工厂没有能够导出流量数据的设备。
通过将工厂流量信息从 DS3 流量记录中拆分出来,并为每个工厂运行一个单独的 FlowScan 实例,我提供了有用(但不完美)的结果。我说“不完美”,因为这些结果不会显示工厂之间的流量,例如。然而,由于每个工厂的绝大多数外部流量都流向了中央数据中心,它对电路上的流量提供了一个很好的猜测。
流量记录拆分适用于许多环境。例如,Web 农场没有远程站点,但他们可能有一些主要客户,每个客户都希望有自己的 FlowScan 页面。您可以通过首先将流量拆分为多个数据集,然后为每个数据集设置一个单独的 FlowScan 实例来提供这些单独的页面。
流量拆分
要将流数据分割成更小的数据集,请使用 flow-nfilter。您可能已经为每个数据子集都有一个过滤器,但您需要确保过滤器覆盖传入和传出流量。例如,要仅提取包含地址 192.0.2.0/24 的流数据,您可以使用以下基本过滤器:
filter-primitive site1
type ip-address-prefix
permit 192.0.2.0/24
filter-definition site1
match ip-source-address site1
or
match ip-destination-address site1
接下来,使用 flow-print 验证过滤器只为这些地址传递流,并使用 flow-cat 和 flow-nfilter 创建只包含这些数据的流文件。
# `flow-cat ft-v05.2011-02-18.112001-0500 | flow-nfilter -F` ❶ `site1 >`
❷ `ft-v05.site1`
文件 ft-v05.site1(❷)是一个只包含由 site1 过滤器(❶)允许的流的流文件。使用 flow-print 验证这一点。
流记录分割脚本编写
FlowScan 预期流文件的稳定供应。您不应手动为每个新的流文件运行 flow-cat 和 flow-nfilter。相反,使用流旋转脚本将每个新的流文件过滤到更小的数据集中,如下例所示:
#!/bin/sh
PATH=/bin:/usr/bin:/usr/local/bin
#for our primary flowscan instance
cp $1 /var/db/flows/test/flowscandata
#for flowscan on a data subset
flow-cat /var/db/flows/test/$1 | \
flow-nfilter ❶ -f /usr/local/etc/flow-tools/site1-filter.cfg -F site1 > \
❷ /var/db/flows/site1/flowscandata/
该脚本的开始部分与您用来将流文件复制到现有 FlowScan 实例的流旋转脚本相同。(您不希望破坏已经正常工作的东西!)最后一个命令将特定站点的流分离出来,并在单独的目录中创建该数据流文件。使用 flow-nfilter 的 -f 参数(❶)来使用非标准流过滤器定义文件,记住如果您的流过滤器文件包含不完整或无效的规则,flow-nfilter 将不会运行。
注意
如果在旋转脚本运行时编辑过滤器规则,脚本将失败。最好有一个专门的过滤器定义文件,专门用于分离这些流。
每个 FlowScan 实例都需要其自己的传入数据目录(❷),如下一节详细讨论的那样。为此脚本添加针对您数据子集的每个 FlowScan 实例的行,并且每次更改旋转脚本时都要确保重启 flow-capture。
过滤后的 CUFlow 和目录设置
为每个 FlowScan 实例分配其自己的目录。主要流文件收集在 /var/db/flows/test 中,因此请使用类似 /var/db/flows/site1 的目录。此目录需要三个子目录:flowscandata(用于传入的过滤流文件)、flowscanrrd(用于从处理过的流文件创建的 RRD 文件)和 bin(用于此 FlowScan 实例)。确保 flowscan 用户可以写入这些目录。
将您原始 FlowScan bin 目录中的所有内容复制到此 FlowScan 实例的 bin 目录中,以获取所有更新后的模块。然后,为了设置您的新实例,通过将 FlowFileGlob 更改为指向您新实例的数据目录路径来编辑 flowscan.cf。
现在,因为每个 FlowScan 实例都需要在你的 web 服务器下单独的目录来存储其计分板和顶级主机列表,所以创建该目录,然后编辑 CUFlow.cf 以更改 OutputDir、Scoreboard 和 AggregateScore 目录和文件,使其指向该目录。最后,通过复制现有的启动脚本、编辑它以匹配你的新实例,并为其分配一个新的日志文件,为每个 FlowScan 实例提供自己的启动脚本。(记住,在启动 FlowScan 之前,日志文件必须存在,并且 flowscan 用户必须能够写入它。)现在启动你的第二个 FlowScan 实例。如果有问题,你应该能在日志文件中看到。
虽然为网络中的每个服务器组或甚至每个主机创建单独的 FlowScan 实例可能很有吸引力,但这样做会增加系统负载和维护开销。FlowScan 每五分钟运行一次,如果你的服务器需要超过五分钟才能完全处理数百个 FlowScan 实例,那么你的系统将变得不可用。
深入了解 PERL
FlowScan 和 CUFlow 并非适合所有人。对于那些希望自行实现的人来说,本章的其余部分讨论了如何编写自己的 Perl 模块来读取流量记录。以下代码片段假设你具备基本的、实际操作的 Perl 知识,但并非很多人都是网络工程师、系统管理员和 Perl 程序员。如果你不习惯阅读行噪声,并且对导出变量或函数不感兴趣,请跳到下一章。
使用 Cflow.pm
Perl 是系统管理和网络开发中流行的语言。Cflow.pm 模块允许你编写直接读取流量文件的 Perl 代码。
一个 Sample Cflow.pm 脚本
这是一个简单的 Cflow.pm Perl 脚本,它打印出所有 UDP 端口 500 (Checkpoint ISAKMP,用于 IPSec VPN) 流量,从 Cflow.pm 文档中提供的脚本中简化而来。此脚本接受一个或多个流程文件名作为参数。
#!/usr/bin/perl
❶ use Cflow qw(:flowvars find);
❷ find (\&wanted, @ARGV);
❸ sub wanted {
return unless (($srcport == 500 && $dstport == 500 ) && $udp == $protocol);
printf("%s %15.15s.%-5hu %15.15s.%-5hu %2hu %10u %10u\n",
$localtime, $srcip, $srcport, $dstip,
$dstport, $protocol, $pkts, $bytes)
}
此脚本首先包含 Cflow.pm (❶),然后从该模块导出流程变量名和 find() 函数。Cflow.pm (❷) 的核心是 find() 和 wanted() 函数。当你将流程文件传递给脚本时,find() 将文件中的每个流程发送到 wanted() 函数。在 wanted() 函数 (❸) 中,脚本执行你为每个单独的流程编写的任何函数。
Cflow.pm 提供了许多变量来访问流量数据。尽管许多这些变量的含义很容易猜测,例如 $srcport、$dstport、$protocol 等等,但我还是将它们列在 表 6-1 中。
Find() 和 wanted() 允许你使用 Cflow.pm 作为引擎将流量数据输入到数据库、RRD 或哈希文件中;标记符合你环境独特模式(你无法轻松过滤)的有趣流量等等。
Cflow.pm 变量
表 6-1 显示了由Cflow.pm提供的流评估变量。
表 6-1. Cflow.pm变量
| 变量 | 含义 | 样本输出 |
|---|---|---|
$unix_secs |
流开始时间的纪元秒 | 1229490004 |
$exporter |
传感器 IP 地址,作为长整数 | 1430200323 |
$exporterip |
传感器 IP 地址,作为点分四元组 | 192.0.2.3 |
$localtime |
将纪元时间转换为本地时间 | 2011/12/16 23:59:43 |
$srcaddr |
作为长整数的源 IP 地址 | 1430200341 |
$srcip |
作为点分四元组的源 IP 地址 | 192.0.2.27 |
$dstaddr |
作为长整数的目标 IP 地址 | 1166468433 |
$dstip |
作为点分四元组的目标 IP 地址 | 69.134.229.81 |
$input_if |
输入接口索引 | 2 |
$output_if |
输出接口索引 | 9 |
$srcport |
TCP 或 UDP 源端口号或等效值 | 53 |
$dstport |
TCP 或 UDP 目标端口号或等效值 | 46819 |
$ICMPType | ICMP 类型(仅对 ICMP 流,$dstport 的高字节) |
3 | |
$ICMPCode | ICMP 代码(仅对 ICMP 流,$dstport 的低字节) |
1 | |
$ICMPTypeCode |
ICMP 类型和代码的友好名称 | HOST_UNREACH |
$pkts |
流中的数据包 | 5 |
$bytes |
期间发送的字节数 | 138 |
$nexthop |
下一个跳转路由器的 IP 地址,作为长整数 | 1398215405 |
$nexthopip |
下一个跳转路由器的 IP 地址,作为点分四元组 | 12.61.8.12 |
$starttime |
流开始时本地时间的纪元秒 | 1229489984 |
$start_msecs |
起始时间的毫秒部分 | 131 |
$endtime |
流结束时本地时间的纪元秒 | 1229489985 |
$end_msecs |
结束时间的毫秒部分 | 871 |
$protocol |
TCP/IP 协议号 | 17 |
$tos |
服务类型 | 0 |
$tcp_flags |
所有 TCP 标志的按位或,或非 TCP 流的 0x10 | 16 |
$TCPFlags |
tcp_flags 的友好表示 | ACK |
$raw |
整个原始流格式 | 二进制 |
$reraw |
修改后的原始流文件格式,用于写入新文件 | 二进制 |
$Bps |
此流每秒的最小字节数 | 40 |
$pps |
此流的每秒最小数据包数 | 5 |
$src_as |
当前流的 BGP 源 AS | 701 |
$dst_as |
当前流的 BGP 目标 AS | 11512 |
$src_mask |
源地址前缀掩码位 | /23 |
$dst_mask |
目标地址前缀掩码位 | /16 |
$engine_type |
流切换引擎的类型(供应商特定) | 1 |
$engine_id |
流切换引擎的引擎 ID(供应商特定) | 0 |
要使用这些变量,您必须首先在它们前面加上Cflow::或像我在示例脚本顶部所做的那样从Cflow.pm导出它们。
其他 Cflow.pm 导出
Cflow.pm 还导出了 TCP 标志和 ICMP 类型及代码的符号名称。您可能会发现这些名称(如表 6-2 所示)比原始数字更容易使用,尤其是在复杂的脚本中。
表 6-2. 导出的 TCP 标志符号名称
| 变量 | 含义 | 值 |
|---|---|---|
$TH_FIN |
结束标志 | 1 |
$TH_SYN |
同步标志 | 2 |
$TH_RST |
重置标志 | 4 |
$TH_PUSH |
推送标志 | 8 |
$TH_ACK |
确认标志 | 16 |
$TH_URG |
紧急标志 | 32 |
将 TCP 标志通过导出tcpflags使其可访问。同样,导出icmptypes和icmpcodes以使用它们的符号名称,如表 6-3 所示。
表 6-3. 导出的 ICMP 类型符号名称
| 变量 | 含义 | 值 |
|---|---|---|
$ICMP_ECHOREPLY |
回显响应 | 0 |
$ICMP_DEST_UNREACH |
目标不可达 | 3 |
$ICMP_SOURCE_QUENCH |
源抑制 | 4 |
$ICMP_REDIRECT |
重定向 | 5 |
$ICMP_ECHO |
回显请求 | 8 |
$ICMP_TIME_EXCEEDED |
超时 | 11 |
$ICMP_PARAMETERPROB |
其他 ICMP 类型未涵盖的错误 | 12 |
$ICMP_TIMESTAMP |
时间戳请求 | 13 |
$ICMP_TIMESTAMPREPLY |
时间戳响应 | 14 |
$ICMP_INFO_REQUEST |
网络信息请求(已弃用) | 15 |
$ICMP_INFO_REPLY |
网络信息响应(已弃用) | 16 |
$ICMP_ADDRESS |
网络掩码请求 | 17 |
$ICMP_ADDRESSREPLY |
网络掩码请求响应 | 18 |
符号名称包括用于 ICMP 类型 3(不可达,表 6-4)、5(重定向,表 6-5)和 11(超时,表 6-5)的 ICMP 代码。
表 6-4. 导出的 ICMP 类型 3 代码符号名称
| 变量 | 含义 | 值 |
|---|---|---|
$ICMP_NET_UNREACH |
网络不可达 | 0 |
$ICMP_HOST_UNREACH |
主机不可达 | 1 |
$ICMP_PROT_UNREACH |
协议不可达 | 2 |
$ICMP_PORT_UNREACH |
UDP 端口不可达 | 3 |
$ICMP_FRAG_NEEDED |
需要分片 | 4 |
$ICMP_SR_FAILED |
源路由失败 | 5 |
$ICMP_NET_UNKNOWN |
网络未知 | 6 |
$ICMP_HOST_UNKNOWN |
主机未知 | 7 |
$ICMP_HOST_ISOLATED |
源主机隔离 | 8 |
$ICMP_NET_ANO |
网络被管理禁止 | 9 |
$ICMP_HOST_ANO |
主机被管理禁止 | 10 |
$ICMP_NET_UNR_TOS |
在此服务类型下网络不可达 | 11 |
$ICMP_HOST_UNR_TOS |
在此服务类型下主机不可达 | 12 |
$ICMP_PKT_FILTERED |
被过滤禁止的通信 | 13 |
$ICMP_PREC_VIOLATION |
主机优先级违规 | 14 |
$ICMP_PREC_CUTOFF |
优先级截止生效 | 15 |
$ICMP_REDIRECT_NET |
网络重定向 | 0 |
$ICMP_REDIRECT_HOST |
主机重定向 | 1 |
$ICMP_REDIRECT_NETTOS |
网络和类型服务重定向 | 2 |
$ICMP_REDIRECT_HOSTTOS |
主机和类型服务重定向 | 3 |
表 6-5. 导出的 ICMP 类型 11 代码符号名
| 变量 | 含义 | 值 |
|---|---|---|
$ICMP_EXC_TTL |
转运中生存时间超时 | 0 |
$ICMP_EXC_FRAGTIME |
片段重组时间超时 | 1 |
注意
在每个流量的可用值、TCP 标志和 ICMP 类型及代码之间,你可以添加代码以执行流量分析。
对每个文件执行操作
Cflow.pm 支持在处理流量文件后的操作,例如释放内存、重新初始化变量,或者可能将文件移动到存档目录。如果你将其包含在你的脚本中,Cflow.pm 将对每个流量文件调用一次 perfile() 函数。在你的 find() 函数中立即包含对 perfile 的引用,紧随 wanted 引用之后。
#!/usr/bin/perl
use Cflow qw(:flowvars find );
find (\&wanted, \&perfile, @ARGV);
sub wanted {
}
sub perfile {
print "working on \"$_[0]\"...\n";
}
此代码示例会为每个文件打印一次文件名。
返回值
find() 函数返回匹配 wanted() 函数的流量数量比率。例如,这里我返回流量文件中的 ICMP 流量数量:
#!/usr/bin/perl
use Cflow qw(find :flowvars );
$hitrate = find (\&wanted, @ARGV);
sub wanted {
return unless (1 == $protocol);
$icmp++;
}
print "hitrate is $hitrate\n";
运行此命令会生成如下所示的输出:
hitrate is 34/4140
输入文件中的 4,140 个流量中有 34 个是 ICMP 流量。
详细模式
Cflow.pm 默认生成错误信息。要禁用此功能,将 verbose 设置为 0,如下所示:
use Cflow qw(find :flowvars );
verbose(0);
...
每次设置此选项时,我通常都会希望我没有这样做,因为它会生成大量的输出,掩盖了有用的数据。尽管如此,它对于调试仍然很有用。
现在你已经了解了如何进行简单的基于网络的报告,你将学习如何进行复杂的报告。
第七章. FLOWVIEWER

几乎每个人都喜欢网络流量的漂亮图片。FlowScan 和 CUFlow 以用户友好的方式绘制常见的、预期的流量类型。然而,你的网络却并非如此普通或预期。除了 CUFlow 之外,你还需要一个更可定制的分析工具,无论是因为你需要一次性报告、对从未期望看到的流量进行洞察,还是对去年流量的近距离观察。正如你将在本章中学到的,FlowViewer 套件 (ensight.eos.nasa.gov/FlowViewer/) 是这样的可定制工具之一,它可以快速创建和访问基于网络的报告。
FlowViewer 包含三个独立的组件:FlowViewer、FlowTracker 和 FlowGrapher。FlowViewer 是 flow-print 和 flow-nfilter 的网络界面,一旦你在网页表单中定义了过滤器,就会打印出匹配的流量。FlowGrapher 允许你根据需要绘制数据子集。FlowTracker 是一种简单的方式来构建和查看 RRDs,就像 CUFlow 一样,但它允许你非常具体地过滤绘制的流量。如果你想持续跟踪企业资源规划 (ERP) 系统的 HTTPS 和 telnet 流量,FlowTracker 就是你的好朋友。总体而言,这三个工具为网络提供了大量的可见性。
注意
FlowViewer 拥有一份详尽的用户手册,其中包含的信息比我能够在一个章节中容纳的要多。请参阅 FlowViewer 手册以获取更深入的信息。
FlowTracker 和 FlowGrapher 与 CUFlow 的比较
如果 FlowTracker、FlowGrapher 和 CUFlow 有类似的功能,为什么不只使用其中一个呢?主要原因是易用性。
CUFlow 很容易理解。你可以给你的客户访问 CUFlow 图表,并且只需最少的解释,他们就可以相当准确地解释结果。即使是最笨拙的同事也能理解 CUFlow 的输出。但与此同时,这种易于理解也牺牲了灵活性。用户只能获得网络管理员配置的功能和报告,而旧的报告则受到第六章中讨论的 RRD 数据库压缩的影响。
另一方面,FlowViewer 的绘图和跟踪功能比 CUFlow 更强大,但也更复杂。报告几乎可以无限定制、调整和配置,这一广泛的功能集意味着你真的需要知道自己在做什么才能获取有用的信息。此外,FlowViewer 没有只读用户的观念:任何可以访问你的 FlowViewer 网站的人都可以完全访问其所有功能。FlowViewer 是为网络管理员设计的,而不是为普通用户。
FlowViewer 安全性
如前所述,任何可以访问 FlowViewer 的人都可以看到您内部网络的所有信息。一个熟练的入侵者会认为这是无法抗拒的。其他人可能只是打扰您:不熟练的访客,例如您的帮助台工作人员,可能会错误地解释 FlowViewer 的结果,让您花费时间解释为什么它们是错误的。因此,我强烈建议对 FlowViewer 网站进行密码保护,并限制允许访问服务器的 IP 地址。即使使用自签名证书,HTTPS 也能保护您的用户凭据和数据在传输过程中的安全。
FlowViewer 的默认安装还使用一个可由世界写入的目录来存储报告。这在多用户系统中是一个安全风险。如果您使用共享系统作为您的分析工作站,您必须比 FlowViewer 的默认设置更严格地限制权限。
安装 FlowViewer
如果可能,请从您的操作系统供应商提供的软件包中安装 FlowViewer。如果您的供应商不提供 FlowViewer 软件包,您当然需要手动安装。
先决条件
在安装 FlowViewer 之前安装以下软件包,这些软件包在大多数操作系统中都应作为软件包提供:
-
Web 服务器,例如任何最近的 Apache
-
Perl
-
RRDtool (
oss.oetiker.ch/rrdtool/) 支持 Perl 共享模块 -
GD 图形库 (
www.boutell.com/gd/) -
gd::graph Perl 模块
-
GDBM Perl 模块(可能打包为 GDBM_File)
您还需要知道运行您的网页的系统用户。这可能是名为 www、http 或 www-data 的用户。如果您的 Web 服务器正在运行,请输入 ps -axe 或 ps -axj 以获取运行服务器的用户名。
FlowViewer 安装过程
要安装 FlowViewer,首先从 ensight.eos.nasa.gov/FlowViewer/ 下载 FlowViewer 的最新版本。压缩的安装文件包含一个包含整个包的 FlowViewer 目录,将其解压到您的 Web 服务器下的一个目录中。
现在配置您的 Web 服务器以允许在该目录中执行 CGI。例如,以下是如何配置 Apache 以在目录 /usr/local/www/flowviewer 中支持 FlowViewer 的示例:
❶ `Alias /FlowViewer/ /usr/local/www/flowviewer/`
❷ `<Directory /usr/local/www/flowviewer/>`
`Options +ExecCGI`
`AddHandler cgi-script .cgi`
`Order allow,deny`
`Allow from all`
`</Directory>`
在❶处的别名定义将 Web 位置 servername/FlowViewer/ 映射到本地目录 */usr/local/www/flowviewer/。然后,在❷处您为 FlowViewer 目录分配特定的权限,允许 CGI 执行和客户端访问。最后,重新启动 Apache。
安装部分到此结束。FlowViewer 更困难的部分是配置。
配置 FlowViewer
FlowViewer 套件中的所有工具都使用FlowViewer_Configuration.pm配置文件。尽管此文件包含许多设置,但只有少数是正确操作所必需的;其他设置允许你调整应用程序的外观和 FlowTracker 的 RRD 文件的行为。如果你对这里未讨论的设置感兴趣,请参阅 FlowViewer 的详细手册。我将仅介绍使 FlowViewer 工作所需的设置。(某些操作系统包在安装过程中为你设置这些设置。)不再多言,以下是你将需要的设置:
-
$ENV{PATH}变量仅包括 FlowViewer 所需的系统命令的路径。在几乎所有系统中,你应该保持这个设置不变。你不需要在这些目录中有 flow-tools 和 RRDtool;它们有自己的路径变量,你将在稍后设置。 -
$FlowViewer_server变量告诉 FlowViewer 你网站的域名。例如,为了使我的测试收集器在netflow.blackhelicopters.org/可见,我将$FlowViewer_server设置为netflow.blackhelicopters.org。 -
$FlowViewer_service变量帮助 FlowViewer 构建网页。根据你网站的适当情况将其设置为http或https。
目录和网站路径
FlowViewer 将文件存储在 Web 服务器上,所有文件存储目录都必须可由 Web 服务器用户写入。创建这些目录,并将它们的所有权更改为 Web 服务器用户。(不可写入的目录是 FlowViewer 问题的一个常见原因。)
大多数目录变量还有一个“简短”版本,它定义了网络浏览器可以在服务器上找到该目录的位置。FlowViewer 使用这个简短名称来创建指向生成内容的链接。当我带你设置前几个变量时,我会通过例子来展示。
搜索和替换配置
默认的FlowViewer_Configuration.pm假定 Apache 的DocumentRoot目录是/htp/htdocs,而 FlowViewer 安装的 CGI 目录是/htp/cgi-bin。你可能需要对这些值进行简单的搜索和替换,将它们替换为你环境中正确的DocumentRoot和FlowViewer安装目录。在所有以下示例中,我的网站根目录是/var/www/ssl,FlowViewer 安装在/usr/local/www/flowviewer。你必须创建 FlowViewer 告诉你要使用的所有目录。
$reports_directory告诉 FlowViewer 报告的存储位置,而$reports_short给出客户端在网站上找到$reports目录的位置。报告目录必须在 Apache 的DocumentRoot或另一个 Apache 可访问的目录下。在这里,我在我的DocumentRoot中创建了一个FlowViewer目录:
$reports_directory = "/var/www/ssl/FlowViewer";
$reports_short = "/FlowViewer";
FlowViewer 将生成的图形存储在$graphs_directory中,$graphs_short定义了客户端在网站上找到$graphs_directory的位置。像$reports_directory一样,$graphs_directory必须在网站上可访问。我使用目录/var/www/ssl/FlowGrapher。
$graphs_directory = "/var/www/ssl/FlowGrapher";
$graphs_short = "/FlowGrapher";
FlowTracker 工具将文件存储在$tracker_directory中,该目录在网站上可通过$tracker_short访问。我使用目录/var/www/ssl/FlowTracker。
$tracker_directory = "/var/www/ssl/FlowTracker";
$tracker_short = "/FlowTracker";
$$cgi_bin_directory变量指向包含 FlowViewer 软件的目录。您可以选择将其复制到您的 Web 服务器的常规 CGI 可执行目录,但我建议在单独的目录中安装 FlowViewer,然后配置您的 Web 服务器在该目录中运行 CGI 脚本。例如,正如您在这里可以看到的,我的 FlowViewer 安装在/usr/local/www/flowviewer,我已配置 Web 服务器提供servername/flowviewer:
$cgi_bin_directory = "/usr/local/www/flowviewer";
$cgi_bin_short = "/flowviewer";
FlowViewer 将临时文件保存在$work_directory中,该目录在 Web 服务器上可通过$work_short访问。这里我使用/var/www/ssl/FlowWorking:
$work_directory = "/var/www/ssl/FlowWorking";
$work_short = "/FlowWorking";
为以后保存的报告和过滤器存储在$save_directory中,该目录可通过 Web 客户端作为$save_short访问。为此创建/var/www/ssl/FlowViewer_Saves。
$save_directory = "/var/www/ssl/FlowViewer";
$save_short = "/FlowViewer_Saves";
剩余的目录在网站上的路径上没有“短”变量。FlowViewer 使用它们进行内部跟踪或查找关键软件,客户端不应直接访问它们。
-
当用户要求 FlowViewer 解析 IP 地址的名称时,它将在
$names_directory中缓存结果。例如,我把我的名称缓存放在/usr/local/www/flowviewer/names。记住,任何缓存的 DNS 数据随着主机更改 IP 地址而逐渐变得过时。 -
FlowTracker 将其用于创建跟踪器的过滤器存储在
$filter_directory中,并将 RRD 文件存储在$rrdtool_directory中。 -
$flow_bin_directory目录是 flow-tools 安装的位置。这通常是类似/usr/local/bin或/usr/local/flow-tools/bin的东西。 -
类似地,
rrdtool_bin_directory是 RRDtool 安装的位置,通常是/usr/local/bin或/usr/local/rrdtool/bin。
在配置中,它们看起来是这样的:
$names_directory = "/usr/local/www/flowviewer/names";
$filter_directory = "/usr/local/www/flowviewer/FlowTracker_
Files/FlowTracker_Filters";
$rrdtool_directory = "/usr/local/www/flowviewer/FlowTracker
_Files/FlowTracker_RRDtool";
$flow_bin_directory = "/usr/local/bin";
$rrdtool_bin_directory = "/usr/local/bin";
网站设置
下面的四个值在 FlowViewer 的 Web 界面中设置了一些基本属性:
-
FlowTracker 自动生成一个网页,列出当前正在运行的跟踪器。默认文件是
$tracker_directory中的index.html。通过将$actives_webpage设置为所需的文件名来更改此设置。 -
自动生成的跟踪页面将您的组织名称作为
$trackings_title的值列出。 -
要将您的公司标志放在每个页面顶部的 FlowViewer 图形旁边,创建一个高度为 86 像素的标志文件,并将其复制到
$reports_directory。 -
然后将
$user_logo分配给文件名。标志将链接到在$user_hyperlink中定义的网站。
在配置中,它们将看起来像这样:
$actives_webpage = "index.html";
$trackings_title = "Lucas LLC";
$user_logo = "myfirm.jpg";
$user_hyperlink = "http://www.michaelwlucas.com/";
设备和导出器
在第二章中,您决定使用一个接受来自所有传感器的流量记录的单个收集器,或者为每个传感器设置一个单独的收集器。FlowViewer 可以支持这两种配置,但您必须告诉它它使用的是哪一种。
最简单的情况是单个传感器和单个收集器,当您预期永远不会更多时,但我不建议做出这个假设。网络会随着时间的推移而变化,您的 FlowViewer 安装应该适应这种变化。如果您坚持只有一个收集器和单个传感器,尽管如此,请参阅 FlowViewer 手册了解有关更改 $no_devices_or_exporters 的信息。
每个传感器一个收集器
在第二章中,我建议为每个传感器设置一个收集器。您的流量数据将进入一个目录,例如 /var/db/flows,每个设备都有一个子目录。您最终会得到如下目录:/var/db/flows/router1(用于传感器路由器 1),/var/db/flows/router2(用于传感器路由器 2),等等。
对于这个设置,将流量数据根目录分配给 $flow_data_directory。在我的设置中,$flow_data_directory 是 /var/db/flows。现在将变量 @devices 分配给代表传感器的目录名称列表。例如,我的网络有传感器路由器 1、路由器 2 和路由器 3。我会将以下值分配给 @devices。(FlowViewer 将 @devices 中的所有内容作为下拉菜单中的选项提供。)
$flow_data_directory = "/var/db/flows";
@devices=("router1","router2","router3");
为所有传感器分配一个收集器
如果所有您的传感器都将数据发送到单个收集器,请不要设置 @devices 或 $flow_data_directory。相反,将 $exporter_directory 设置为您的综合流量数据的位置。如果您运行了一个单独的收集器并且所有数据都进入了 /var/db/flows,则将 $exporter_directory 设置为 /var/db/flows。此外,取消注释 @exporters,并将其设置为收集器中的传感器列表,按 IP 地址和主机名列出导出器,如下所示:
$exporter_directory = "/var/db/flows";
@exporters = ("192.0.2.1:router1","192.0.2.2:router2","192.0.2.3:router3");
FlowViewer 现在已配置并准备好使用。将您的网络浏览器指向 FlowViewer.cgi 以查看其初始屏幕。
流览器套件故障排除
FlowViewer 有许多设置选项,您在第一次安装时可能会犯错。我强烈建议保持一个终端窗口打开,并在您的 Web 服务器错误日志上运行 tail -f 以显示错误。根据我的经验,最常见的问题是目录变量不正确和目录权限问题。
在使用 FlowViewer 时,请监视错误日志,并在错误出现时进行纠正。遵循这些程序,在测试几分钟内,您应该有一个正确工作的 FlowViewer 安装。
使用 FlowViewer
正确安装后,FlowViewer 应该看起来像图 7-1。

图 7-1. 默认 FlowViewer 界面
屏幕上半部分,过滤条件,控制流量选择。这基本上是flow-nfilter的接口,让您选择您想要检查的确切流量。FlowGrapher 和 FlowTracker 与 FlowViewer 的过滤接口共享大部分功能。屏幕下半部分,报告参数,控制结果的显示。您可以对流量运行报告或仅查看匹配的流量。
在以下章节中,我将首先介绍如何使用过滤界面,然后是查看选项。
使用 FlowViewer 过滤流量
您在过滤条件部分修改的每个字段都会传递给flow-nfilter。大多数字段接受多个条目,条目之间用逗号分隔。您还可以通过在条目前加负号来否定一个条目。(如果您对过滤流量有一般性问题,请参阅第四章。)
设备
如果您有多个传感器,您必须首先选择提供您想要检查的数据的设备。此下拉菜单直接来自您为 FlowViewer 配置的设备或导出列表,并且是唯一需要您输入内容的字段。
下一跳 IP
这是传感器发送流量的 IP 地址。请记住,只有硬件流量传感器(如路由器和交换机)在流中包含下一跳地址信息。软件流量传感器无法访问此信息。
开始和结束日期和时间
在这里,您设置您感兴趣的时间。时间以 24 小时制格式表示。FlowViewer 默认提供最近的完整小时。请参阅包含流量如果中的包含流量如果,了解 FlowViewer 如何处理跨越开始或结束时间的流量。
TOS 字段、TCP 标志和协议
FlowViewer 的服务类型(DSCP)和 TCP 标志过滤接受十进制值(16)和十六进制值(0x10)。
您可以通过名称(TCP、UDP 等)或数字(6、17 等)输入 IP 协议。
源和目标 IP
您可以报告单个地址、主机名、多个以逗号分隔的地址,或者带有前缀长度的网络(斜杠表示法)中的网络。例如,要报告来自网络 192.0.2.0 且子网掩码为 255.255.255.128 的流量,您将输入192.0.2.0/25。
备注
在使用主机名进行网络分析时,请务必非常小心。一些主机有多个 IP 地址。在这种情况下,您最好使用实际的 IP 地址以减少歧义。
源和目标接口
如果您认为您知道您的流量是如何流动的,您可以通过源或目标接口进行过滤。当您这样做时,请记住接口是通过索引号进行编号的,您可以从 SNMP 中获取这些索引号。您可以将接口名称添加到 FlowViewer 中,我将在本章末尾讨论这一点。
我最常在分析问题和故障时使用 FlowViewer。在这种情况下,我建议不要按接口过滤,因为流量错误是问题和故障的常见原因,按接口过滤可能会过滤掉问题流量。
源和目的端口以及 AS
FlowViewer 可以按 TCP 或 UDP 端口进行过滤。您还可以将 ICMP 类型和代码编码为端口,如 ICMP 类型和代码及流量记录中所述,并使用它来过滤 ICMP 流量。此外,如果您的传感器导出 BGP 信息,您还可以按源和目的 AS 号进行过滤。
报告参数
FlowViewer 可以提供统计报告或打印报告。这两种类型的报告共享剩余的选项设置。我将首先介绍选项,然后讨论两种类型的报告。您一次可以运行一个报告,但如果您同时选择统计报告和打印报告,FlowViewer 将返回错误。
包含流量条件
此设置确定 FlowViewer 如何选择要报告的流量。默认的“指定时间段内任何部分”设置,如果流量的任何部分在您指定的时间范围内,就会包含流量记录。例如,如果您对 9 到 10 点的流量数据感兴趣,您的原始数据可能包括一个从 8:59:30 开始到 9:01:30 结束的流量,以及一个从 9:59:59 开始到 10:05:59 结束的流量,其中这些流量的部分在您选择的时间窗口两端。
大多数情况下,默认设置可以提供您选择时间段内交通状况的最佳视图。当使用默认设置时,这些流量将会包含在过滤后的数据中。另一方面,指定时间段结束时间设置会截断任何超出关闭窗口的流量。具体来说,在这个例子中,从 9:59:59 开始到 10:05:59 结束的流量将不会包含在所选数据中。指定时间段开始时间设置会截断从 8:59:30 开始的流量,而完全在指定时间段设置会排除这两段尾随流量。
排序字段、解析地址、字节转换和采样倍数
与flow-report类似,FlowViewer 可以根据任何字段对输出进行排序,输出列从 1 开始编号。要按特定字段排序,请在排序字段区域输入您想要排序的列号。
一些报告可以将 IP 地址替换为主机名,但默认情况下,FlowViewer 会解析名称。要使 FlowViewer 只显示 IP 地址,请将解析地址更改为N。同样,FlowViewer 默认将大字节数显示为千字节、兆字节或吉字节,而不是数百万或数十亿字节的原始计数。要查看原始字节数,请将字节转换设置为N。(以千字节、兆字节或吉字节显示结果不会影响排序;FlowViewer 足够智能,可以正确地对不同单位进行排序。)
如果你的传感器采样流量,你知道你报告中显示的流量水平只是你实际流量的一个小部分。FlowViewer 会将其结果乘以你在采样倍数中输入的数字,以近似你的真实世界流量。
饼图
FlowViewer 的统计报告可以生成结果饼图,但饼图对于 FlowViewer 报告来说并不实用;它们就像制作电话簿的饼图。对于统计报告,你可以选择在你的图表中包含一个“其他”的通用类别。尝试两种方法,看看哪种在你的环境中生成最有用的图表。
截止值
如果你有一个繁忙的路由器,即使是经过良好过滤的报告也可能包含数十万个流量。在这种情况下,截止值非常有用,因为它们告诉 FlowViewer 何时停止打印结果。你可以通过输出行数或字节数来截断报告。
如果你真的想拥有所有这些数据,考虑从命令行运行报告并将结果保存到文件以供以后分析。
打印报告
FlowViewer 的打印报告是 flow-print 的网络界面。表 7-1 将 FlowViewer 的打印报告映射到 flow-print 格式。第三章 详细介绍了各种打印格式。
表 7-1. 打印报告和 flow-print 格式
| 打印报告 | flow-print 格式 |
|---|---|
| 流量时间 | -f 1 |
| AS 号码 | -f 4 |
| 132 列 | -f 5 |
| 带标签的 1 行 | -f 9 |
| AS 聚合 | -f 10 |
| 协议端口聚合 | -f 11 |
| 源前缀聚合 | -f 12 |
| 目的端口前缀聚合 | -f 13 |
| 前缀聚合 | -f 14 |
| 完整(Catalyst) | -f 24 |
注意,并非所有报告都会产生输出。例如,如果你的流量数据不包含 BGP 信息,而你运行了一个基于 BGP 的报告,你将得到一个空报告。
统计报告
FlowViewer 的统计报告基于 flow-stat,它是 flow-report 的前身。flow-stat 相比 flow-report 要少很多灵活性,但其中一些报告更适合用于网络应用。大多数 flow-stat 分析都可以作为 flow-report 输出格式的子集使用,具体请参见 表 7-2。
表 7-2. FlowViewer 统计报告和相应的 flow-reports
| 统计报告 | flow-report |
|---|---|
| 摘要 | summary (默认) |
| UDP/TCP 目的端口 | ip-destination-port |
| UDP/TCP 源端口 | ip-source-port |
| UDP/TCP 端口 | ip-port |
| 目的 IP | ip-destination-address |
| 源 IP | ip-source-address |
| 源/目的 IP | ip-source/destination-address |
| 源或目的 IP | ip-address |
| IP 协议 | ip-protocol |
| 输入接口 | input-interface |
| 输出接口 | output-interface |
| 输入/输出接口 | input/output-interface |
| 源 AS | source-as |
| 目的 AS | destination-as |
| 源/目的 AS | source/destination-as |
| IP ToS | ip-tos |
| 源地址前缀 | 类似于 ip-source-address,其中 ip-source-address-format 设置为 prefix-len |
| 目的地址前缀 | 类似于 ip-destination-address,其中 ip-destination-address-format 设置为 prefix-len |
| 源/目的地址前缀 | 类似于 ip-source/destination-address,其中 ip-source-address-format 和 ip-destination-address-format 都设置为 prefix-len |
| 导出器 IP | ip-exporter-address |
注意
如果您需要这里没有提供的报告,请使用 flow-report。
FlowGrapher
FlowGrapher 创建任意流数据的图表。从 FlowViewer 页面顶部的标志中选择 FlowGrapher 文本,即可进入 FlowGrapher。
FlowGrapher 设置
FlowGrapher 页面的上半部分允许您根据需要定义数据包过滤器。FlowGrapher 过滤器与在 图 7-1 中列出的 FlowViewer 过滤器定义相同,因此我不会再次详细说明,但 FlowGrapher 页面的底部提供了新的图形选项,如图 图 7-2 所示。

图 7-2. FlowGrapher 选项
如果包含流、解析地址和采样乘数与 FlowViewer 中的等效字段工作方式相同。FlowGrapher 独有的选项——详细行、图宽和样本时间——决定了您的图表如何绘制、其外观以及如何呈现任何相关数据。
详细行
FlowGrapher 在图表下方打印所选流文件的 flow-print 输出的前几行。此列表让您验证图表是否包含您认为应该包含的流。
图宽
默认的 FlowGrapher 图像宽度为 600 像素,但覆盖超过几个小时的数据的图表必须更宽,以便显示必要的细节。图宽设置将图表宽度乘以所选的数字。例如,选择 3 将创建一个宽度为 1,800 像素的图表。
样本时间
FlowGrapher 通过时间“桶”来计算带宽,以平滑数据并呈现更真实的图表。(您将在 第八章 中看到为什么这很重要。)默认的桶大小为五秒,对于几乎所有环境来说都是合理的。更大的桶大小将减少带宽峰值的大小,如果您的流量大部分由长时间存在的流组成,这可能更真实。
图形类型
您可以选择每秒比特数(默认)、每秒流数或每秒数据包数图表。大多数情况下,您会想要每秒比特数,但如果您的环境中有很多小数据包,您可能会发现每秒数据包数图表很有用。每秒流数主要用于确定您是否有比平时更多的或更少的活动。
FlowGrapher 输出
图 7-3 展示了我的服务器的流量图,没有标志或样本 flow-print 输出。

图 7-3. 样本流量图
注意 FlowGrapher 如何在图表上方打印所选的过滤器标准。这些信息让您能够轻松地以略有不同的条件重新创建图表,并在您稍后返回图像时提醒您尝试绘制的内容。
注意
要创建超出 FlowGrapher 容量的流量图,请参阅第八章。
FlowTracker
FlowTracker 不断生成基于 RRD 的流量数据图表,类似于 FlowScan 和 CUFlow。您创建的每个图表都称为 跟踪器。一个跟踪器可以绘制入站或出站流量,但不能同时绘制两者。FlowTracker 比 FlowScan 更灵活,但这种灵活性也使其不适合客户或管理层直接访问。
FlowTracker 进程
与 FlowScan 类似,FlowTracker 在创建 flow-capture 文件时创建 RRD 文件。然而,FlowTracker 不是移动流文件,而是使用两个进程来监视 flow-capture 目录的变化,并在每个新流文件关闭时读取它。如果这些进程停止,FlowTracker 将不会更新新流的 RRD,也不会创建新的图表。
在系统启动时启动 FlowTracker_Collector 和 FlowTracker_Grapher 进程。包含的 flowcap 脚本可能适用于您的操作系统,如果不适用,您可以按照以下方式启动它们:
#!/bin/sh
PERL5LIB=/usr/local/www/flowviewer/ /usr/local/www/flowviewer/FlowTracker_Collector &
PERL5LIB=/usr/local/www/flowviewer/ /usr/local/www/flowviewer/FlowTracker_Grapher &
在网络初始化后开始这些进程。让您的网络管理系统监控这些进程,如果它们失败,则发送警报或自动重启它们。
FlowTracker 设置
FlowTracker 提供与 FlowViewer 和 FlowGrapher 相同的过滤选项,但没有选择您想要覆盖的时间的选项。(由于 FlowTracker 持续处理流数据,基于时间的过滤没有意义。)FlowTracker 根据您定义的过滤器创建图表,就像 FlowGrapher 和 FlowViewer 一样。
图 7-4 展示了 FlowTracker 特定的配置选项。

图 7-4. FlowTracker 选项
一旦您设置了所需的参数,点击建立跟踪以启动您的跟踪器。
跟踪集标签
跟踪集标签是跟踪器的名称。你应该根据主机、网络或流量名称以及流量流动的方向来命名跟踪器,例如“服务器 1 Web 流量入站”或“服务器 2 出站”。你在此处输入的文本将作为链接出现在主 FlowTracker 页面上,指向实际的跟踪器。
跟踪类型
FlowTracker 可以将单个跟踪器聚合为“分组跟踪器”。我将在后面介绍分组跟踪器;现在,所有跟踪器都应该是个体。
采样乘数
与 FlowViewer 的其他部分一样,FlowTracker 可以对图表应用采样乘数来近似正确的流量水平。
警报阈值
作为持续运行的过程,FlowTracker 可以监控总流量水平,并在流量超过一定水平时发送警报。在此处输入每秒比特数来设置警报。请注意,你的服务器必须有一个正确配置的邮件系统来发送警报。
警报频率
每当流量超过你的临界水平时,如果流量负载在该水平上下波动,频繁地发出警报可能会令人烦恼。使用警报频率来告诉 FlowTracker 每次流量超过临界限制时发送警报,每天只发送一次,或者完全禁用电子邮件警报。
警报目的地
这是接收警报的电子邮件地址。
一般评论
此处任何备注或评论都将出现在完成的图表上。
查看跟踪器
你已经创建的跟踪器将出现在 FlowTracker 页面的底部。图 7-5 显示了两个机器的入站和出站跟踪器。

图 7-5. FlowTracker 个体跟踪
要查看跟踪器,请点击其名称。跟踪器包括过去 24 小时、7 天、4 周、12 个月和 3 年的视图。每个图表看起来与 FlowGrapher 输出非常相似,所以这里不会重现那些图表。
你可以编辑跟踪器来更新过滤器或纠正错误。为此,点击跟踪器旁边的修订链接,以便在 FlowTracker 页面上填充跟踪器的原始设置,然后进行所需的更改。你还可以添加一个备注,在图表上显示跟踪器何时被更改。
存档跟踪器告诉 FlowTracker 停止处理此特定跟踪器的当前流,同时继续更新其他跟踪器。它保留存档跟踪器的配置和图表。存档让您能够保留历史信息,而不会浪费计算能力,并在需要时轻松重新激活跟踪器。
最后,你也可以通过点击链接完全删除跟踪器。这将删除所有图表和相关数据库。
分组跟踪器
FlowTracker 允许您将单个跟踪器组合成组跟踪器,以提供不同类型流量的统一视图。例如,在图 7-5 中,您可以看到两个服务器的单独入站和出站跟踪器。要同时查看服务器的入站和出站流量,您需要使用组跟踪器。
要创建组跟踪器,请命名跟踪器,并选择组类型的跟踪方式。接下来,当您点击建立跟踪时,FlowTracker 将打开一个单独的页面来定义您的组跟踪器,如图图 7-6 所示。

图 7-6. 基本 FlowTracker 设置
图 7-6 顶部显示的示例图形不是基于实际数据,但它将展示您的颜色选择在实际图形上的外观。
图形下方是关键组件。在这里,您可以选择要包含在您的组跟踪器中的单个跟踪器,或者选择跟踪器出现在 x 轴的上方或下方。我尽量将入站跟踪器放在 x 轴上方,出站跟踪器放在下方,以减少混淆。如果您更喜欢,可以切换这些设置;只需选择一个标准并坚持下去。
您可以为您的图形中的每个跟踪器分配颜色。自动选项选择同一颜色家族中的颜色。我建议为所有入站跟踪器使用一个自动颜色,并为所有出站跟踪器使用不同的自动颜色。
一旦您将单个跟踪器添加到您的组跟踪器中,请点击添加此组件。然后,立即在此选项下方,您将看到该组跟踪器中所有单个跟踪器的列表。例如,图 7-7 显示了我添加了两个个人服务器的入站和出站跟踪器后的这个组跟踪器。

图 7-7. 组跟踪器组件
火炬和 bewilderbeast 服务器现在将出现在这个跟踪器中。入站跟踪器将出现在 x 轴上方,如长水平线所示。颜色名称出现在所选颜色中(当然,在这个黑白图形中不会出现)。如果您不喜欢这个颜色,可以使用新颜色下拉菜单进行更改。
使用最右侧的移动下拉菜单重新排列服务器顺序,然后点击调整组以应用您的更改。我建议在跟踪器的入站和出站两侧保持服务器顺序一致。
一旦您配置了您的组跟踪器,请点击页面底部的完成以创建跟踪器。您可以对您的组跟踪器进行修改、存档和删除,就像对个人跟踪器一样。
ADDITIONAL RRD SOFTWARE
不同的工具有不同的展示方式和侧重点。如果你觉得 FlowTracker 并不完全适合你的长期跟踪需求,可以看看 Webview Netflow Reporter,网址为wvnetflow.sourceforge.net/。
接口名称和 FlowViewer
流量通过索引号管理接口,但人类使用接口名称。如果你告诉 FlowViewer 与每个接口号关联的名称,它将在 Web 界面中提供这些名称作为选项。如果你在FlowViewer目录中创建名为NamedInterfaces_Devices的文件,FlowViewer 将使用文件中的信息填充所有三个工具过滤器部分的接口名称下拉菜单。
NamedInterfaces_Devices文件中的每一行包含三个条目:
exporter name:SNMP index:human-friendly name
例如,我主路由器的千兆上行链路位于 SNMP 索引号 5。这个接口的条目可能看起来像这样:
core-4:5:Gigabit Ethernet 1/0 - uplink
将所有导出器的接口信息输入到 FlowViewer 中,将为你未来的问题解决带来便利并简化问题。你不必查找你感兴趣的接口的编号,只需从菜单中选择即可。
FlowTracker、FlowViewer 和 FlowGrapher 可以让你可视化大多数常见情况,但它们并不能解决所有问题。在下一章中,你将看到当 FlowGrapher 不够强大或不够灵活时如何绘制数据。
第八章。即兴流量可视化

虽然查看流量内容和运行报告有助于追踪问题,但某些问题只能通过可视化来正确评估。普通的人类大脑根本无法将 6,000 行纯文本数据组合成一个对情况的连贯理解。将大量数据转换为视觉形式可以简化理解。
将数据转换为图形形式最常见的方式可能是通过办公套件,例如 Microsoft Office 或 OpenOffice.org。然而,办公套件并不适合自动化。一旦你设计好了你的图表,用新数据重新生成它们应该是简单或甚至是瞬间的。CUFlow (第六章) 和 FlowGrapher (第七章) 这样的工具提供了基本的绘图功能,但它们缺乏真正的即兴灵活性,例如选择图表样式或是否将一个图表叠加在另一个图表之上。要提供真正无限的灵活性,并且能够自动化或快速重现,你需要 gnuplot。
gnuplot 101
gnuplot (www.gnuplot.info/) 以其陡峭的学习曲线和复杂性著称。这种恶名和声誉并非完全无根据。然而,gnuplot 的强大和效率足以弥补其挑战。虽然掌握 gnuplot 可能需要数年,但你可以快速学习到足够多的知识来创建你网络数据的令人印象深刻的图表。几乎每个类 Unix 的操作系统都包括当前的 gnuplot 软件包,你还可以找到适用于 Windows、DOS、VMS 以及过去 20 年中使用的几乎所有其他操作系统的软件包。
在报告服务器上使用 gnuplot 可以简化报告和图表的开发。要在你的报告服务器上使用 gnuplot,你需要在你的工作站上有一个 X 服务器。如果你使用的是 Unix 工作站,那么你已经准备好了。如果不是,你可以找到许多适用于 Microsoft Windows 的 X Windows 服务器。务必选择一个可以转发 X 通过 SSH 的服务器,而不是在网络中直接传输原始 X。(在 Windows 上,我使用 PuTTY SSH 客户端和 Xming X 服务器。)
如果你不想在桌面上的 X 终端上使用 gnuplot,请在你的工作站上安装 gnuplot,然后在服务器上运行报告并将它们传输到你的工作站。在你的工作站上开发图表,保存它们的配置,并将这些配置复制到你的服务器上以自动创建更多图表。
其他绘图程序
gnuplot 的主要优势是它易于自动化。为了即时创建图表而不用担心以后的重现,请考虑 Grace (plasma-gate.weizmann.ac.il/Grace/)。
启动 gnuplot
学习 gnuplot 的最好方法是使用它。当 gnuplot 启动时,它会显示一条消息并提供一个自己的命令提示符。
# `gnuplot`
...
Terminal type set to 'x11'
gnuplot>
要退出 gnuplot,请输入 exit 或 quit。
大多数 gnuplot 命令要么改变图表的外观,要么创建一个新的图表。为了体验 gnuplot 的工作方式,绘制一个正弦波。 (出于某种原因,正弦图在 gnuplot 教程中是传统的。) 在 gnuplot 命令行中,输入以下内容:
gnuplot> `plot sin(x)`
您应该会看到一个新窗口出现,显示经典的正弦波,如图 图 8-1 所示。

图 8-1. 正弦波
要修改您的图表,请使用 set 命令。您可以设置无数个值,从图表的标题到 x 轴和 y 轴的标签,使用的颜色等等。在这里,我正在给图表添加标题 test graph:
gnuplot> `set title "test graph"`
显示的图表在你告诉 gnuplot 重新绘制数据之前不会改变,就像这样:
gnuplot> `plot sin(x)`
现在您的图表应该有一个标题。
gnuplot 配置文件
您在这里创建的测试图表几乎不需要任何努力。您没有读取任何数据或输入复杂的公式。然而,流量数据比正弦波复杂得多,在本章中,您将通过多次迭代您的图表来使其看起来“恰到好处”。您可以从 gnuplot 会话中保存所有设置,以便您可以调用相同的设置并使用它们来绘制新的数据。只需告诉 gnuplot 您想保存配置的文件名即可。
gnuplot> `save "test.plt"`
您将在当前目录中找到一个名为 test.plt 的 gnuplot 配置文件。此文件包含您输入的所有 gnuplot 命令,包括标题和 plot sin(x) 指令。退出 gnuplot,然后重新启动它。然后加载此配置文件:
gnuplot> `load "test.plt"`
您指定的所有更改都会在图表中重新出现。
重新输入两个命令来重新创建您的图表并不困难,但基于流量报告的图表可能包含数十条指令,其中一些可能很长且繁琐。能够保存您的 gnuplot 配置并重新使用它来绘制新的数据将节省时间和精力,并减少错误。
现在让我们获取一些实际的数据来绘制图表。
时间序列示例:带宽
网络工程师经常遇到的一个常见问题是“这个应用程序使用了多少带宽?” 我在多个全球运营中工作过,管理层关心电子邮件消耗了多少内部带宽,或者 Active Directory 团队需要知道域间控制器通信使用了多少带宽。
流量报告可以通过许多不同的方式回答这个问题。一天中带宽使用的平均值很有用,但不会揭示间歇性的性能瓶颈。一个大部分时间都处于空闲状态,但在每天高峰时段有大量吞吐量波峰的连接,其平均吞吐量可能约为 50Kbps。一天的平均值既准确又无意义。回答这个问题的最佳方式是使用图表。
你将从调查在特定 24 小时期间,你的桌面 DHCP 范围与内部网络上远程站点的 Active Directory 域控制器之间使用了多少带宽开始。这是一个网络工程师经常遇到的具体问题示例,你可以使用这种技术来回答任何与带宽相关的问题。你将从查看总带宽报告中的总入站和出站流量开始。
总带宽报告
每次你想创建一个随时间变化的带宽、数据包或流量的图表时,获取数据的最佳方式是使用linear-interpolated-flows-octets-packets报告(在第五章中讨论)。此报告产生了一个关于所选流量数据中每秒八位字节、流和数据包数量的良好估计。你特别感兴趣的是每秒带宽(八位字节),因此你可以使用以下stat.cfg配置来生成此信息:
stat-report octets
type linear-interpolated-flows-octets-packets
output
❶ fields -packets,-flows
path |/usr/local/bin/flow-rptfmt
sort -key
stat-definition octets
report octets
由于你感兴趣的是传输的字节数,你从❶报告中删除了数据包和流计数。其他设置是flow-report的默认设置。接下来,你需要决定将什么数据输入到报告中。
过滤总流量中的流量
假设你想要绘制你的桌面 DHCP 范围与几个远程主机之间的带宽使用情况图。为了从你的流量数据中过滤出这些主机,你将使用这些主机的原语。
filter-primitive localDesktops
type ip-address-prefix
permit 172.17.3/24
permit 172.17.4/23
filter-primitive remoteDC
type ip-address
permit 172.18.0.10
permit 172.18.0.11
...
你需要一个用于远程域控制器的过滤器和一个用于桌面的过滤器。(你可以编写一个捕获从桌面到域控制器并返回的流量的单个过滤器,但通常两个独立的过滤器更易于重用。)
filter-definition desktops
match src-ip-addr desktops
or
match dst-ip-addr desktops
filter-definition remoteDCs
match src-ip-addr remoteDC
or
match dst-ip-addr remoteDC
现在将你选择的日期的流量通过这些过滤器以及你的插值八位字节flow-report运行。你正在报告 2011 年 1 月 14 日的所有流量。
# `flow-cat ft-v05.2011-01-14.* | flow-nfilter -F desktops | flow-nfilter -F`
`remoteDCs | flow-report -S octets > desktop-DC-traffic.txt`
文件顶部应类似于以下内容:
# ['/usr/local/bin/flow-rptfmt']
unix-secs octets
1294981479 168.000000
1294981610 30.000000
...
1295066753 15.000000
1295066757 367.000000
左侧的数字是 Unix 纪元秒。为了验证报告时间,使用date程序将第一个和最后一个数字转换一下。
# `date -r 1294981479`
Fri Jan 14 00:04:39 EST 2011
# `date -r 1295066757`
Fri Jan 14 23:45:57 EST 2011
第一个匹配的流量在午夜后四分钟开始,最后一个流量在几乎 11:46 pm结束,都是在 1 月 14 日。报告涵盖了您感兴趣的时间段。
gnuplot将无法处理此文件的列名,因为unix-secs和octets不是可绘制的数字。处理这个问题最简单的方法是手动或使用sed删除前两行。(尽管手动编辑文件在手动创建图表时可能更容易,但sed可以自动化。)
# `sed '1,2d' desktop-DC-traffic.txt > octets.txt`
目标图表
你希望图表看起来是什么样子?它应该清楚地显示使用了多少带宽。坐标轴应该标注时间以及带宽测量的单位,图表本身也应该有一个标签。如果你想让人真正关心你的图表,时间应该是本地时钟时间,而不是纪元秒或格林威治平均时间(GMT)。如果图表对不同类型的流量有不同的线条,应该有一个解释键。所有这些都应该自动生成。哦,顺便说一下,你还会使数据准确且有意义。
第一张图:未达到目标
首先创建一个默认的 gnuplot 图表来展示你的数据,并将其与你的期望结果进行比较。
gnuplot> `plot "octets.txt"`
在任何给定时间,带宽由一个点表示,如图 图 8-2 所示。基于每秒的带宽利用率太不规则,不适合绘制平滑的曲线,但稍后你将学习如何使用除点以外的标记来绘制图表。

图 8-2. 原始吞吐量图
两个坐标轴都没有标签;从你所能看到的,默认图表可能代表苹果与石榴。此外,底部的沿时间看起来像纪元秒,例如 1.2319E+08,而不是有用的时间。从严格意义上讲,纪元秒是准确的,但并不是你想要给你的同事看的东西。你将迭代地改进图表,首先在两个坐标轴上设置标签,然后告诉 gnuplot 如何格式化时间。
❶ gnuplot> `set xdata time`
❷ gnuplot> `set timefmt x "%s"`
❸ gnuplot> `set format x "%H"`
❹ gnuplot> `set xlabel "time"`
❺ gnuplot> `set ylabel "bytes"`
❻ gnuplot> `plot "octets.txt" using ($1):($2)`
你首先告诉 gnuplot ❶ 横轴上的数据代表时间。然后,在 ❷ 你告诉 gnuplot 横轴上时间数据的格式。字符 %s 是 gnuplot 的时间格式,代表纪元秒,它为 gnuplot 提供了将纪元秒转换为人类友好时间所需的信息。gnuplot 可以以 flow-rptfmt(见 第五章)使用的相同 strftime 格式打印时间度量。对于覆盖 24 小时的图表,打印小时是一个合理的选择,你在 ❸ 设置了该格式。然后你在 ❹ 和 ❺ 标注了 x 轴和 y 轴。
现在你已经开始了复杂化的操作,你需要告诉 gnuplot ❻ 如何在你的文件中绘制数据。跟随数字的美元符号表示数据列。($1) 表示“第 1 列”,而 ($2) 表示“第 2 列”。语句 plot "octets.txt" using ($1):($2) 告诉 gnuplot 读取 octets.txt 并将第一列与第二列进行绘图。结果看起来像 图 8-3。

图 8-3. 带有基本标签的流程图
此图表更接近之前描述的目标图表。x 轴以字节为单位标注,y 轴以可读时间标注。请注意,底部的时间与报告中的数据不匹配。流量数据在午夜后不久开始,在午夜前结束,但此图表从大约早上 5 点开始,并在 24 小时后结束。这是一个时区问题。我在东部标准时间(EST),而gnuplot生成的图表是协调世界时(UTC)。此图表需要显示本地时间。此外,我购买的是千比特而不是千字节。尽管千字节标签是准确的,但我希望图表显示千比特。
要将协调世界时(UTC)转换为东部标准时间(EST),您需要减去 5 小时,即每个值减去(5 × 60 × 60 =)18,000 秒。您需要将数据中列出的所有时间减去 18,000 秒,以便图表显示准确的时钟时间。要将字节转换为千比特,您需要除以 125。 (一个字节有 8 位,一个千比特有 1,000 位:1,000 / 8 = 125。)您可以将这两个转换设置为gnuplot中的常量,以便在绘图时转换数据。(别忘了在更改测量单位时更改 y 轴的标签。)
❶ gnuplot> `edt = −18000`
❷ gnuplot> `kb = 125`
❸ gnuplot> `set ylabel "kb"`
gnuplot> `plot "octets.txt" using ($1+edt)` ❹ `:($2/kb)` ❺
首先,您定义一个从 EST 到 UTC 之间的秒数常量(❶)以及一个每千比特的八位常量(❷)。
接下来,因为您正在将 y 轴的测量单位从字节更改为千比特,所以您也更改了 y 轴标签,如图❸所示。
困难的部分是告诉gnuplot在绘图时更改数据。之前,您将第一列与第二列绘图。您通过将时区偏移量加到该列的每个值上来转换第一列(❹)。您通过除以常量kb(❺)来转换第二列。您不更改octets.txt文件中的数字;您在它们到达图表的过程中进行转换。
当您在这里时,您可以做一些其他更改,例如分配一个标题并给图表添加网格。
gnuplot> `set title "Traffic between desktops and remote DCs, 14 Jan"`
gnuplot> `set grid`
gnuplot> `replot`
您将得到图 8-4 中所示的图表,乍一看与图 8-2 中的图表相似,但具有更合适的时间和更有用的带宽测量,这使得它更适合与同事分享。

图 8-4. 使用更好的时间、带宽单位、网格和标题的网络利用率
改变图表的绘制方式
虽然我喜欢由单独的点组成的图表,但许多人更喜欢不同的图表风格。gnuplot 支持几乎无限数量的图表风格。一种流行的带宽图表风格是使用实线,称为脉冲,来表示任何给定时间的带宽使用情况。在这里,我正在创建与之前完全相同的图表,但使用脉冲:
gnuplot> `plot "octets.txt" using ($1+edt):($2/kb) with impulses`
除了指定脉冲之外,这个命令完全相同。
你会得到一个如图图 8-5 所示的图表。有些人会发现这种图表风格更容易理解。只需使用你大脑适应的任何格式即可。

图 8-5. 使用脉冲的网络利用率
裁剪级别
你可能已经注意到在图 8-5 中,一些数据点与平均值差异很大。如果你检查原始数据,你会发现有几个连接只有三或四个数据包。在一毫秒内传输四个八位字节与在一秒内传输 4,000 个八位字节不同,但这就是在大部分空闲网络上简单的“每秒平均八位字节”计算产生的结果。
为了消除这些异常值,你可以设置一个合理的裁剪级别来创建一个更真实的图表。为此,你将使用 gnuplot 内置的逻辑运算符,格式如下。(Perl 和 C 爱好者应该熟悉这种语法。)
(a ? b : c )
这表示“a 是否为真?如果是真的,则使用 b。如果不是真的,则使用 c。”
在评估了第一个图表及其下的数据峰值之后,你可能会决定希望你的图表最大值为,比如说,300Kbps,并且如果值超过 300Kbps,则应将其视为 300。用之前的语法翻译,你有以下内容:
( $2/kb>300 ? 300 : $2/kb)
$2/kb 是千比特带宽。使用 >300 ?,你可以检查带宽是否超过 300。如果超过,则使用值 300。如果没有超过,则使用实际的 $2/kb 值。
要让 gnuplot 为你执行此检查,请在 plot 语句中输入它。
gnuplot> `plot "octets.txt" using ($1+edt):($2/kb>300 ? 300 : $2/kb ) with impulses`
你会得到一个如图图 8-6 所示的图表。

图 8-6. 使用裁剪级别的网络利用率
通过设置裁剪级别,你可以得到一个更真实反映你实际带宽使用的图表。
裁剪级别和多个图表
当创建用于比较的图表时,所有图表应使用相同的裁剪级别。不同的裁剪级别会混淆结果。
将图表打印到文件
gnuplot 支持广泛的图形格式。要查看您版本支持的完整列表,请在 gnuplot> 提示符下输入 set terminal。网站最常用的三种格式是 GIF、JPEG 和 PNG。
要让 gnuplot 将图形打印到文件而不是屏幕上,告诉 gnuplot 文件类型和名称。在这里,您将图形保存为 JPEG 文件:
❶ gnuplot> `set terminal jpeg`
Terminal type set to 'jpeg'
Options are 'nocrop medium '
❷ gnuplot> `set output "bandwidth.jpeg"`
❸ gnuplot> `replot`
❹ gnuplot> `set terminal x11`
❶ 处的 set output 语句告诉 gnuplot 要生成哪种类型的输出,❷ 处的 set output 语句说明将输出放在哪里。要实际创建文件,您需要让 gnuplot 在❸处重新绘制图形。最后,在❹处您设置终端再次将输出显示到屏幕上。
保存您的作品!
您可以使用此配置轻松生成非常相似的图形。将其保存为未来报告的基础。
gnuplot> `save "totalBW.plt"`
单向带宽报告
图 8-6 中的图形显示了桌面和远程站点域控制器之间通信使用的总带宽。如果您只想查看单向使用的带宽报告,比如从服务器到桌面或从桌面到服务器,怎么办?
您生成的报告与上一节中生成的总带宽报告没有太大区别。要创建报告,您将使用 flow-nfilter 配置来提取感兴趣的数据,将其输入到您的八位字节 flow-report,然后将其输入到一个非常相似的 gnuplot 配置中。
过滤单向流量
过滤器配置使用与总带宽报告相同的 desktops 和 remoteDCs 基本元素。如所示,您创建了两个新的过滤器,每个方向一个:
filter-definition DCtoDesktops
match src-ip-addr remoteDC
match dst-ip-addr desktops
filter-definition DesktopsToDC
match src-ip-addr desktops
match dst-ip-addr remoteDC
第一个过滤器仅显示域控制器发送到桌面的流量;第二个过滤器显示桌面发送到域控制器的流量。现在您运行这些新过滤器之一对相同的流量文件进行操作,从域控制器到桌面的流量开始。
# `flow-cat ft-v05.2011-01-14.* | flow-nfilter`
`-F DCtoDesktops | flow-report -S octets > DCtoDesktop.txt`
# `sed '1,2d' DCtoDesktop.txt > octets.txt`
您可以使用相同的 sed 命令来删除文件顶部额外的两行。最后,验证数据文件的内容是否与您之前报告中的内容相似:包含时间戳和带宽数量的两列。
创建单向图
单向流量图应该非常类似于总带宽图。实际上,要生成最终图形,您只需修改现有的 gnuplot 配置并更改标题。
❶ gnuplot> `load "totalBW.plt"`
❷ gnuplot> `set title "DC to Desktop Traffic, 14 Jan 11"`
❸ gnuplot> `replot`
您首先在❶处加载用于总带宽图的配置。此配置为您提供正确的时间、比特而不是八位字节等。接下来,在❷处更改标题,在❸处使用新数据创建一个新的图形。结果将类似于 图 8-7。

图 8-7. 单向带宽使用图
如你所见,使用不同的数据重用gnuplot配置是一种快速生成外观一致但数据不同的图表的方法。
要创建一个显示相反方向流量的图表,你几乎会做同样的事情;只需更改图表标题和流量过滤器。
结合入站/出站流量
同时显示入站和出站流量的图表可能比只显示单向流量的图表更有用。你已经有数据了;要生成显示双向流量的图表,你只需要一个稍微不同的gnuplot配置。
准备数据文件
如果你创建两个单向图表,你将已经有你需要的数据文件,你本质上会这样做。你不能将两个数据文件都命名为octets.txt;然而,你需要给每个文件一个独特的名称。由于你在测量本地和远程主机之间的流量,让我们将其中一个命名为inbound.txt,另一个命名为outbound.txt。使用sed从原始数据文件中删除标题,但其他数据保持不变。
# `flow-cat ft-v05.2011-01-14.* | flow-nfilter`
`-F DCtoDesktops | flow-report -S octets > DCtoDesktop.txt`
# `flow-cat ft-v05.2011-01-14.* | flow-nfilter -F DesktopsToDC`
`| flow-report -S octets > DesktopToDC.txt`
# `sed '1,2d' DCtoDesktop.txt > inbound.txt`
# `sed '1,2d' DesktopToDC.txt > outbound.txt`
同时显示两个图表
要同时显示两个图表,首先从你的单向图表配置开始。你将更改正在绘制的文件名,但所有其他配置信息,如时区、千比特而不是字节等,都将适用于这个新图表。
要在一个图表上绘制来自两个不同文件的两个不同数据集,在单个plot语句中用逗号分隔每个数据集,如下所示:
gnuplot> `plot "inbound.txt" using ($1+edt):($2/kb>300 ? 300 : $2/kb)` ❶ `\`
> ❷ `title "inbound"` ❸`, \`
> `"outbound.txt" using ($1+edt):($2/kb>300 ? 300 : $2/kb) title "outbound"`
此列表在此显示了几个新功能。❶处的反斜杠(\)告诉gnuplot命令将在下一行继续。如果你需要使用反斜杠来显示续行,输入反斜杠,然后按Enter键。你将被带到下一行。
在plot语句中的❷处title标签标识数据。在这种情况下,你有两种类型的数据,分别标记为inbound和outbound。❸处的逗号(,)分隔两个数据源。生成的图表看起来就像图 8-8。

图 8-8. 入站和出站流量图
根据键值,入站流量的数据点以加号(+)表示。出站流量的数据点则以x字符表示。gnuplot也会为数据点使用不同的颜色。(图 8-8 在颜色上更容易理解,但本书是黑白印刷,因为我希望它更便宜。)使用两种不同的数据点字符有所帮助,但效果有限。最好同时显示两种类型的流量,但不要混合在一起。
为了使这张图更容易一眼看懂,将出站流量表示为负数,如下所示:
gnuplot > `plot "inbound.txt" using ($1+edt):($2/kb>300 ? 300 : $2/kb) \`
> `title "inbound", \`
> `"outbound.txt" using ($1+edt):($2/kb>300 ?` ❶ `−300 :` ❷
`-$2/kb) title "outbound"`
你在这里只做了两项小的改动,在你的出站图表的绘图语句中放置了❶和❷的负号。图 8-9 显示了结果图。

图 8-9. 以负数表示出站流量的利用率图
如您从这张图中可以看到,很明显,你接收到的流量比你发送的要多得多,而且接收的频率也要高得多。入站和出站的剪辑级别没有变化,但出站流量从未接近剪辑级别。您还可以看到,在东部标准时间上午 9 点之后,您有一个很大的利用率峰值。
要以另一种方式查看这些数据,您可以像这样用脉冲来绘制图表:
gnuplot> `plot "inbound.txt" using ($1+edt):($2/kb>300 ? 300 : $2/kb) \`
> `title "inbound" with impulses, \`
> `"outbound.txt" using ($1+edt):($2/kb>300 ? −300 : -$2/kb) \`
> `title "outbound" with impulses`
结果类似于图 8-10。
使用适当的图表,任何人——甚至你的经理——都可以理解网络利用率。图 8-10 清楚地表明,桌面计算机正在与远程域控制器交换流量,尽管微软坚持认为客户端应该只联系其本地域控制器。你现在可以用有据可查的事实而不是猜测和间歇性的数据包嗅探快照来解决问题。

图 8-10. 以负数表示出站流量的脉冲利用率图
自动化图表生成
虽然您始终需要具备一些临时的报告能力,但您会发现您需要某些图表一次又一次。您应该使这些图表的生成变得如此简单,以至于您的助手可以完成它,或者您甚至可以用cron安排图表生成。管理这些图表的最佳方式是通过脚本和自动化。gnuplot非常适合脚本,以下脚本处理昨天的流量文件以生成双向流量图。
注意
这个脚本没有优化。在实际环境中,您会通过 Perl 发送电子邮件,但我不想在您可能已经在系统上有一个标准的发送邮件方式时浪费一页来介绍这个例子。此外,这个脚本使用不安全的临时文件,您不应该在共享系统上使用这样的文件。简而言之,不要直接使用此脚本;相反,将其用作编写适合您自己需求的脚本的指南,并尽可能使用您能维护的最好的 Perl。谁告诉你要听我的,对吧?
#!/usr/bin/perl
#where are our flow files?
$logdir="/var/log/flows/";
#flow file version
$version=5;
#get yesterday's date
@T=localtime(time-86400);
$year=$T[5]+1900;
$month=$T[4]+1;
unless ($month>9) {
$month = '0'.$month;
}
$day=$T[3];
$filePrefix="ft-v0$version.$year-$month-$day";
#generate the reports and prepare them for graphing
system ("flow-cat $logdir$filePrefix* | flow-nfilter -F DCtoDesktops
| flow-report -S octets > /tmp/DCtoDesktop.txt");
system ("flow-cat $logdir$filePrefix* | flow-nfilter -F DesktopsToDC
| flow-report -S octets > /tmp/DesktopToDC.txt");
system ("sed '1,2d' /tmp/DesktopToDC.txt > /tmp/outbound.txt");
system ("sed '1,2d' /tmp/DCtoDesktop.txt > /tmp/inbound.txt");
#`run gnuplot`
open GNUPLOT, "| gnuplot";
print GNUPLOT <<gnuplot_settings;
set terminal jpeg
set output "/tmp/desktop-DC.jpeg"
set xdata time
set timefmt x "%s"
set format x "%H"
set xlabel "time"
set ylabel "kb"
set title "Desktop/DC Traffic, $day $month $year"
edt = −18000
kb=125
set grid
plot "/tmp/inbound.txt" using (\$1+edt):(\$2/kb>300 ? 300 : \$2/kb) \\
title "inbound" with impulses, \\
"/tmp/outbound.txt" using (\$1+edt):(\$2/kb>300 ? −300 : -\$2/kb) \\
title "outbound" with impulses
gnuplot_settings
close GNUPLOT;
#`send mail`
system ("mutt -s \"Traffic for $day $month $year\" -a /tmp/desktop
-DC.jpeg mwlucas@localhost < /dev/null");
承认,这里的一些命令有点长,但直接从 Perl 中运行流量报告没有接口。你用教科书中的 Perl 例程替换sed,但你已经在各个地方使用system()调用了。
从run gnuplot开始,你在这个脚本中完全配置gnuplot。你也可以从文件中加载大部分gnuplot配置。
至于发送邮件(在脚本末尾),你可能已经有一个从你的服务器发送邮件的首选方式。如果没有,我推荐使用 Perl 的 MIME::Lite 模块。否则,查看mutt或metamail等程序。
比较图
比较多个时间段的交通最简单的方法是将一个图叠加在另一个图上;这样做有助于你评估系统变化对网络的影响。你也可以使用相同类型的线性插值,但需要对图形技术和时间值进行一些调整。
在以下报告中,你将比较两个不同 24 小时周期 A 和 B 的入站和出站互联网流量。数据在两个文件中:inboundA.txt和inboundB.txt。我已经从这些文件的顶部移除了列名。
数据归一化
要使图形相互叠加,你需要调整数据时间。带宽值基本没有变化,但时间值有问题。最简单的方法是从每组数据中减去一个值,使每个图从时间零开始。
当你在线性插值报告的输出部分使用sort -key时,你的文件中最早的时间出现在顶部。例如,看看inboundA.txt的顶部。
# ['/usr/local/bin/flow-rptfmt']
unix-secs octets
❶ 1229488610 1033.430171
1229488611 1033.430171
1229488612 1033.430171
...
InboundA.txt从纪元秒 1229488610(❶)开始。你从每个时间值中减去 1,229,488,610,将其转换为从零开始的偏移量。同样,inboundB.txt从纪元秒 1230179749 开始。你将这些值存储在gnuplot中,在定义常量的同时,你也会定义千字节中的字节数。
gnuplot> `inboundA=1229488610`
gnuplot> `inboundB=1230179749`
gnuplot> `kb=125`
注意
检查这些日期的各位会注意到它们大约相差一分钟。在一天交通的小图中,一分钟的差异是可以忽略不计的。如果你是在单个分钟内绘图交通或为单个小时创建宽图,你将不得不为此差异进行校正,但在这个规模上我们并不关心。
时间尺度
你想用“样本中的小时数”来标记 x 轴,但就目前情况来看,x 轴将以秒为单位进行编号。你可以通过配置gnuplot的tics将秒转换为小时。tic 是轴上的分隔符;主 tic 有标签,而副 tic 没有。之前的图形每两小时有一个标记的 tic,每小时中间有一个副 tic。让我们保持这个值:两小时是 7,200 秒。
gnuplot> `set xtics 7200`
gnuplot> `set mxtics 2`
使用这些基本标签,你现在可以绘制你的数据了。
gnuplot> `plot "inboundA.txt" using ($1-inboundA)`
`:($2/kb) with lines title "day 1 traffic", "inboundB.txt"`
`using ($1-inboundB):($2/kb) with lines title "day 2 traffic"`
结果应该看起来像图 8-11,只是颜色不同。

图 8-11. 两天不同日期的交通比较
您可以将这种比较图与同时显示进出流量的图表结合起来,从而得到两个不同时间窗口之间交通的易于理解的比较。或者,您可以将一天的交通设置为负值,以便更容易查看。您可以构建图表,展示从周一到周五,上午 9 点至下午 5 点,您的互联网流量中有多少是网页浏览,以显示用户对网络的影响。或者,您可以比较您当前的网络使用情况与去年安装新的互联网电路时的使用情况。gnuplot让您可视化您拥有的任何数据。如果您想了解更多使用gnuplot处理流量数据的复杂示例,请查找 CAIDA 工具或 FloCon(www.cert.org/flocon/)会议记录。
第九章。边和数据分析

通过本书中讨论的工具,您可以用您可能需要的任何方式分析和展示您的数据。在本章中,您将考虑几个类似系统,并学习如何将它们连接到您的流量收集器。然后,您将查看几个常见用例,说明您可以使用流量分析实现什么。
NetFlow v9
NetFlow 版本 9 主要用于 IPv6(尽管它可以扩展以包含其他类型的信息),并且很少部署。尽管大多数 NetFlow 传感器支持多个版本,如 5 或 7 以及 9,但一些制造商生产的硬件只能使用版本 9。当版本 9 得到更广泛的应用时,flow-tools 和其同类产品可能会开发对其的支持。然而,在此之前,您如何处理 NetFlow 版本 9 数据呢?
其他免费流量收集器接受版本 9 流量。您可以将版本 9 数据转换为 flow-tools 格式。我将展示如何使用 flowd^([11]) (www.mindrot.org/projects/flowd/),这是 softflowd 的作者开发的。要将您的数据转换为 flow-capture 记录文件,您首先需要安装 flowd。
安装 flowd
如果您的操作系统包含 flowd 软件包,请使用它。如果没有,您应该安装 flowd,但在安装之前,您应该安装以下软件:
-
BSD
yacc(在 Linux 系统上通常打包为byacc) -
GNU
make
是的,这是 GNU 风格的 make 加上 BSD 风格的 yacc。
flowd 软件期望以无特权的用户 _flowd 运行。在构建软件之前,请创建此用户。
一旦安装了 yacc 和 make,构建 flowd 的方式与构建 flow-tools 或 softflowd 类似。configure 脚本包含各种选项。在这里,我在 /usr/local/flowd 下构建和安装 flowd:
# `configure --prefix=/usr/local/flowd`
# `gmake`
# `gmake install`
就这些!您应该会得到一个配置文件和程序本身。
配置 flowd
在您使用命令行参数控制 flow-capture 的地方,flowd 使用配置文件。大多数 flowd 配置选项与 flow-capture 提供的选项类似。
❶ logfile "/var/flow/router-v9/current"
❷ pidfile "/var/run/flowd.pid"
❸ listen on 0.0.0.0:6789
❹ flow source 192.0.2.1
❺ store ALL
❻ accept all
flowd 将流量记录存储在日志文件中 ❶。与 flow-capture 的 ft- 文件类似,flowd 日志是一个无法直接查看的压缩二进制文件。像大多数其他软件一样,flowd 在 PID 文件中记录其进程 ID,如图 ❷ 所示。大多数系统将 PID 文件存储在目录 /var/run 中。
flowd 必须监听网络,并在 ❸ 中指定一个 IP 地址和一个 UDP 端口,用冒号分隔。如果您使用 IP 0.0.0.0,flowd 将监听系统上所有 IP 地址的传入流量数据。要限制 flowd 接受流量数据的 IP 地址,请将路由器的 IP 地址作为流量源列出,如图 ❹ 所示。
虽然flowd具有全面的过滤功能,让您仅记录某些类型的流量,但您在❺处告诉flowd记录所有内容,并在❻处接受传感器传输的所有内容。
修改完配置文件后,启动flowd,并告诉您的版本 9 传感器将数据传输到该收集器的 IP 地址和端口。当版本 9 流量数据到达时,flowd应该将其记录在日志文件中。一旦您看到日志文件变大,就是将数据转换为 flow-tools 格式的时候了。
将 flowd 数据转换为 Flow-tools
NetFlow 版本 9 包括 NetFlow v5 记录中预期的信息:源和目标地址和端口、协议号、数据包计数等。您需要自动从flowd日志中提取这些信息并将其导入到flow-capture ft-文件中。幸运的是,Craig Weinhold 的flowd2ft脚本为您做了这件事。您可以从以下列表中复制脚本或从www.networkflowanalysis.com/下载它。让我们看看它。
#!/usr/bin/perl
# "flowd2ft" crontab script to move flowd capture files into flow-tools
# -- flow-tools variables
# where ft's flow-import is
❶ our $ftImport = "/usr/local/bin/flow-import";
# put a copy of the flow file here, for flowscan
❷ our $ftDir = "/var/flow/router-v5/ft";
# timezone for ft capture files
❸ our $ftTZ = "-0500";
# seconds per ft capture file and cron interval
❹ our $ftPeriod = 300;
# -- flowd variables
# where flowd-reader is
❺ our $flowdReader = "/usr/local/bin/flowd-reader";
# where flowd.conf is
❻ our $flowdConf = "/usr/local/etc/flowd.conf";
# SIGUSR1
our $flowdHup = "10";
our ($flowdPid, $flowdLog);
our ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time - $ftPeriod);
our $ftFile = sprintf("ft-v05.%04d-%02d-%02d.%02d%02d%02d$ftTZ",
$year + 1900, $mon + 1, $mday, $hour, $min, $sec);
❼ open(IN, $flowdConf) || die "Could not read $flowdConf";
while ( <IN> ) {
if (/^\s*logfile ["]?([^"\s]+)/) { $flowdLog = $1; }
if (/^\s*pidfile ["]?([^"\s]+)/) { $flowdPid = $1; }
}
close(IN);
exit if (! -f $flowdLog); # exit silently on empty file
die "$flowdPid does not exist: $!" if (! -f $flowdPid);
my $pid = `cat $flowdPid`;
❽ `mv $flowdLog $flowdLog.tmp`;
die "$flowdPid ($pid) invalid: $!" if (! kill $flowdHup, $pid);
❾ `$flowdReader -c $flowdLog.tmp | $ftImport -f 2 -V 5 -z 1 > $ftDir/$ftFile`;
在使用此脚本之前,您需要设置配置变量。在❶处,您将flow-import程序的路径硬编码。在❷处,您将脚本指向您想要用于存储创建的flow-capture文件的目录。在❸处,您给脚本提供分钟数的时间区域偏移量,以便它可以在文件名中包含该信息,就像flow-capture一样。在❹处,您告诉脚本每 300 秒创建一个新的ft-文件,就像您的常规flow-capture实例一样。
脚本还需要知道flowd-reader程序(❺)的安装位置以及如何找到flowd配置(❻)。在❼处,脚本读取flowd配置文件以获取其余设置,然后在❽处将现有的flowd文件移开,以便重新启动flowd并关闭现有的日志文件。最后,在❾处,它读取新关闭的日志文件并创建一个新的flow-capture文件。
配置脚本后,手动运行一次。它应该在目标目录中创建一个新的ft-日志文件,并告诉你处理了多少流量。如果脚本运行不正确,请检查您的设置和错误日志消息。一旦您确定脚本运行正常,请通过在cron中添加适当的条目,使系统每五分钟运行一次,如下所示:
*/5 * * * * /usr/local/bin/convert-flowd-ft.pl > /tmp/convert.log
现在您将拥有与您其余流量报告系统兼容的流量记录。您可以使用这些记录来设置 FlowScan,运行flow-report或执行您喜欢的任何其他操作。
^([11]) 我认真考虑过使用flowd来编写这本书,但它还没有像flow-capture支持的那样多种预定义报告。然而,我预计这会随着时间的推移而改变,如果您需要一个 IPv6 流量收集器并且能够用 Perl 或 Python 编写报告,您应该考虑使用flowd。
sFlow
sFlow 是由 InMon 发明的流量导出技术,与思科的 NetFlow 竞争。许多供应商,如 HP 和 Extreme,提供导出 sFlow 但不导出 NetFlow 的设备。不过,没有必要绝望:你可以将 sFlow 数据包转换为 NetFlow 版本 5 数据,并将其提供给 flow-tools。
注意
然而,如果你有很多基于 sFlow 的设备,那么真正需要考虑的是一个 sFlow 报告系统。我建议在你有一个现有的 flow-tools 设置和几个你想要集成到该系统中的 sFlow 设备时将 sFlow 转换为 NetFlow,而不是当你有一个满载 sFlow 硬件的数据中心时。
使用 sflowenable 配置 sFlow 导出
一些 sFlow 传感器可以通过 GUI 或命令行进行配置,但有一些 sFlow 传感器需要通过 SNMP 进行配置。虽然你可以手动使用 SNMP GET 和 SET 命令来设置 sFlow,但 InMon 的那些好人提供了一个脚本来自动化这个过程。从 www.inmon.com/technology/sflowenable/ 获取 sflowenable 的副本。
sflowenable 需要你可能已经安装在你的网络管理工作站上的 net-snmp 工具。它还需要 GNU awk,也称为 gawk。一些操作系统将 gawk 作为默认的 awk 包含在内;其他操作系统则将其作为附加包提供。如果 sflowenable 因为神秘的 awk 错误而失败,你使用的 awk 是错误的。安装 gawk,然后编辑脚本以使用 gawk 而不是 awk,或者在你的 shell 中将 awk 别名为 gawk。现在快速地说三遍。
运行 sflowenable 需要传感器主机名和读写 SNMP 社区、收集器 IP 地址以及你想要接收 sFlow 数据的 UDP 端口。
sflowenable.sh *`sFlow-sensor community collector_IP collector_port`*
例如,为了在设备 bigSwitch 上激活 sFlow,使用 SNMP 社区 LucasRulez,并将数据传输到主机 192.0.2.15 上的端口 5515 的 sFlow 收集器,我会运行以下命令:
# `sflowenable.sh bigSwitch LucasRulez 192.0.2.15 5515`
你应该几乎立即在你的收集器上看到数据流向端口 5515。但是等等——你没有可以监听 sFlow 的东西,更不用说做任何事情了!你现在将处理这个细节。
转换 sFlow 到 NetFlow
sflowtool 程序是一个免费的 sFlow 收集器、捕获器和转换器,可以从 www.inmon.com/technology/sflowTools.php 获取。在其特性中,它可以转换 sFlow 数据流到 NetFlow 版本 5 并发送到 NetFlow 收集器。这对于这些目的来说非常完美。
sflowtool 是一个没有特殊要求的简单程序。你可以使用熟悉的 ./configure、make、make install 程序来构建它,这些程序你已经多次使用过了。
要让 sflowtool 转换并重新传输数据,你需要一个用于监听 sFlow 连接的端口、一个 flow-capture 主机以及 flow-capture 端口。
sflowtool -p *`sflow_port`* -c flow-capture-host -d *`flow-capture-port`* > /dev/null &
在前面的示例中,我假设你有一个在端口 5515 上的 sFlow 收集器。让我们假设你想要接受这些 sFlow 数据包,将它们转换为 NetFlow,并将它们重新传输到同一主机上的端口 5516 上运行的 flow-capture 实例。你会这样运行 sflowtool:
sflowtool -p 5515 -c localhost -d 5516 > /dev/null &
现在配置一个 flow-capture 实例以记录流量数据,你就可以从仅支持 sFlow 的设备中获取数据,无需任何本地脚本或转换程序。
使用流量数据解决问题
你已经在本书中探讨了各种流量分析功能的有用性。现在,你将查看一些真实问题的案例研究和可能的解决方案。其中一些我在前面已经提到过;其他则是全新的。
找到损坏的软件
在正常情况下,每个网络上的 TCP 连接都会定期断开一小部分。软件堆栈行为不当,客户端尝试连接到已废弃的打印机,应该知道更好的用户安装了行为无法言喻的免费软件。也许使用流量数据来改善你的网络最快的方法就是检查这些损坏的连接,确定它们的来源和目的地,并发现受影响机器上导致问题的软件。以下是有两种常见的“损坏”TCP 连接组:
仅 SYN 流
一台机器尝试连接到一个不响应的远程主机。
仅 RST 流
一台机器尝试连接到一个拒绝连接的远程主机。你可以为这些情况编写过滤器,并分别报告它们。
损坏的连接过滤器
以下过滤器将捕获这两种类型的损坏 TCP 连接:
❶ filter-primitive syn-only
type ip-tcp-flags
permit 0x2
❷ filter-primitive rst-only
type ip-tcp-flags
permit 0x4
❸ filter-definition syn-only
match ip-tcp-flags syn-only
❹ filter-definition rst-only
match ip-tcp-flags rst-only
在这里,你定义了一个仅 SYN 流的原型 ❶,一个相应的过滤器 ❸,一个仅 RST 的原型 ❷,以及它的匹配过滤器 ❹。
检查重置
现在在一个典型流量的样本上使用 rst-only 过滤器。
# `flow-cat` ❶ `ft-v05.2010-01-22.10* | flow-nfilter -F rst-only | flow-report -v` ❷
`TYPE=ip-address -v` ❸ `SORT=+flows`
ip-address flows octets packets duration
❹ 192.0.2.184 1186 14880 372 100
192.0.2.197 1186 14880 372 100
198.22.63.8 39 1720 43 4
72.21.91.20 23 920 23 0
192.0.6.197 23 1920 48 16
192.0.64.69 16 640 16 0
...
选择你预期“典型”流量的时间段的记录。例如,如果你的办公室只在上午 9 点到下午 5 点开放,那么凌晨 2 点的流量记录将不会代表正常使用(尽管它们可能单独查看很有趣)。在我的网络上,我正在分析上午 10 点到 11 点的记录 ❶。
你正在寻找发送或接收异常大量仅 SYN 或仅 RST 流的机器。虽然你可能会最初用 flow-print 查看数据,但你真正想要的是一个 IP 地址列表和匹配流量的数量,如 ip-address 报告 ❷ 所提供的。我想按降序排序,如 ❸ 所示。在这个小时里,前两个主机的仅 RST 流量比第三名的机器多 30 倍,如 ❹ 所见。那里似乎有什么行为不正常。
下一步是检查更多的时段,看看这种行为是否一致,或者这两个主机是否只是在特定时间有问题。假设行为是一致的,那么更仔细地查看第一个主机的 RST-only 流量。在这个例子中,我正在使用在第四章中创建的 ip-addr 报告,所以我还不需要区分源地址和目标地址:
# `flow-cat ft-v05.2010-01-22.10* | flow-nfilter`
`-F rst-only | flow-nfilter -F ip-addr -v ADDR=192.0.2.184 | flow-print | less`
srcIP dstIP prot srcPort dstPort octets packets
192.0.2.184 192.0.2.197 6 443 33171 80 2
192.0.2.184 192.0.2.197 6 443 17866 80 2
192.0.2.184 192.0.2.197 6 443 64447 80 2
192.0.2.184 192.0.2.197 6 443 60076 80 2
192.0.2.184 192.0.2.197 6 443 13839 80 2
...
如您在前面的列表中看到的,每个流在第一眼看来基本上是相同的。主机 192.0.2.184 向 192.0.2.197 发送了两个 TCP RST,从端口 443 到一个高端口。这些都是被拒绝的 HTTPS 请求。如果您查看这两个主机之间的所有流量,您会看到 192.0.2.197 向 192.0.2.184 发送 HTTPS 请求,然后被拒绝。
第二次运行 flow-print 并使用包括时间戳的格式,如下所示,显示客户端每隔几秒就发起这个请求:
flow-print -f 5
主机 192.0.2.197 正在运行一个损坏或配置错误的软件。现在去询问系统管理员发生了什么。
注意,我的测试网络相当小。在企业数据中心,您可能会发现几十种不同的软件包表现不佳;我亲眼见过配置错误的软件每秒尝试联系其他主机数百次。尽管 TCP RST 通常不会消耗足够的带宽来引起问题,但解决这些问题可以使软件更高效,减少硬件需求,并可能以意想不到的方式减少网络流量和服务延迟。
检查失败的连接
SYN-only 流表明主机请求了一个连接,但没有得到响应。要么请求的地址不在网络上,要么该地址的主机无法响应请求,或者该主机正在静默忽略请求。尽管您可能知道您的设备是否配置为静默忽略请求,但识别前两种类型的设备可能非常有用。您将像检查 RST-only 流一样识别具有高 SYN-only 流量的 IP 地址;只是过滤器有所变化。
# `flow-cat ft-v05.2011-01-22.10* | flow-nfilter -F`
`hamlin | flow-nfilter -F syn-only | flow-report -v TYPE=ip-address -v SORT=+flows`
ip-address flows octets packets duration
❶ 192.0.2.13 8306 526240 16998 2390732
118.126.4.66 256 10240 256 0
112.110.75.169 224 40640 635 1828064
192.0.2.158 193 24624 513 1430236
192.0.2.233 158 24648 474 1421304
...
在这份报告中,您再次看到了一个明显的异常值:显示在❶处的主机 192.0.2.13 比其他任何主机都有更多的 SYN-only 流。为了了解原因,请使用与特定 RST-only 主机相同的技巧查看该主机的流量,如下所示:
# `flow-cat ft-v05.2011-01-22.10* | flow-nfilter`
`-F rst-only | flow-nfilter -F ip-addr -v ADDR=192.0.2.13 | flow-print | less`
srcIP dstIP prot srcPort dstPort octets packets
❶ 192.0.2.13 192.0.2.16 6 26064 24 64 1
❷ 192.0.2.13 192.0.2.16 6 26064 26 64 1
❸ 192.0.2.13 192.0.2.16 6 26147 27 64 1
❹ 192.0.2.13 192.0.2.16 6 26148 28 64 1
192.0.2.13 192.0.2.16 6 26152 29 64 1
192.0.2.13 192.0.2.16 6 26149 30 64 1
192.0.2.13 192.0.2.16 6 26246 31 64 1
192.0.2.13 192.0.2.16 6 26248 32 64 1
192.0.2.13 192.0.2.16 6 26253 33 64 1
...
如您所见,主机 192.0.2.13 重复尝试联系 192.0.2.16,首先是在端口 24 上(❶),然后是端口 26(❷),端口 27(❸),端口 28(❹),以此类推。这一特定数据表明 192.0.2.13 正在尝试 192.0.2.16 上的 1 到 1024 之间的所有端口。随后,连接尝试转向 192.0.2.17。
这个活动表明这是一台端口扫描器。记住,并非所有端口扫描器都是按顺序扫描端口的——关键是要寻找在相对较短的时间内被同一 IP 地址在多个端口上击中的情况。如果 192.0.2.13 是你的安全工作站,并且你习惯性地扫描自己的网络,这可能是一种正常行为。然而,蠕虫和入侵者也会使用端口扫描器来识别易受攻击的目标。如果你不知道这台机器为什么扫描网络,找出原因!
在这个输出中,有一个有趣的现象是端口扫描似乎跳过了端口 25。记住,你正在检查立即重置的数据流。如果一个主机在端口上响应,它将不会出现在这个列表中。在这种情况下,192.0.2.16 运行着一个邮件服务器;查看这些主机之间的所有流量将显示一个到端口 25 的数据流和一个响应的数据流。
调查另一个具有高只包含 SYN 计数器的 IP 地址可能会产生类似以下的结果:
srcIP dstIP prot srcPort dstPort octets packets
221.194.136.17 192.0.2.158 6 35628 80 432 8
66.249.67.245 192.0.2.158 6 44008 80 240 4
221.194.136.17 192.0.2.158 6 35628 80 48 1
66.249.67.245 192.0.2.158 6 44008 80 60 1
65.55.207.118 192.0.2.158 6 52684 80 144 3
65.55.106.137 192.0.2.158 6 54180 80 144 3
65.55.106.185 192.0.2.158 6 21976 80 144 3
...
这些不同的源 IP 地址都在尝试连接到 192.0.2.158,所有这些都是在 TCP 端口 80 上。快速检查显示,这台机器是一个 Web 服务器,并且它确实在端口 80 上响应请求。为什么你会看到这些只包含 SYN 的数据流?
如果你的网络设备报告了一个数据流,那么它肯定将数据包发送到了网络节点,因为发送数据包是一个比流量报告更高的优先级任务!在这个特定的情况下,从flow-print命令中移除syn-only过滤器显示 Web 服务器响应了数千个请求。"flow-report"告诉你,在你检查的那个小时内,这台主机有 193 个只包含 SYN 的数据流,但 Web 服务器并没有响应这 193 个请求。可能是它耗尽了内存或 CPU。也许网卡已经饱和,或者 Web 服务器软件被重新加载了。
绘制只包含 SYN 的数据包出现的时间图可能会提供一些答案,特别是当与当时打开的连接数量图或服务器执行内部维护的时间列表进行比较时。作为网络管理员,你只能说,在这个小时内,用户遇到了“页面无法显示”或类似的错误 193 次。在你的环境和情况下,这是可以接受的吗?可能不是。
这种类型的结果的好处是,你知道交付系统中的哪个部分失败了。网络交付了数据包,而 Web 服务器没有响应。如果 Web 服务器管理员报告说他在收到关于网络超时的投诉,你可以提供证据表明超时实际上并不是网络问题,并提出解决问题的建议。
识别蠕虫
如果你在一个企业网络中,蠕虫造成的麻烦远不止系统问题。它们会引发会议。与管理层一起。由于你的防病毒软件可能在蠕虫尝试传播时触发桌面警报,这些会议可能包括高级管理人员,他们可能会提出关于你如何度过时间的尴尬问题。
你最好的应对策略是尽快找到蠕虫的源头。例如,在 2009 年春季,我的雇主的安全系统开始发出关于 Conficker 病毒感染尝试的警告。在一个拥有数万台桌面的全球公司中,手动识别病毒源头可能需要无数的人时,并需要跨越多个时区和多种语言障碍的合作。尽管我只有全球数十个工厂中的三个工厂的流量数据,但流量分析在约 15 分钟内就确定了源头,并避免了大多数会议。
要找到蠕虫,首先确定蠕虫的传播方式。几分钟的谷歌搜索告诉我,Conficker 通过微软的文件共享端口,在 TCP/445 上传播。蠕虫探测其网络上的每个 IP 以识别 Windows 主机,并感染它找到的任何主机。这种行为是不寻常的:尽管许多服务器会从许多不同的主机接收连接,但很少会有系统试图连接到网络上的每个其他主机。
你可以使用ip-source-address-destination-count报告来统计系统尝试联系的主机数量,如下所示:
# `flow-cat` ❶ `ft-v05.2009-05-29.* | flow-nfilter -F ip-port -v` ❷
`PORT=445 | flow-report -v` ❸
`TYPE=ip-source-address-destination-count -v OPTIONS=-header -v` ❹
`FIELDS=-duration,-packets,-octets |` ❺
`sort -rnk 2 | less`ip-source-address ip-destination-address-count flows
❻ 172.17.84.14 1851 1711
❼ 172.17.84.13 1591 1483
❽ 172.19.11.65 59 225
172.19.11.8 44 60
172.19.11.4 17 38
...
正如你所见,我从❶开始,查找的是蠕虫攻击我的本地网络的时间窗口内的流量文件。然后我在❷处仅搜索流向或来自端口 445 的流量,并在❸处通过ip-source-address-destination-count报告运行这些流量。为了使输出更易于阅读,❹处移除了不必要的字段。
注意
记住,这个报告及其对应报告ip-destination-address-source-count没有内置的排序功能。你必须在外部进行排序,如下❺所示。(外部排序的一个后果是,每个列的标题出现在列表的底部。我已经将这个示例的标题恢复到了顶部,以便更容易理解。对你的经理们也这样做。)
该报告揭示了两个试图连接到大量其他主机的计算机:172.17.84.14 在我的数据中心网络上连接或尝试连接了 1,851 个不同的主机,如下❻所示。由于网络中少于 500 台活跃的计算机,这立即引起了怀疑。❽处显示的第二个主机具有类似的配置,而❽处的第三个是我的公司文件服务器,它的连接数要少得多。
这两台机器实际上位于不同半球的一个测试网络上。没有流量分析,我永远无法识别这些机器。有了分析,一份记录结果的电子邮件让我免去了参加任何后续会议的需要。
流向非法地址的流量
你的防火墙配置错误吗?是的。是的,它是。你只是不知道而已。
大多数防火墙使用网络地址转换(NAT)将私有地址上的主机连接到公共互联网上的地址。如果您有一个复杂的防火墙策略,并且防火墙平台鼓励复杂或甚至古怪的 NAT 规则^([12]), 那么不小心将未翻译的地址泄露到您的面向互联网的网络中很容易。如果您正在使用一个策略运行多个防火墙,这几乎不可避免。您的 ISP 应该从您的互联网电路中过滤内部地址,因此任何在您的外部网络上带有私有 IP 地址的流量都来自您(或者您和您的 ISP 需要稍微谈谈)。
跟踪来自私有地址的流量很容易。首先,定义一个包括您内部地址的过滤器。
filter-primitive internal
type ip-address-prefix
❶ permit 172.16.0.0/16
permit 172.17.0.0/16
permit 172.18.0.0/16
filter-definition internal
match ip-source-address internal
or
match ip-destination-address internal
在这里,您在❶处确定了三个用于内部的三块 IP 地址,并为它们定义了一个过滤器。接下来,转到您存储面向互联网网络流量记录的目录,对这些地址进行过滤,并打印结果。
# `flow-cat * | flow-nfilter -F internal | flow-print | less`
srcIP dstIP prot srcPort dstPort octets packets
❶ 172.16.84.151 137.118.232.3 6 33892 25 40 1
172.16.84.151 94.190.193.162 6 43729 25 309 1
172.16.84.151 123.118.100.174 6 25051 25 339 1
172.16.84.151 189.70.172.2 6 33724 2015 133 1
172.16.84.151 212.242.180.151 6 33724 11906 133 1
❷ 172.16.84.130 198.22.66.10 17 4132 53 132 1
172.16.84.130 198.22.62.19 17 38897 53 132 1
...
每个这些流量都通过了具有不正确 NAT 配置的防火墙规则。换句话说,这些规则是错误的,并且它们将以意想不到的方式影响您。例如,❶行显示一个主机试图从一个私有地址发送电子邮件。当然,连接永远不会完成。如果这是您的备用邮件交换机,当您的首选邮件交换机出现问题时,您将会有一个令人不快的惊喜。同样,在❷处,您也有一个主机试图从一个私有地址进行域名服务查询。提前修复这些问题将减少未来的中断。
非存在主机的流量
理论上,移除网络服务器应该减少网络使用。不幸的是,这并不总是正确的。
在某个时候,我雇主公司网络上的某些桌面电脑在用户输入用户名和密码五分钟之后才会变得有用。即使是普通操作系统,这也太慢了。尽管并非每个工作站都受到影响,但受影响的大部分工作站都在我缺乏诊断设备的远程位置。我让一个用户在特定时间尝试了一个这样的工作站,然后检查流量记录,看看该工作站是否在窗口期间尝试联系我的数据中心中的任何东西。
结果表明,在那个时间段内,那个工作站的大部分流量都在尝试连接我的 Novell 登录服务器,该服务器几天前已被关闭。然而,工作站仍然安装了客户端。显然,Novell 客户端软件坚持尝试联系登录服务器,尽管它被告知要关闭。从那个客户端中移除 Novell 客户端解决了缓慢登录的问题。
在确定了一个问题后,我接下来使用 FlowGrapher 绘制了从那个远程工厂到断开连接的服务器 IP 地址的流量图。每天早上两个小时,这种流量几乎消耗了工厂网络连接的 25%。尽管之前认为移除禁用客户端是不必要的,但这个证据改变了人们的想法。
严格来说,这不是一个网络问题,但诊断它需要网络管理员的参与,而解决问题减少了网络投诉的数量。记住,网络工程师想要的只是让他的用户闭嘴。
^([12]) (咳嗽。) 检查点。(咳嗽。)
后记
我确信你们中的大多数人都能与每一位同事相处得非常好,你们的工作环境令人愉快,充满乐趣,你们的 IT 团队是一个无缝、团结的团队,没有恶意的争吵或痛苦的诽谤。对于那些在不太支持的环境中工作的人来说,应该读一读这篇文章。
流量分析将改变你的问题解决能力。你将解决那些多年来一直困扰你网络的奇怪问题。你将最终证明,那些大家都舒适地归咎于网络的问题实际上是服务器或软件问题。你甚至能够挖出一长串其他人正在网络上造成的问题。所有这些都会迅速改变你与同事和管理层的关系。
系统管理和网络工程师有与难以共事的传统;我们甚至有像地狱里的混蛋操作员这样的原型。现在你有证据了,你可能会想让你那些怀疑你的人为他们的固执付出代价。然而,现在你有证据了,你可以表现得更加宽容。当你遇到问题时,承认它。当你表明某件事不是你的问题时,然而,可以说些像“这里有证据表明问题。尽管这显然不是网络问题,但我很高兴帮助你解决问题。”诚然,这比用“你 loser”这样的词要令人满意得多。虽然看起来不太可能,但积极的态度可以改变同事和管理层对网络员工的态度,并改善你的生活。
如果不是这样,至少你可以确信这不是你的问题。而且,永远不晚于称呼某人傻瓜。
更新内容
访问www.nostarch.com/networkflow_mlucas.htm获取更新、勘误和其他信息。
《网络流分析》使用 New Baskerville、TheSansMono Condensed、Futura 和 Dogma 字体。
本书由密歇根州安阿伯的 Malloy Incorporated 印刷和装订。纸张为 60# Spring Forge,经可持续林业倡议认证。本书采用 RepKover 装订,使其打开时可以平铺。
[3] ↩︎



浙公网安备 33010602011771号