linux下tc限速核心是控制出向流量,通过qdisc、class、filter协同实现;须作用于真实网卡,tbf适合单流限速,htb+filter可按ip差异化限速,注意方向与匹配逻辑。

Linux 下用 tc(traffic control)做网络限速,核心是控制出方向(egress)流量,本质是给网卡队列加调度策略。它不直接“堵”带宽,而是通过排队规则(qdisc)、分类(class)和过滤器(filter)协同实现带宽分配与限制。实际配置中,误用 qdisc 类型或忽略默认队列常导致限速无效。
先确认网卡和基础环境
限速只对出站流量生效(即本机发出去的数据),且必须作用于真实网卡(如 eth0、ens33),不能用于 lo 或虚拟接口(除非特殊场景)。操作前建议:
- 用
ip link show确认目标网卡名及状态(UP) - 检查是否已有 tc 规则:
tc qdisc show dev eth0,有输出说明已配置,需先清理再重试 - 普通用户需 root 权限,所有 tc 命令建议加
sudo
最简限速:使用 tbf(Token Bucket Filter)
tbf 是入门首选,适合单一流量整体限速,原理直观、稳定性好,不涉及分类和过滤。例如将 eth0 出向带宽限制为 2Mbit/s,突发 5KB,延迟容忍 50ms:
sudo tc qdisc add dev eth0 root tbf rate 2mbit burst 5kb latency 50ms
说明:
-
rate是平均速率,单位可写 kbit、mbit、kbit、mbps(注意大小写敏感) -
burst太小会导致小包频繁丢弃;太大则限速不严格;一般设为rate / 10左右较稳妥 - 删除该规则:
sudo tc qdisc del dev eth0 root
按源/目标 IP 限速:htb + filter 组合
需要差异化限速时(比如只限制某台客户端的上传速度),用 htb(hierarchical token bucket)建分层结构,配合 u32 或 cgroup 过滤器匹配流量。
示例:限制来自 192.168.1.100 的所有出向流量为 1Mbit/s:
# 1. 挂载根 htb qdisc sudo tc qdisc add dev eth0 root handle 1: htb default 30 <h1>2. 创建主类(总带宽假设为物理上限,如 100mbit)</h1><p>sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit</p><h1>3. 创建子类,专用于 192.168.1.100,限速 1mbit</h1><p>sudo tc class add dev eth0 parent 1:1 classid 1:10 htb rate 1mbit ceil 1mbit</p><h1>4. 添加过滤器,将源 IP 匹配到该类</h1><p>sudo tc filter add dev eth0 parent 1: protocol ip u32 match ip src 192.168.1.100 flowid 1:10
注意:
- filter 中
match ip src是匹配“本机发出、目的为该 IP”的流量?错——出向规则中,src 是本机 IP,dst 才是远端 IP。若想限速“本机发往 192.168.1.100”的流量,应写match ip dst 192.168.1.100 - 若要限速“从 192.168.1.100 连入本机的请求”,那是入向(ingress),需用 ifb 模块重定向,不能直接在 eth0 上用 tc out 方式实现
验证与排错要点
限速后没效果?常见原因:
- 规则加在了错误方向:tc 默认只控 egress,ssh 登录慢通常是入向问题,需另想办法(如防火墙限速或应用层控制)
- 应用使用了多连接(如下载工具开 10 线程),而规则未做连接追踪,结果每个流都跑满子带宽 → 应改用 sfq 或 fq_codel 配合 htb 做公平排队
- 测试方式不当:用
iperf3 -c server测的是本机到服务器的出向,但若服务器不在同一局域网,中间链路可能成为瓶颈,建议本地局域网对测 - 查看实时效果:
tc -s class show dev eth0可看到各 class 的 sent 字节数、dropped 数、rate 实际值










