Linux下实现IP流量限制的QoS工具详解

2026-01-04 14:59:30 · 作者: AI Assistant · 浏览: 6

在Linux系统中,通过Traffic Control (TC)实现对特定IP的上传和下载速度限制,是网络管理和开发中一项重要的技能。本文将深入解析TC的工作原理,并结合真实场景,展示如何使用HTB和u32等工具实现精确的流量控制。

在Linux系统中,网络流量控制(QoS)是确保网络资源合理分配和关键服务优先传输的重要手段。通过TC工具,我们可以实现带宽限制、流量整形、优先级调度等多种功能。本文将围绕TC的核心概念、常用队列算法以及如何实现对特定IP的上传和下载限速,展开全面的讲解。

TC的基本结构和功能

TC(Traffic Control)是Linux内核提供的一个强大工具,用于对网络接口上的数据包进行精细控制。它支持多种功能,包括 SHAPINGSCHEDULINGPOLICINGDROPPING。其中,SHAPINGSCHEDULING 通常用于出站流量的控制,而 POLICING 则用于入站流量的策略管理。

TC的核心命令格式为:

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

其中,COMMAND 可以是 qdiscclassfilter 等,用于执行不同的流量控制任务。

TC的主要功能包括:

  • 带宽限制(SHAPING):控制数据流的传输速率,防止突发流量对网络造成影响。
  • 优先级调度(SCHEDULING):根据数据包的优先级分配带宽,保证关键服务的性能。
  • 策略控制(POLICING):监控并限制入站流量,防止网络过载。
  • 丢包策略(DROPPING):在流量饱和时丢弃部分数据包,以维持网络的稳定性。

这些功能共同构成了Linux系统下完善的QoS控制体系,为网络管理提供了极大的灵活性。

qdisc(排队规则)详解

qdisc(排队规则)是TC的核心组件之一,它决定了数据包如何被排队和调度。qdisc分为 CLASSLESS QDISCCLASSFUL QDISC 两大类。

CLASSLESS QDISC

CLASSLESS QDISC 是一种简单的队列管理方式,适用于基本的流量控制任务。它包括以下几种常见的队列算法:

  • FIFO (First-In-First-Out):最简单的队列纪律,数据包按到达顺序发送,不进行任何管理。
  • PFIFO (Priority FIFO):提供了有限的优先级队列(通常是3个),允许对关键数据包进行优先处理。
  • RED (Random Early Detection):一种主动丢包机制,用于预防网络拥塞。
  • SFQ (Stochastic Fair Queuing):用于多个数据流的公平调度,确保每个流获得合理的带宽。
  • TBF (Token Bucket Filter):基于令牌桶算法的限速工具,非常适用于对带宽进行精确控制。

这些队列算法虽然功能各异,但都适用于简单的限速或调度任务。对于大多数用户来说,FIFO和PFIFO已经足够满足基础需求,但在复杂场景下,如企业级网络或数据中心,通常需要更高级的算法如 HTBCBQ

CLASSFUL QDISC

CLASSFUL QDISC 提供了更细粒度的控制,允许创建基于类别的队列。其中,HTB (Hierarchical Token Bucket) 是最常用的 CLASSFUL QDISC,支持复杂的带宽分配、优先级管理和流量整形。

HTB 通过创建 父类子类 的结构,实现多层的带宽控制。例如,可以先为整个接口设置一个父类,然后为子类分配具体的带宽速率和上限。这种结构非常适合需要精细控制网络资源的场景。

其他的 CLASSFUL QDISC 如 CBQ (Class-based Queueing),虽然功能强大,但配置复杂,逐渐被 HTB 所取代。

qdisc 的主要功能包括:

  • 带宽分配:限制或保证数据流的带宽。
  • 延迟控制:通过缓存机制控制数据包的发送时间,从而影响网络延迟。
  • 丢包策略:当队列满时决定哪些数据包被丢弃的策略,以防止拥塞。
  • 公平性:确保多个数据流之间的公平带宽分配。

掌握这些队列算法,是实现高效流量控制的第一步。

Class(类别)和 Filter(过滤器)的使用

