由于 IP 记账与 IP 防火墙密切相关,因此指定了相同的工具来配置它,因此使用 ipfwadm、ipchains 或 iptables 来配置 IP 记账。 命令语法与防火墙规则非常相似,因此我们不会过多关注它,但我们将讨论如何使用此功能发现网络流量的本质。
使用 ipfwadm 进行 IP 记账的通用语法是
# ipfwadm -A [direction] [command] [parameters] |
方向参数是新的。它只是简单地编码为in (进入), out (外出),或者both (两者)。这些方向是从 Linux 机器本身的角度来看的,所以in (进入)表示从网络连接进入机器的数据,并且out (外出)表示该主机正在通过网络连接传输的数据。 Theboth (两者)方向是传入和传出方向的总和。
ipchains 和 iptables 的通用命令语法是
# ipchains -A chain rule-specification # iptables -A chain rule-specification |
ipchains 和 iptables 命令允许您以与防火墙规则更一致的方式指定方向。 IP 防火墙链不允许您配置聚合两个方向的规则,但它允许您在forward (转发)链中配置规则,而较旧的实现不允许这样做。 稍后我们将在一些示例中看到它所产生的差异。
这些命令与防火墙规则非常相似,只是策略规则不适用于此处。 我们可以添加、插入、删除和列出记账规则。 对于 ipchains 和 iptables,所有有效的规则都是记账规则,并且任何未指定 -j 选项的命令都只执行记账。
IP 记账的规则指定参数与 IP 防火墙使用的参数相同。 这些是我们用来精确定义我们希望计数和汇总的网络流量的参数。
让我们用一个例子来说明我们将如何使用 IP 记账。
假设我们有一个基于 Linux 的路由器,为 Virtual Brewery 的两个部门提供服务。 该路由器有两个以太网设备,eth0和eth1,每个设备都为一个部门提供服务;以及一个 PPP 设备,ppp0,通过高速串行链路将我们连接到 Groucho Marx University 的主校区。
让我们还假设,出于计费目的,我们想知道每个部门通过串行链路产生的总流量,并且出于管理目的,我们想知道两个部门之间产生的总流量。
下表显示了我们将在示例中使用的接口地址
要回答“每个部门在 PPP 链接上生成多少数据?”这个问题,我们可以使用如下规则
# ipfwadm -A both -a -W ppp0 -S 172.16.3.0/24 -b # ipfwadm -A both -a -W ppp0 -S 172.16.4.0/24 -b |
# ipchains -A input -i ppp0 -d 172.16.3.0/24 # ipchains -A output -i ppp0 -s 172.16.3.0/24 # ipchains -A input -i ppp0 -d 172.16.4.0/24 # ipchains -A output -i ppp0 -s 172.16.4.0/24 |
# iptables -A FORWARD -i ppp0 -d 172.16.3.0/24 # iptables -A FORWARD -o ppp0 -s 172.16.3.0/24 # iptables -A FORWARD -i ppp0 -d 172.16.4.0/24 # iptables -A FORWARD -o ppp0 -s 172.16.4.0/24 |
这些规则集的前半部分说:“统计通过名为 ppp0 的接口在任一方向上,其源地址或目标地址(记住 ipfwadm 和 iptables 中的 -b 标志的作用)为172.16.3.0/24.” 的所有数据。 每个规则集的后半部分是相同的,但是针对我们站点的第二个以太网网络。
要回答第二个问题“两个部门之间传输了多少数据?”,我们需要一个如下所示的规则
# ipfwadm -A both -a -S 172.16.3.0/24 -D 172.16.4.0/24 -b |
# ipchains -A forward -s 172.16.3.0/24 -d 172.16.4.0/24 -b |
# iptables -A FORWARD -s 172.16.3.0/24 -d 172.16.4.0/24 # iptables -A FORWARD -s 172.16.4.0/24 -d 172.16.3.0/24 |
好的,让我们假设我们还想更好地了解通过我们的 PPP 链路传输的确切流量类型。 例如,我们可能想知道 FTP、SMTP 和 World Wide Web 服务占用了多少链路。
启用我们收集此信息的规则脚本可能如下所示
#!/bin/sh # Collect FTP, smtp and www volume statistics for data carried on our # PPP link using ipfwadm # ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 ftp ftp-data ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 smtp ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 www |
#!/bin/sh # Collect ftp, smtp and www volume statistics for data carried on our # PPP link using ipchains # ipchains -A input -i ppp0 -p tcp -s 0/0 ftp-data:ftp ipchains -A output -i ppp0 -p tcp -d 0/0 ftp-data:ftp ipchains -A input -i ppp0 -p tcp -s 0/0 smtp ipchains -A output -i ppp0 -p tcp -d 0/0 smtp ipchains -A input -i ppp0 -p tcp -s 0/0 www ipchains -A output -i ppp0 -p tcp -d 0/0 www |
#!/bin/sh # Collect ftp, smtp and www volume statistics for data carried on our # PPP link using iptables. # iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport ftp-data:ftp iptables -A FORWARD -o ppp0 -m tcp -p tcp --dport ftp-data:ftp iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport smtp iptables -A FORWARD -o ppp0 -m tcp -p tcp --dport smtp iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport www iptables -A FORWARD -o ppp0 -m tcp -p tcp --dport www |
此配置有几个有趣的特征。 首先,我们指定了协议。 当我们在规则中指定端口时,我们还必须指定协议,因为 TCP 和 UDP 提供单独的端口集。 由于所有这些服务都是基于 TCB 的,因此我们已将其指定为协议。 其次,我们指定了两个服务ftp和ftp-data在一个命令中。 ipfwadm 允许您指定单个端口、端口范围或任意端口列表。 ipchains 命令允许单个端口或端口范围,这就是我们在此处使用的。 语法 "ftp-data:ftp"表示“端口 ftp-data (20) 到 ftp (21)”,这是我们在 ipchains 和 iptables 中对端口范围进行编码的方式。 当您的记账规则中包含端口列表时,这意味着为列表中任何端口接收到的任何数据都将添加到该条目的总计中。 记住 FTP 服务使用两个端口,命令端口和数据传输端口,我们将它们加在一起以合计 FTP 流量。 最后,我们将源地址指定为“0/0,”,这是匹配所有地址的特殊表示法,并且 ipfwadm 和 ipchains 命令都需要它才能指定端口。
我们可以稍微扩展第二点,以使我们对链接上的数据有不同的看法。 现在让我们想象一下,我们将 FTP、SMTP 和 World Wide Web 流量分类为基本流量,将所有其他流量分类为非基本流量。 如果我们有兴趣查看基本流量与非基本流量的比率,我们可以执行以下操作
# ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 ftp ftp-data smtp www # ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 1:19 22:24 26:79 81:32767 |
如果您已经检查过您的/etc/services文件,您会看到第二个规则涵盖了除(ftp, ftp-data, smtp,和www).
)之外的所有端口。 我们如何使用 ipchains 或 iptables 命令来做到这一点,因为它们在端口规范中只允许一个参数? 我们可以像在防火墙规则中一样轻松地利用用户定义的链进行记账。 考虑以下方法
# ipchains -N a-essent # ipchains -N a-noness # ipchains -A a-essent -j ACCEPT # ipchains -A a-noness -j ACCEPT # ipchains -A forward -i ppp0 -p tcp -s 0/0 ftp-data:ftp -j a-essent # ipchains -A forward -i ppp0 -p tcp -s 0/0 smtp -j a-essent # ipchains -A forward -i ppp0 -p tcp -s 0/0 www -j a-essent # ipchains -A forward -j a-noness |
# iptables -N a-essent # iptables -N a-noness # iptables -A a-essent -j ACCEPT # iptables -A a-noness -j ACCEPT # iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport ftp-data:ftp -j a-essent # iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport smtp -j a-essent # iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport www -j a-essent # iptables -A FORWARD -j a-noness |
这看起来很简单。 不幸的是,尝试按服务类型进行记账时,存在一个小的但不可避免的问题。 您会记得,我们在前面的章节中讨论了 MTU 在 TCP/IP 网络中的作用。 MTU 定义了将在网络设备上传输的最大数据报。 当路由器接收到的数据报大于需要重新传输的接口的 MTU 时,路由器会执行一个称为分片的技巧。 路由器将大的数据报分成不大于接口 MTU 的小块,然后传输这些块。 路由器构建新的标头以放在每个块的前面,这些是远程计算机用于重建原始数据的标头。 不幸的是,在分片过程中,除了第一个片段之外,所有片段的端口都将丢失。 这意味着 IP 记账无法正确计算分片的数据报。 它只能可靠地计算第一个片段或未分片的数据报。 ipfwadm 允许使用一个小技巧,该技巧确保虽然我们无法确切知道第二个和后面的片段来自哪个端口,但我们仍然可以对其进行计数。 Linux 记账软件的早期版本为片段分配了一个虚拟端口号 0xFFFF,我们可以对其进行计数。 为了确保我们捕获第二个和后面的片段,我们可以使用如下规则
# ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 0xFFFF |
IP 链实现有一个稍微复杂的解决方案,但结果几乎相同。 如果使用 ipchains 命令,我们将改为使用
# ipchains -A forward -i ppp0 -p tcp -f |
# iptables -A FORWARD -i ppp0 -m tcp -p tcp -f |
这些不会告诉我们此数据的原始端口是什么,但至少我们能够看到有多少数据是片段,并且能够计算出它们消耗的流量。
在 2.2 内核中,如果您的 Linux 机器充当网络的单个访问点,则可以选择内核编译时选项来否定整个问题。 如果您在编译内核时启用了IP: always defragment (IP:始终进行碎片整理)选项,则所有接收到的数据报都将在路由和重新传输之前由 Linux 路由器重新组装。 此操作在防火墙和记账软件看到数据报之前执行,因此您将无需处理任何片段。 在 2.4 内核中,您编译并加载 netfilterforward-fragment模块。
ICMP 协议不使用服务端口号,因此收集其详细信息稍微困难一些。ICMP 使用多种不同类型的数据报。其中许多是无害且正常的,而另一些只应在特殊情况下看到。有时,有些人会花太多时间,试图通过生成大量 ICMP 消息来恶意中断用户的网络访问。这通常被称为ping 泛洪。虽然 IP 记帐无法阻止这个问题(IP 防火墙可以提供帮助!),但我们至少可以制定记帐规则,以便在我们发现有人试图这样做时显示出来。
ICMP 不像 TCP 和 UDP 那样使用端口。 相反,ICMP 具有 ICMP 消息类型。 我们可以建立规则来记录每种 ICMP 消息类型。 为此,我们将 ICMP 消息和类型编号放置在 ipfwadm 记帐命令中的端口字段位置。 我们在 第 9.6.3.5 节 列出了 ICMP 消息类型”,因此如果您需要记住它们是什么,请参考它。
一个用于收集发送给您或您正在生成的 ping 数据量的 IP 记帐规则可能如下所示:
# ipfwadm -A both -a -P icmp -S 0/0 8 # ipfwadm -A both -a -P icmp -S 0/0 0 # ipfwadm -A both -a -P icmp -S 0/0 0xff |
# ipchains -A forward -p icmp -s 0/0 8 # ipchains -A forward -p icmp -s 0/0 0 # ipchains -A forward -p icmp -s 0/0 -f |
# iptables -A FORWARD -m icmp -p icmp --sports echo-request # iptables -A FORWARD -m icmp -p icmp --sports echo-reply # iptables -A FORWARD -m icmp -p icmp -f |
如果您在规则中指定源和/或目标地址,您可以跟踪 ping 的来源,例如它们是否源自您的网络内部或外部。 一旦确定了恶意数据报的来源,您就可以决定是否要设置防火墙规则来阻止它们或采取其他措施,例如联系攻击网络的拥有者,告知他们问题,甚至在问题是恶意行为时采取法律行动。
现在让我们假设我们有兴趣了解我们的链路上有多少流量是 TCP、UDP 和 ICMP。 我们将使用如下规则:
# ipfwadm -A both -a -W ppp0 -P tcp -D 0/0 # ipfwadm -A both -a -W ppp0 -P udp -D 0/0 # ipfwadm -A both -a -W ppp0 -P icmp -D 0/0 |
# ipchains -A forward -i ppp0 -p tcp -d 0/0 # ipchains -A forward -i ppp0 -p udp -d 0/0 # ipchains -A forward -i ppp0 -p icmp -d 0/0 |
# iptables -A FORWARD -i ppp0 -m tcp -p tcp # iptables -A FORWARD -o ppp0 -m tcp -p tcp # iptables -A FORWARD -i ppp0 -m udp -p udp # iptables -A FORWARD -o ppp0 -m udp -p udp # iptables -A FORWARD -i ppp0 -m icmp -p icmp # iptables -A FORWARD -o ppp0 -m icmp -p icmp |