一、基本原理介绍
Traffic Control(TC)是Linux内核提供的一个强大的流量控制工具,用于限制、调度和优先级处理网络流量。它包括队列管理(qdisc)、分类(class)和过滤器(filter)三个核心组件。通过建立CBQ或HTB等队列,可以实现带宽限制、优先级分配和数据包分类。例如,为不同目标IP或子网创建不同带宽限制的流量,可以通过tc命令配置QDisc、类和过滤器,并配合路由表来实现。流量控制的维护包括添加、修改和删除队列、分类和过滤器。通过监视工具,可以查看队列、分类和过滤器的状态,以便调整和优化网络性能。

详细的TC使用规则请参考官方手册页,或者使用在线资源学习https://man7.org/linux/man-pages/man8/tc.8.html ,我们常用的是TBF和HBT(使用令牌桶限速,HBT更灵活),CBQ是基于空闲时间计算的带宽分配算法配置相比最为复杂(可选了解)
二、基本使用(流量限制)
bash
# 查看和清除配置
---------------------------------
# 查看网卡的tc规则
tc qdisc show dev eth0
tc class show dev eth0
tc filter show dev eth0
# 清除所有tc规则
tc qdisc del dev eth0 root
# 演示示例
---------------------------------
# 需求:假设eth0出口有100mbit/s的带宽,分配给WWW、E-mail和Telnet三种数据流量,其中的Telnet独立分配20Mbit/s的带宽。另一方面,WWW 和SMTP各自分配40Mbit/s的带宽。同时,它们又是共享的关系,即它们可以互相借用带宽。
# 实现如下:
tc qdisc add dev eth0 root handle 1: htb default 21
# 命令中的"add"表示要添加,"dev eth0"表示要操作的网卡为eth0,"root"表示为网卡eth0添加的是一个根队列,"handle 1:"表示队列的句柄为1: ,"htb"表示要添加的队列为HTB队列,命令最后的"default 21"是htb特有的队列参数,意思是所有未分类的流量都将分配给类别1:21。
tc class add dev eth0 partent 1: classid 1:1 htb rate 20mbit ceil 20mbit
# 命令中的"add"表示要添加,"parent 1:"表示类别的父亲为根队列1: ,"classid1:1"表示创建一个标识为1:1的类别,"rate 20mbit"表示系统将为该类别确保带宽20mbit,"ceil 20mbit",表示该类别的最高可突发占用带宽为20mbit。
tc class add dev eth0 parent 1: classid 1:2 htb rate 80mbit ceil 80mbit
tc class add dev eth0 parent 1:2 classid 1:21 htb rate 40mbit ceil 20mbit
# 命令中的"add"表示要添加,"parent 1:2"表示类别的父亲为父类别1:2 ,"classid1:21"表示创建一个标识为1:21的类别,"rate 40mbit"表示系统将为该类别确保带宽40mbit,"ceil 20mbit",表示该类别的最高可突发占用带宽为20mbit。
tc class add dev eth0 parent 1:2 classid 1:22 htb rate 40mbit ceil 80mbit
tc filter add dev eth0 protocol parent 1:0 prio 1 u32 match ip dport 80 0xffff flowid 1:21
# "protocol ip"表示该过滤器检查链路层(以太网)的协议字段,只处理 IPv4 数据包。"prio 1" 表示它们对报文处理的优先级是相同的,对于不同优先级的过滤器,系统将按照从小到大的优先级顺序来执行过滤器,对于相同的优先级,系统将按照命令的先后顺序执行。这个过滤器还用到了u32选择器(命令中u32后面的部分)来匹配不同的数据流。以该命令为例,判断的是dport字段,使用掩码 0xffff 对目标端口进行匹配(与操作),匹配端口是80,则"flowid 1:21"表示将把该数据流分配给类别1:21。
tc filter add dev eth0 protocol parent 1:0 prio 1 u32 match ip dport 25 0xffff flowid 1:22
tc filter add dev eth0 protocol parent 1:0 prio 1 u32 match ip dport 23 0xffff flowid 1:1
1、出站流量控制
bash
# 方式一、htb队列控制
----------------------------------
tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 1: htb default 10
tc class add dev eth0 parent 1: classid 1:10 htb rate 100mbit ceil 100mbit
# 方式二、tbf队列控制
----------------------------------
tc qdisc add dev eth0 root handle 1: tbf rate 100mbit burst 32kbit latency 400ms
2、入站流量控制
bash
# 在 Linux 中,tc(Traffic Control)默认只能控制出站(egress)流量,无法直接限制入站(ingress)流量。这是因为数据包进入网卡后,内核立即处理,没有"排队调度"的机会。但是可以通过 ifb(Intermediate Functional Block)虚拟网卡 技术,将入站流量重定向到一个虚拟出口,然后在这个虚拟出口上应用 tc 规则,从而间接实现入站限速。
# 查看ifb 内核模块加载
lsmod | grep ifb
# 查看ifb 内核模块是否存在
modinfo ifb
# 加载 ifb 内核模块
modprobe ifb numifbs=1
lsmod | grep ifb
# 确认 ifb0 网络接口是否存在并启用
ip link show ifb0
ip link set dev ifb0 up
ip link show ifb0
# 添加 ingress 重定向
tc qdisc add dev eth0 handle ffff: ingress
tc filter add dev eth0 parent ffff: protocol all u32 match u32 0 0 action mirred egress redirect dev ifb0
# 在 ifb0 上限速
tc qdisc add dev ifb0 root handle 1: tbf rate 100mbit burst 32kbit latency 400ms
--------------------------------
# 关闭并清除ifb0虚拟管卡(测试完成后,可选)
# 确保没有引用ifb0的规则
tc qdisc del dev ifb0 root
tc qdisc del dev eth0 ingress
# 关闭 ifb0 虚拟接口
ip link set dev ifb0 down
ip link show ifb0
# 完全卸载 ifb 模块(可选,后续使用需重新加载)
# 卸载掉内核模块ifb
modprobe -r ifb
lsmod | grep ifb