在 TC 中,Class 用于对数据包进行分类,而 Filter 用于识别并匹配特定的数据包,将其导向对应的 Class

Class 的创建和配置

创建 Class 通常需要与 qdisc 结合使用。以 HTB 为例,首先需要在根 qdisc 上创建一个父类,然后可以在父类下创建子类。例如:

# 创建父 qdisc
tc qdisc add dev eth0 root handle 1: htb default 11

# 创建父 class
tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit

# 创建子 class
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10mbit ceil 10mbit

在上述命令中,eth0 是目标网络接口,rate 是该类别的带宽速率,ceil 是该类别的最大带宽,burst 用于控制突发流量的大小。通过这种方式,我们可以为不同的数据流分配不同的带宽。

Filter 的应用

Filter 的作用是识别数据包并将其导向特定的 Class。例如,我们可以使用 u32 匹配器来匹配特定的 IP 地址或端口号,并将其分配到相应的 Class。

tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 1.1.1.3 flowid 1:11

此命令将目的 IP 为 1.1.1.3 的所有数据包导向 Class 1:11。通过合理配置 Filter,我们可以实现对不同数据流的精确控制。

上传速度限制的实现

在Linux系统中,TC默认只支持对出站流量进行限速,即对发送的数据包进行控制。然而,在某些特定场景中,我们需要对入站流量进行限速,例如限制某个 IP 的上传速度。

要实现对某个 IP 的上传速度限制,即限制其发送到其他主机的数据包,我们需要使用 Ingress 队列,并将其数据包重定向到一个虚拟网卡。

实现步骤

  1. 创建虚拟网卡:使用 ifb(Intermediate Forwarding Buffer)模块创建一个虚拟网卡 ifb0,并将其启用。
    bash modprobe ifb numifbs=1 ip link set dev ifb0 up

  2. 设置 Ingress 队列:在原始网卡(如 ens18)上添加一个 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

  3. 对虚拟网卡进行限速:在虚拟网卡 ifb0 上创建一个 HTB 队列,并设置具体的限速规则。例如,限制 IP 1.1.1.3 的上传速度为 10Mbps:
    bash 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 的上传速度进行了限制。ifb0 虚拟网卡起到了中介作用,将原始网卡上的入站流量重定向过去,然后在虚拟网卡上应用限速策略。

下载速度限制的实现

与上传速度限制不同,下载速度限制可以通过直接在原始网卡上创建 HTB 队列,并使用 u32 匹配器匹配目的地 IP 来实现。

实现步骤

  1. 创建 HTB 队列:在原始网卡 ens18 上创建一个 HTB 队列,并设置默认类。
    bash tc qdisc add dev ens18 root handle 1:0 htb default 22

  2. 创建限速类:为特定 IP(例如 1.1.1.3)创建限速类。
    bash 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

  3. 应用 Filter 匹配目标 IP:将目的 IP 为 1.1.1.3 的数据包导向限速类。
    bash tc filter add dev ens18 parent 1:0 protocol ip prio 1 u32 match ip dst 1.1.1.3 flowid 1:1

通过以上命令,我们实现了对 1.1.1.3 的下载速度限制。需要注意的是,u32 匹配器可以灵活匹配 IP 地址、端口号、协议类型等字段,从而实现对流量的精细化控制。

u32 匹配器详解

u32 是 TC 中一种非常灵活的匹配器,可以基于数据包头部的多种字段进行匹配。它支持逻辑运算(如 AND、OR、NOT),使得我们可以创建复杂的匹配规则。

u32 的主要特点

  • 灵活性:u32 可以基于多种数据包字段(如 IP 源地址、目的地址、端口号、协议类型等)进行匹配。
  • 支持逻辑运算:u32 允许使用 AND、OR、NOT 等逻辑运算符,从而创建复杂的匹配规则。
  • 高效性:u32 匹配器设计得非常高效,能够在高负载的网络环境下快速处理大量数据包。

u32 的匹配规则

u32 支持多种匹配方式,包括:

基于 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

基于端口号匹配

  • 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

基于协议类型匹配

  • 匹配 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

