9.6. 使用过滤器分类数据包

为了确定哪个类应处理数据包,每次需要做出选择时都会调用所谓的“分类器链”。此链由附加到需要做出决定的有类别队列规则的所有过滤器组成。

重申一下树状结构,虽然它不是一棵树

                    root 1:
                      |
                    _1:1_
                   /  |  \
                  /   |   \
                 /    |    \
               10:   11:   12:
              /   \       /   \
           10:1  10:2   12:1  12:2

当数据包入队时,在每个分支都会查阅过滤器链以获取相关指令。一个典型的设置可能是在 1:1 中有一个过滤器,将数据包定向到 12:,并在 12: 上有一个过滤器,将数据包发送到 12:2。

您也可以将后一个规则附加到 1:1,但是通过在链中较低的位置进行更具体的测试,您可以获得效率提升。

顺便说一句,您不能“向上”过滤数据包。此外,使用 HTB,您应该将所有过滤器附加到根节点!

再次强调 - 数据包仅向下入队!当它们出队时,它们会再次向上移动,到达接口所在的位置。它们不会从树的末端掉到网络适配器上!

9.6.1. 一些简单的过滤示例

正如分类器章节中解释的那样,您可以使用非常复杂的语法来匹配几乎任何内容。首先,我们将展示如何执行显而易见的事情,幸运的是这些事情非常容易。

假设我们有一个名为“10:”的 PRIO 队列规则,其中包含三个类,我们想将所有来自和去往端口 22 的流量分配给最高优先级频带,过滤器将是

# tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match \ 
  ip dport 22 0xffff flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match \
  ip sport 80 0xffff flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2

这是什么意思? 它的意思是:附加到 eth0,节点 10: 一个优先级为 1 的 u32 过滤器,该过滤器完全匹配 IP 目标端口 22,并将其发送到频带 10:1。 然后它对源端口 80 重复相同的操作。 最后一个命令表示,到目前为止任何未匹配的内容都应转到频带 10:2,即次高优先级。

您需要添加 'eth0',或您的接口名称,因为每个接口都有唯一的句柄命名空间。

要选择 IP 地址,请使用以下命令
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 \ 
  match ip dst 4.3.2.1/32 flowid 10:1
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 \
  match ip src 1.2.3.4/32 flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 2      \
  flowid 10:2

这会将发送到 4.3.2.1 和来自 1.2.3.4 的流量分配给最高优先级队列,其余流量分配给次高优先级队列。

您可以连接匹配项,以匹配来自 1.2.3.4 和端口 80 的流量,请执行以下操作
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 4.3.2.1/32
  match ip sport 80 0xffff flowid 10:1

9.6.2. 您通常需要的所有过滤命令

此处介绍的大多数整形命令都以此序言开头
# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 ..
这些是所谓的“u32”匹配,可以匹配数据包的任何部分。

关于源/目标地址

源掩码 'match ip src 1.2.3.0/24',目标掩码 'match ip dst 4.3.2.0/24'。 要匹配单个主机,请使用 /32,或省略掩码。

关于源/目标端口,所有 IP 协议

源:'match ip sport 80 0xffff','match ip dport 0xffff'

关于 ip 协议(tcp、udp、icmp、gre、ipsec)

使用 /etc/protocols 中的数字,例如,icmp 是 1: 'match ip protocol 1 0xff'。

关于 fwmark

您可以使用 ipchains 标记数据包,并让该标记在跨接口路由后仍然存在。 这对于例如仅整形在 eth0 上进入的 eth1 上的流量非常有用。 语法:# tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1 请注意,这不是 u32 匹配!

您可以像这样放置标记
# iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6
数字 6 是任意的。

如果您不想理解完整的 tc 过滤器语法,只需使用 iptables,并且只学习选择 fwmark。

关于 TOS 字段

要选择交互式、最小延迟流量
# tc filter add dev ppp0 parent 1:0 protocol ip prio 10 u32 \
      match ip tos 0x10 0xff \
     flowid 1:4
对于批量流量,请使用 0x08 0xff。

有关更多过滤命令,请参阅高级过滤器章节。