06 对包进行分类的高级过滤器

对包进行分类的高级过滤器

你能够了解到什么

04 带宽管理的队列规定 中,我们已经详细地讲述了 qdisc 以及 calss, filter 我们在使用,但是并没有详细地讲述其使用。

还记得 04 带宽管理的队列规定.md 告诫你不要尝试的案例吗,如果你想解决这个尴尬的问题,这章会给出你解决的方案。阅读本章,请保证 04 带宽管理的队列规定 相关的知识你已经掌握。

简介

就像在分类的队列规定一段中解释的,过滤器用于把数据包分类并分入对应的子队列中。这些过滤器在分类的队列规定的内部被调用。

下面就是我们可用的分类器(部分):

  • fw : 根据防火墙如何对这个数据包做标记进行判断。如果你不想学习 tc 的过
    滤器语法,这倒是一个捷径。细节请参见队列那一章。
  • u32 : 根据数据包中的各个字段进行判断,如源 IP 地址等等。
  • route : 根据数据包将被哪条路由来进行判断。
  • rsvp, rsvp6 : 根据数据包的 RSVP 情况进行判断。 只能用于你自己的网络, 互联网并不
    遵守 RSVP。
  • tcindex : 用于 DSMARK 队列规定,参见相关章节。

此章内容并不齐全,只介绍了 u32 ,因为 u32 已经足够让你完成足够细腻的操作,此外,由于录播机不可能有那么多个过滤器,所以哈希表的部分也省略了,虽然这章内容很长,但是不得不说其实已经够精简了。

通常来说,总有很多途径可以实现对数据包分包,最终取决于你喜欢使用哪种系统。
分类器一般都能接受几个参数,为了方便我们列举出来:

  • protocol :这个分类器所接受的协议。一般来说你只会接受 IP 数据。必要参数。
  • parent : 这个分类器附带在哪个句柄上。句柄必须是一个已经存在的类。必要参数。
  • prio : 这个分类器的优先权值。优先权值低的优先。
  • handle : 对于不同过滤器,它的意义不同。

后面所有的节都假定你试图对去往 HostA 的流量进行整形。并且假定根类配置为1:,并且你希望把选中的数据包送给 1:1 类。

可以好好思考一下为什么要着一个假设,这涉及到过滤器的原理。在 04 带宽管理的队列规定 中也对此做了解释。

u32 分类器

U32 分类器是当前实现中最先进的过滤器。 全部基于哈希表实现, 所以当有很多过滤器的时候仍然能够保持健壮。

你没有想错,我们可以疯狂加过滤条件在同一条通路上,它们之间的关系是或关系。

U32 过滤器最简单的形式就是一系列记录, 每条记录包含两个部分: 一个选择器和一个动作。下面要讲的选择器用来与 IP 包相匹配,一旦成功匹配就执行其指定的动作。最简单的动作就是把数据包发送到特定的类队列。

用来配置过滤器的 tc 命令行由三部分组成:过滤器说明、选择器和动作。一个过滤器可以如下定义:

tc filter add dev IF    [ protocol PROTO ]
                        [ (preference|priority) PRIO ]
                        [ parent CBQ ]

上面行中, protocol 字段描述了过滤器要匹配的协议。 我们将只讨论 IP 协议的情况。preference 字段(也可以用 priority 代替,可且坑爹的是一般 preference 写做缩写 pref)设置该过滤器的优先权。这非常重要,因为你可能有几条拥有不同优先权的过滤器。每个过滤器列表都按照输入的顺序
被扫描一遍, 然后优先权值低(更高的偏好值)的列表优先被处理。“ parent”字段定义了过滤器所属的 CBQ 的顶部(如 1:0)。

上面描述的选项适用于所有过滤器,而不仅仅适用于 U32。

在讲解下面内容中,你需要时常翻阅这张表,贴在这里供你查阅,当你看到人间迷惑的行为时,好好地看看这张表,你会发现你想要的答案的(更详细的位介绍就自己去查吧):

在这里插入图片描述

U32 选择器

u32 选择器包含了能够对当前通过的数据包进行匹配的特征定义。 它其实只是定
义了 IP 包头中某些位的匹配而已,但这种看似简单的方法却非常有效。让我们
看看这个从实际应用的系统中抄来的例子:

# tc filter add dev eth0 protocol ip parent 1:0 pref 10 u32 \
    match u32 00100000 00ff0000 at 0 flowid 1:10

