tc限速只对出向流量生效,且仅作用于物理网卡(如eth0),lo/veth/docker0等无效;限入向需用ingress+mirred跳转至ifb0,imq在5.0+内核已弃用。

tc限速只对出向流量生效,别在lo或虚拟网卡上折腾
Linux的tc命令本质是调度发包行为,不是“堵”带宽,所以它只控制本机**发出**的数据(egress),对进来的流量(ingress)无效。想限下载速度?必须绕道ifb0或用iptables + IMQ(但IMQ在5.0+内核已弃用)。更关键的是:只能作用于真实物理网卡,比如eth0、ens33;lo、vethxxx、docker0这些无效——除非你明确要控容器网络且已桥接好ifb。
操作前务必确认三件事:
- 用
ip link show检查目标网卡状态是否为UP,名字是否准确(常见坑:以为是eth0,实际是ens33) - 运行
tc qdisc show dev eth0,如果有输出,说明已有规则,不清理就加新规则会冲突或被忽略 - 所有
tc命令必须加sudo,普通用户执行会静默失败或报Permission denied
tbf限速最简但参数容错低,burst和latency设错就丢包
tbf适合全局限速,比如给整台服务器出口设天花板。但它对burst和latency极其敏感,设错直接导致小包(SSH、DNS)频繁排队丢弃,或限速形同虚设。
正确示例(限制eth0出向为5Mbps):
sudo tc qdisc add dev eth0 root tbf rate 5mbit burst 64kb latency 70ms
注意几个硬性细节:
- 单位严格区分大小写:
mbit(兆比特)≠mbps(非标准,部分内核拒识) -
burst太小(如1kb)会让小包等不到令牌,直接丢;太大(如10mb)则突发流量冲垮限速——经验上设为rate / 10左右较平衡(5mbit →64kb合理) -
latency不是网络延迟,而是包在队列里最长能等多久;设太小(10ms)易丢包,太大(2s)会让突发“憋太久”,影响交互响应
按IP或端口限速必须用htb+filter,match方向极易搞反
想只限某客户端上传(比如限制192.168.1.100的出向流量),不能用tbf,得用htb建分层结构,再配u32过滤器。最大陷阱在match ip src的含义:
在egress(出向)规则中,match ip src 192.168.1.100匹配的是“本机作为服务端、向外发送给该IP的响应包”——即该IP是**目的端**,不是源端。真正想限“来自192.168.1.100的请求导致本机上传”,应匹配目的IP:match ip dst 192.168.1.100(因为请求进来了,本机回包才发出去)。
典型流程(限192.168.1.100的响应流量为2mbit):
sudo tc qdisc add dev eth0 root handle 1: htb default 30<br>sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit<br>sudo tc class add dev eth0 parent 1:1 classid 1:10 htb rate 2mbit ceil 2mbit<br>sudo tc filter add dev eth0 parent 1: protocol ip u32 match ip dst 192.168.1.100 flowid 1:10
若限某端口(如只限HTTP回包),过滤器写成:match ip dport 80 0xffff(注意十六进制掩码0xffff)
入站限速要用ingress+mirred,别信imq
现代内核(5.0+)已弃用imq模块,iptables -t mangle -A PREROUTING -j IMQ这条路走不通。替代方案是用tc ingress配合mirred重定向:
sudo tc qdisc add dev eth0 handle ffff: ingress<br>sudo tc filter add dev eth0 parent ffff: protocol ip u32 match ip src 0.0.0.0/0 action mirred egress redirect dev ifb0
这条命令含义:
- 在
eth0上添加ingress类型qdisc(仅捕获入站包,不排队) - 所有来自任意源IP的入站IP包,被
mirred动作重定向到ifb0设备 - 之后你就可以像控制出向一样,在
ifb0上跑tbf或htb了
但注意:ifb0需提前加载模块并启用:modprobe ifb numifbs=1 && ip link set dev ifb0 up。漏掉这步,mirred会静默失败。
ingress规则本身不排队,必须靠mirred跳转到ifb0才能真正限速;还有就是所有match字段在出向规则里的语义,和直觉相反——src是本机IP,dst才是远端IP。











