掌握Linux网络:深入理解TC —— 你的流量控制利器

举报
笨笨小乌龟 发表于 2024/07/11 14:58:00 2024/07/11
【摘要】 ​        目录简单概述:qdisc(队列):  举例:  Bash        整形队列算法:FIFO (First-In-First-Out)PFIFO (Priority FIFO)SFQ (Stochastic Fair Queuing)RED (Random Early Detection)HTB (Hierarchical Token Bucket)TBF (Token ...

        

目录

简单概述:

qdisc(队列):

  举例:

  Bash        

整形队列算法:

FIFO (First-In-First-Out)

PFIFO (Priority FIFO)

SFQ (Stochastic Fair Queuing)

RED (Random Early Detection)

HTB (Hierarchical Token Bucket)

TBF (Token Bucket Filter)

NETEM (Network Emulator)

CBQ (Class-based Queueing)

整形队列流量方向管理:

Class(类) 和 Filter(过滤器):

创建 class

使用 class 和 filter

问题:

带宽或者流速单位:

问题解决方法:

限制IP为1.1.1.3上传速度实例:

  创建虚拟网卡并启用,暂定虚拟网卡名为ifb0

  创建Ingress队列并进行导流

   对ifb0进行限速即可

限制IP为1.1.1.3下载速度实例:

u32匹配:

u32匹配器的特点

 限速总结:   



目前需要做一款关于Linux下对于某IP限制的一个工具(QOS),在网上寻找了许多关于TC的教程,大多数都是一些比较基础的教学,且多数都是对网口的一些限制,然后自己研究了一段时间,最后有一些小小的了解,故在此分享给大家。

首先我们可以先假设把TCP包的架构设成这样,方便我们后续去了解限速的规则。这里一定要记好了。

[source-ip] | [source-port] | [other-data] | [destination-ip] | [destination-port]

简单概述:

TC,即 Traffic Control,是 Linux 内核提供的一种用于网络流量管理和质量服务(Quality of Service, QoS)的工具。它允许网络管理员对网络接口上的数据包进行精细的控制,包括但不限于:

  1. SHAPING(限制)

    • 当流量被限制时,其传输速率被控制在预设的阈值之下。这种限制可以显著减少突发流量,有助于维持网络的稳定性和预测性。SHAPING 主要应用于向外的流量控制。
  2. SCHEDULING(调度)

    • 调度涉及在可用带宽范围内,按优先级分配带宽资源。这确保了关键应用和服务可以得到优先处理,从而提高了网络的整体效率。SCHEDULING 同样适用于向外的流量。
  3. POLICING(策略)

    • POLICING 通常用于控制入站流量,当检测到流量超出预设规则时,可以采取行动,如丢弃超额的数据包,以维持网络政策的一致性。
  4. DROPPING(丢弃)

    • 当流量超出设定的带宽限制时,DROPPING 策略将直接丢弃过量的数据包。这一策略适用于入站和出站流量。

tc 命令的基本结构如下:

Bash

1tc [ OPTIONS ] COMMAND [ @id ] dev DEV [ parent qdisc-id ] [ index INDEX ]

其中 COMMAND 可以是 qdisc, filter, class, action 等不同的子命令,用于执行不同的流量控制任务。

  • qdisc(排队规则)

    • qdisc 定义了数据包在接口上排队和调度的策略。它决定了数据包如何被存储和发送,是流量控制的核心机制。qdisc 可分为 CLASSLESS QDISC 和 CLASSFUL QDISC。
  • CLASSLESS QDISC

    • 包括简单的 FIFO(First-In-First-Out)队列,如 pfifo 和 bfifo,以及更复杂的策略如 pfifo_fast、red、sfq 和 tbf。
      • pfifo/bfifo:简单的 FIFO 队列,前者基于数据包计数,后者基于字节数。
      • pfifo_fast:在高级路由器配置中作为默认 qdisc,具有三个优先级队列。
      • red:随机早期检测,用于预防拥塞。
      • sfq:基于概率的公平队列,适用于多流场景。
      • tbf:令牌桶过滤器,用于限速和整形。
  • CLASSFUL QDISC

    • 提供更细粒度的控制,允许创建基于类别的队列,如 HTB 和 CBQ,用于复杂的服务质量策略。
  • class(类别)

    • 类别用于组织和划分流量,允许为不同类型的流量分配特定的带宽和优先级。
  • filter(过滤器)

    • 过滤器用于识别和分类数据包,基于 IP 地址、端口、协议等属性,将数据包导向特定的 qdisc 或 class。

qdisc(队列):

  1. 带宽分配:限制或保证数据流的带宽。
  2. 延迟控制:通过缓存机制控制数据包的发送时间,从而影响网络延迟。
  3. 丢包策略:当队列满时决定哪些数据包被丢弃的策略,以防止拥塞。
  4. 公平性:确保多个数据流之间的公平带宽分配。
  举例:
  Bash        
tc qdisc add dev ens18 handle fff: htb default 22

   其中fff:就相当于这条队列的特定标识符,也相当于唯一ID。

        谈到队列大家可能有些熟悉,是数据结构中的队列吗?先进先出的那个?当然不是,这是由Linux做的一款流量整形队列,你可以把它看作一条支流,对,小溪那种。

         在我们正常使用的情况下,其实LInux就已经给我们的网卡分配了一些队列,应该也是用来整形稳定的一种。当我们对网口设置了一个新的队列后,这个队列就会被我的这个队列给顶替下去。

         编辑

整形队列算法:

FIFO (First-In-First-Out)

这是最简单的队列纪律类型,没有额外的管理机制。数据包按照它们到达的顺序被发送出去。FIFO 不做任何排序或优先级处理,因此所有数据流都被平等对待。这在大多数情况下是默认的行为,但如果网络负载很高,可能会导致一些数据包的延迟或丢失。

PFIFO (Priority FIFO)

PFIFO 提供了有限数量的优先级队列,通常为三个:高、中、低。这允许网络管理员根据数据包的类型或来源为其分配不同的优先级,从而确保关键数据包(如语音或视频流)得到优先处理。然而,PFIFO 仍然依赖于简单的先进先出原则,只是在不同的优先级队列中。

SFQ (Stochastic Fair Queuing)

SFQ 是一种更复杂的队列管理算法,旨在为每个数据流提供公平的带宽分配,即使在高负载情况下也能保持良好的响应时间。它使用基于概率的算法来分类数据包,然后将它们放入不同的队列中,确保即使小流量的数据流也能获得一定的带宽。

RED (Random Early Detection)

RED 是一种主动丢包机制,用于预防网络拥塞。当队列接近其最大容量时,RED 开始随机丢弃一些数据包,而不是等到队列完全填满。这种提前丢弃数据包的策略有助于平滑网络流量,减少拥塞的发生,从而改善整体网络性能。

HTB (Hierarchical Token Bucket)

HTB 是一种非常灵活的队列纪律,支持复杂的带宽分配和优先级管理。它可以创建层次化的令牌桶,允许网络管理员为不同的数据流设定具体的带宽限制和优先级。HTB 特别适用于需要精细控制网络资源分配的场景,如企业网络和数据中心。

TBF (Token Bucket Filter)

TBF 是基于令牌桶算法的流量整形工具,主要用于限速和流量整形。它允许指定一个固定的带宽速率,确保数据流不会超过这个速率,这对于避免网络拥塞和保证服务质量非常有用。

NETEM (Network Emulator)

NETEM 是一个网络仿真工具,用于模拟各种网络状况,如延迟、丢包和重复。它非常适合在开发和测试环境中模拟真实世界的网络条件,帮助验证应用程序在网络问题下的表现。

CBQ (Class-based Queueing)

CBQ 是早期版本中常用的队列纪律,类似于 HTB,但功能较少且配置更为复杂。它也支持基于类的队列,允许为不同的数据流设置不同的优先级和带宽限制。然而,由于 HTB 的出现,CBQ 在现代系统中的使用已大大减少。


编辑

上方这些算法中,如果你想进行一些简单的流量控制,那么FIFO和PFIFO即可,如果想要进行真正管理级,逻辑稍微复杂一些的流量整控我推荐用HTB,关于HTB它可以进行优先级限制,src和dst IP限制,是一个功能非常强大的算法。SFQ的话是当你建立了多条类的话,用于流量平分用。比如果你从队列里面开出了三条类,也可以理解为引出来了三条小溪流,害怕每条小溪流的水不一样多怎么办?这时候就给每条小溪都设上一个SFQ。

wondershaper源码为例:

编辑

这里其他算法就不过多赘述了,专于对HTB算法进行详细讲解。

整形队列流量方向管理:

  • Ingress:表示数据包进入网络设备的方向。当数据包从网络接口接收进来时,这个过程被称为 ingress。在这个阶段,设备可以执行诸如数据包过滤、流量整形、优先级标记等操作。

  • Egress:表示数据包离开网络设备的方向。当数据包被发送到另一个网络或设备时,这个过程被称为 egress。在 egress 方向,设备也可能执行类似的操作,如基于策略的路由、QoS 保障、流量限速等。

在 Linux 的 Traffic Control (tc) 工具中,ingress 和 egress 通常用来描述数据包在网卡或网络设备上的流动方向。例如,当使用 tc 进行流量控制时,你可以分别对 ingress 和 egress 方向的流量应用不同的队列纪律和过滤规则。这点其实是非常重要的,因为TC实际上是管发不管收的。也就是如果我们通过TC只能限制别人对我们的下载速度,没办法限制别人对我们的上传速度。

这个东西在前期确实让人很头痛,那岂不是我们没有办法在自己的机器上对别人进行上传限速?当然不是,Ingress和Egress就可以解决这个问题。这个在后续应用实例的时候去讲。

Class(类) 和 Filter(过滤器):


classtc 中扮演了组织者和控制器的角色。它允许你创建多个类别,每个类别都可以有自己的带宽限制、优先级和调度策略。通过将数据包分配到不同的 class 中,你可以实现以下目标:

  1. 带宽分配:为每个 class 设置不同的带宽上限,确保每个数据流都得到公平或预定的带宽份额。
  2. 优先级控制:为关键数据流分配更高的优先级,确保它们在拥塞时仍能快速传输。
  3. QoS 改善:通过精细调整 class 参数,改善整个网络的服务质量,特别是对于实时应用如 VoIP 和视频会议。

创建 class

class 的创建和配置通常与 qdisc 相结合。首先,你需要在根 qdisc 下创建一个父 class,然后可以创建子 class 来进一步细分流量。例如,使用 htb(Hierarchical Token Bucket)作为 qdisc 时,你可以这样创建一个 class

Bash

# 创建父 qdisc
tc qdisc add dev <interface> root handle 1: htb default 11

# 创建父 class
tc class add dev <interface> parent 1: classid 1:1 htb rate <rate>

# 创建子 class
tc class add dev <interface> parent 1:1 classid 1:11 htb rate <rate> ceil <max_rate>

在上述命令中,<interface> 是你想要控制的网络接口,<rate> 是你想要分配给该 class 的带宽速率,<max_rate> 是该 class 可以使用的最大带宽。

使用 class 和 filter

为了将特定的数据包分配到正确的 class,你需要使用 filterfilter 根据数据包的属性(如源/目的IP、端口号、协议类型等)将它们导向特定的 class。例如:

Bash

tc filter add dev <interface> protocol ip parent 1:0 prio 1 u32 match ip dst <destination_ip>/32 flowid 1:11

此命令创建了一个 filter,将目的地为 <destination_ip> 的所有 IP 数据包导向 class 1:11

问题:

此时以文章最开始的包结构为例,这里的destination_ip就是我们包结构里面的 [destination-ip]。假如由1.1.1.2给1.1.1.3发消息,那我们在1.1.1.3中收到的这个包的目标IP就是1.1.1.3,所以此时我们如果对1.1.1.3进行限速也就是对1.1.1.3进行限速。那如果我直接这个包的SRC进行限速呢?这不就完成了对客户端上传速度的限制?但是大家别忘了,TC是一个管发不管收的工具,既然不管收,那怎么对客户端进行限速呢?

带宽或者流速单位:

编辑

编辑

问题解决方法:

    我们可以去将Ingress的流量进行一个导流,然后把导流的流量重定向到一个网卡上,为了稳定这个采用一个虚拟网卡,然后对虚拟网卡上的流量进行限速,就可以解决对收包进行限速了。

限制IP为1.1.1.3上传速度实例:

  创建虚拟网卡并启用,暂定虚拟网卡名为ifb0

  Bash

modprobe ifb numifbs=1;
ip link set dev ifb0 up;
  创建Ingress队列并进行导流

   Bash

tc qdisc add dev ens18 handle ffff: ingress
tc filter add dev ens18 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0;
   对ifb0进行限速即可
tc qdisc add dev ifb0 root handle 2: htb default 22;
tc class add dev ifb0 parent 2: classid 2:22 htb rate 10000mbit ceil 10000mbit burst 10000mbit cburst 10000mbit;
tc class add dev ifb0 parent 2: classid 2:1 htb rate 10mbit ceil 10mbit  burst 10mbit  cburst 10mbit ;

tc filter add dev ifb0 protocol ip parent 2: prio 1 u32 match ip src 1.1.1.3 flowid 2:1;

如果想要限制其他的IP将IP改一下即可。

限制IP为1.1.1.3下载速度实例:

正常创建Htb队列,default 22 就是如果没有合适的filter去匹配的话,那就就去找classid为22的类去限速。

tc qdisc add dev ens18 root handle 1:0 htb default 22

创建限速类,这里22限制为10GB每秒,相当于未限速,然后对1.1.1.3限速为10mbit每秒。

tc class add dev ens18 parent 1:0 classid 1:1 htb rate 10mbit ceil 10mbit

tc class add dev ens18 parent 1:0 classid 1:22 htb rate 10000mbit ceil 10000mbit
            
 # dst->src
tc filter add dev ens18 parent 1:0 protocol ip  prio 1 u32 match ip dst 1.1.1.3 flowid 1:1 

u32匹配:

在Linux的tc(Traffic Control)工具中,u32是一种匹配器类型,用于基于数据包头部的信息来过滤和分类网络流量。u32匹配器非常灵活,可以依据各种字段(如IP地址、端口号、协议类型等)来创建复杂的匹配规则,是实现高级流量控制策略的关键组件。

u32匹配器的特点

  1. 灵活性u32匹配器可以基于多种数据包头部字段进行匹配,包括但不限于IP源地址、目的地址、TCP/UDP源端口、目的端口、协议类型等。

  2. 复杂规则支持u32支持逻辑运算,如AND、OR、NOT,允许创建复合的匹配规则,以适应复杂的网络策略需求。

  3. 性能高效u32匹配器设计得非常高效,能够快速处理大量的数据包,即使在高负载的网络环境下也能保持良好的性能

  1. 基于IP地址匹配

    • 源IP地址匹配:

      Bash
      sudo tc filter add dev [interface] protocol ip parent 1:0 prio 1 u32 match ip src [source_ip] flowid 1:1
    • 目的IP地址匹配:

      Bash
      sudo tc filter add dev [interface] protocol ip parent 1:0 prio 1 u32 match ip dst [destination_ip] flowid 1:1
  2. 基于端口号匹配

    • TCP源端口号匹配:

      Bash
      sudo tc filter add dev [interface] protocol tcp parent 1:0 prio 1 u32 match tcp sport [source_port] flowid 1:1
    • TCP目的端口号匹配:

      Bash
      sudo tc filter add dev [interface] protocol tcp parent 1:0 prio 1 u32 match tcp dport [destination_port] flowid 1:1
    • UDP源端口号匹配:

      Bash
      sudo tc filter add dev [interface] protocol udp parent 1:0 prio 1 u32 match udp sport [source_port] flowid 1:1
    • UDP目的端口号匹配:

      Bash
      sudo tc filter add dev [interface] protocol udp parent 1:0 prio 1 u32 match udp dport [destination_port] flowid 1:1
  3. 基于协议类型匹配

    • 匹配TCP协议:

      Bash
      sudo tc filter add dev [interface] protocol tcp parent 1:0 prio 1 u32 flowid 1:1
    • 匹配UDP协议:

      Bash
      sudo tc filter add dev [interface] protocol udp parent 1:0 prio 1 u32 flowid 1:1
    • 匹配ICMP协议:

      Bash
      sudo tc filter add dev [interface] protocol icmp parent 1:0 prio 1 u32 flowid 1:1

 限速总结:   

     对于上传和下载下载的规律是不变的,后续filter跟的一些匹配协议就由大家自由发挥了,例如端口,源端口,协议类型等一些东西都是非常多的,在此我也不一一列举了,由大家自由发挥。




【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。