现在,命令的第一行已经不用解释了,前面都说过了。我们把精力集中在用
“ match” 选项描述选择器的第二行。这个选择器将匹配那些 IP 头部的第二个字
节是 0x10 的数据包。你应该猜到了, 00ff 就是匹配掩码,确切地告诉过滤器应
该匹配哪些位。在这个例子中是 0xff,所以会精确地匹配这个字节是否等于 0x10。
“ at” 关键字的意思是指出从数据包的第几个字节开始匹配——本例中是从数据
包的开头开始。 完全地翻译成人类语言就是:“匹配那些 TOS 字段带有‘最小延
迟’属性的数据包”。让我们看看另一个例子:

# tc filter add dev eth0 protocol ip parent 1:0 pref 10 u32 \
    match u32 00000016 0000ffff at nexthdr+0 flowid 1:10

“ nexthdr” 选项意味着封装在 IP 包中的下一个 PDU 的头部, 也就是说它的上层
协议的头。匹配操作就是从这个协议的头部开始的,应该发生在头部开始的第
16 位处。在 TCP 和 UDP 协议的头部,这个部分存放的是这个报文的目标端口。
数字是按照先高厚低的格式存储的,所以 0x0016 就是十进制的 22(如果是 TCP
的话就是 ssh 服务)。 其实, 这个匹配在没有上下文的情况下含义很模糊, 我们放
在后面讨论。

理解了上面的例子之后,下面这条选择器就很好懂了:

match c0a80100 ffffff00 at 16

表示了:匹配从 IP 头开始数的第 17 个字节到第 19 个字节。这个选择器将匹配
所有去往 192.168.1.0/24 的数据包。成功分析完上面这个例子后,我们就已经掌
握 u32 选择器了。

普通选择器

普通选择器定义了要对数据包进行匹配的特征、掩码和偏移量。使用普通选择器,
你实际上可以匹配 IP(或者上层协议)头部的任意一个 bit,虽然这样的选择器比特
殊选择器难读和难写。一般选择器的语法是:

match [ u32 | u16 | u8 ] PATTERN MASK [ at OFFSET | nexthdr+OFFSET]

利用 u32、 u16 或 u8 三个关键字中的一个来指明特征的 bit 数。然后 PATTERN
和 MASK 应该按照它定义的长度紧挨着写。 OFFSET 参数是开始进行比较的偏
移量(以字节计)。如果给出了“ nexthdr+”关键字,偏移量就移到上层协议头部
开始的位置。

一些例子:

# tc filter add dev ppp14 parent 1:0 prio 10 u32 \
    match u8 64 0xff at 8 \
    flowid 1:4

如果一个数据包的 TTL 值等于 64, 就将匹配这个选择器。 TTL 就位于 IP 包头的
第 9 个字节。

匹配带有 ACK 位的 TCP 数据包:

# tc filter add dev ppp14 parent 1:0 prio 10 u32 \
    match ip protocol 6 0xff \
    match u8 0x10 0xff at nexthdr+13 \
    flowid 1:3

用这个匹配小于 64 字节的 ACK 包:

## match acks the hard way,
## IP protocol 6,
## IP header length 0x5(32 bit words),
## IP Total length 0x34 (ACK + 12 bytes of TCP options)
## TCP ack set (bit 5, offset 33)
# tc filter add dev ppp14 parent 1:0 protocol ip prio 10 u32 \
    match ip protocol 6 0xff \
    match u8 0x05 0x0f at 0 \
    match u16 0x0000 0xffc0 at 2 \
    match u8 0x10 0xff at 33 \
    flowid 1:3

这个规则匹配了带有 ACK 位, 且没有载荷的 TCP 数据包。 这里我们看见了同时
使用两个选择器的例子, 这样用的结果是两个条件进行逻辑“与” 运算。 如果我
们查查 TCP 头的结构, 就会知道 ACK 标志位于第 14 个字节的第 5 个 bit(0x10)。
作为第二个选择器, 如果我们采用更复杂的表达, 可以写成“ match u8 0x06 0xff
at 9”,而不是使用特殊选择器 protocol,因为 TCP 的协议号是 6(写在 IP 头的第
十个字节)。另一方面,在这个例子中我们不使用特殊选择器也是因为没有用来
匹配 TCP 的 ACK 标志的特殊选择器。

下面这个选择器是上面选择器的改进版,区别在于它不检查 IP 头部的长度。为
什么呢?因为上面的过滤器只能在 32 位系统上工作。

tc filter add dev ppp14 parent 1:0 protocol ip prio 10 u32 \
    match ip protocol 6 0xff \
    match u8 0x10 0xff at nexthdr+13 \
    match u16 0x0000 0xffc0 at 2 \
    flowid 1:3

总结

强烈建议你好好地再重新学习一下 ip报文 的格式以及具体各个字段的意义,你已经看到了它的作用了吧。实际上很容易理解,但是很不人性化,很野生地配置方法。推荐你自己写一个解析程序。这部分保留待做。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值