通过这些匹配规则,我们可以实现对网络流量的精细控制。u32 的灵活性和高效性使其成为 TC 中最常用的匹配器之一。

流量方向管理:Ingress 和 Egress

在 TC 中,IngressEgress 是两个重要的流量方向概念。

Ingress 表示数据包进入网络设备的方向。在这种情况下,设备可以对数据包进行过滤、整形和优先级标记等操作。Egress 表示数据包离开网络设备的方向,设备可以在此阶段对数据包进行调度、限速和丢弃等策略。

TC 的一个重要特点是它只管理出站流量(Egress),入站流量(Ingress)无法直接通过 TC 进行限速。但是,我们可以通过创建虚拟网卡并将入站流量重定向到该虚拟网卡,从而实现对入站流量的限速。

为什么TC管发不管收?

TC 的设计初衷是为了控制数据包的发送行为,而不是接收行为。因此,它无法直接对入站流量(例如某个 IP 的上传速度)进行控制。然而,通过使用 Ingress 队列和虚拟网卡,我们可以间接实现对入站流量的限速。

实现上传速度限制的思路

通过将入站流量重定向到虚拟网卡,并在该虚拟网卡上应用 HTB 队列,我们可以限制某个 IP 的上传速度。这一过程的主要步骤如下:

  1. 创建虚拟网卡:使用 ifb 模块创建一个虚拟网卡 ifb0
  2. 设置 Ingress 队列:在原始网卡上添加一个 Ingress 队列,并将数据包重定向到虚拟网卡。
  3. 对虚拟网卡进行限速:在虚拟网卡上创建 HTB 队列,并设置具体的限速规则。

通过这种方式,我们实现了对入站流量的限速,解决了 TC 无法直接对上传速度进行限制的问题。

强大的HTB队列算法

HTB(Hierarchical Token Bucket)是 TC 中最为强大的队列算法之一。它支持复杂的带宽分配、优先级管理以及层次化的流量控制。

HTB 的核心功能

HTB 能够实现以下功能:

  • 带宽限制:为每个 Class 设置具体的带宽速率和上限。
  • 优先级管理:为关键数据流分配更高的优先级,确保它们在拥塞时仍能快速传输。
  • 层次化结构:支持多级 Class 分配,允许对流量进行更精细的控制。

HTB 的灵活性使其成为企业级网络、数据中心等复杂场景下的首选队列算法。

HTB 的使用示例

在实际工作中,我们通常会结合 HTB 和 u32 过滤器,实现对特定 IP 或端口的限速。例如,限制某 IP 的上传速度为 10Mbps,可以使用以下命令:

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 1.1.1.3 的上传速度限制。HTB 的层次结构和灵活的参数设置,使得我们可以对网络流量进行精确控制。

带宽或流速单位的说明

在 TC 中,带宽或流速的单位通常是 mbit/s(兆比特每秒),而不是 Mbps(兆字节每秒)。这是因为网络传输的最小单位是比特(bit),而不是字节(byte)。

  • 1 mbit/s = 1,000,000 bits per second
  • 1 Mbps = 1,000,000 bytes per second

因此,在配置 TC 带宽限制时,需要注意单位的准确性。例如,限制某个 IP 的下载速度为 10Mbps,应使用 rate 10mbit 而不是 rate 10Mbitrate 10Mbps

限速总结

通过以上讲解,我们可以总结出以下几点关键信息:

  1. TC 默认只支持对出站流量进行限速,因此如果需要对入站流量进行控制,必须结合 Ingress 队列虚拟网卡
  2. HTB 是一种非常灵活的队列算法,支持层次化结构、带宽限制和优先级管理。
  3. u32 匹配器 是 TC 中最常用的匹配器之一,用于对数据包进行分类和匹配。
  4. 通过虚拟网卡实现上传速度限制 是一种有效的解决方案,能够解决 TC 无法直接控制入站流量的问题。

在实际应用中,我们可以通过这些工具和算法实现对网络流量的精细化控制,从而提升网络性能和稳定性。

关键词

Linux, TC, Traffic Control, QoS, HTB, u32, Ingress, Egress, 带宽限制, 流量整形, 过滤器