![流量控制 (tc) 过滤器不工作](https://linux22.com/image/762899/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6%20(tc)%20%E8%BF%87%E6%BB%A4%E5%99%A8%E4%B8%8D%E5%B7%A5%E4%BD%9C.png)
我正在使用 Debian,并尝试根据 IP 限制上传带宽。
配置如下:
#!/bin/bash
tc=/sbin/tc
$tc qdisc del dev eth0 root 2> /dev/null > /dev/null
$tc qdisc del dev eth0 ingress 2> /dev/null > /dev/null
$tc qdisc del dev tun0 root 2> /dev/null > /dev/null
$tc qdisc del dev tun0 ingress 2> /dev/null > /dev/null
$tc qdisc add dev eth0 root handle 1: htb default 30
$tc class add dev eth0 parent 1: classid 1:1 htb rate 5.0mbit burst 6k
$tc class add dev eth0 parent 1:1 classid 1:10 htb rate 2.0mbit ceil 4.5mbit burst 2k prio 1
$tc class add dev eth0 parent 1:1 classid 1:20 htb rate 2.0mbit ceil 4.5mbit burst 3k prio 2
$tc class add dev eth0 parent 1:1 classid 1:30 htb rate 0.5mbit burst 1k prio 3
$tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
$tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
$tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
$tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip src 192.168.1.1 flowid 1:10
$tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip src 192.168.1.2 flowid 1:20
$tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip src 192.168.1.4 flowid 1:30
“设置”似乎很好:
filter parent 1: protocol ip pref 1 u32 chain 0
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800: ht divisor 1
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:10 not_in_hw
match c0a80101/ffffffff at 12
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:20 not_in_hw
match c0a80102/ffffffff at 12
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::802 order 2050 key ht 800 bkt 0 flowid 1:30 not_in_hw
match c0a80104/ffffffff at 12
但尽管使用了过滤器,我最终还是让所有客户端都处于 1:30 状态:
+---(1:1) htb rate 5Mbit ceil 5Mbit burst 6Kb cburst 1600b
| Sent 18121225 bytes 29841 pkt (dropped 0, overlimits 1926 requeues 0)
| backlog 0b 0p requeues 0
|
+---(1:10) htb prio 1 rate 2Mbit ceil 4500Kbit burst 2Kb cburst 1599b
| Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
| backlog 0b 0p requeues 0
|
+---(1:20) htb prio 2 rate 2Mbit ceil 4500Kbit burst 3Kb cburst 1599b
| Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
| backlog 0b 0p requeues 0
|
+---(1:30) htb prio 3 rate 500Kbit ceil 500Kbit burst 1Kb cburst 1600b
Sent 18121225 bytes 29841 pkt (dropped 23532, overlimits 27820 requeues 0)
backlog 244086b 117p requeues 0
我究竟做错了什么?
更新
我能够使用 iptables 应用过滤规则:
$tc filter add dev eth0 parent 1: protocol ip handle 2 fw flowid 1:20
$ipt -t mangle -A FORWARD -i eth1 -o eth0 -s 192.168.1.2 -j MARK --set-mark 2
这会导致来自 192.168.1.2 的流量被放入 1:20:
+---(1:1) htb rate 5Mbit ceil 5Mbit burst 6Kb cburst 1600b
| Sent 34671556 bytes 40595 pkt (dropped 0, overlimits 8591 requeues 0)
| backlog 0b 0p requeues 0
|
+---(1:10) htb prio 1 rate 2Mbit ceil 4500Kbit burst 2Kb cburst 1599b
| Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
| backlog 0b 0p requeues 0
|
+---(1:20) htb prio 2 rate 2Mbit ceil 3500Kbit burst 3Kb cburst 1599b
| Sent 26070590 bytes 17443 pkt (dropped 0, overlimits 10466 requeues 0)
| backlog 0b 0p requeues 0
|
+---(1:30) htb prio 3 rate 500Kbit ceil 500Kbit burst 1Kb cburst 1600b
Sent 8600966 bytes 23152 pkt (dropped 0, overlimits 23146 requeues 0)
backlog 57060b 70p requeues 0
到目前为止,u32 过滤器似乎不起作用。
答案1
谢谢 @AB谁让我知道了 tc 无法过滤的原因。
我确实在所有外部接口上使用了 MASQUERADING,而且似乎这些规则在 tc 可以过滤数据包之前就已应用。这导致以下建议:
如果您在传出接口上使用 MASQUERADE 规则,则需要使用流量控制中的 fw 过滤器并使用 iptables 标记数据包。
对于更有经验的用户来说,这似乎很明显,但它没有在任何地方提及,并且(至少对我来说)很难找到。
例子:
#!/bin/bash
tc=/sbin/tc
ipt=/sbin/iptables
$tc qdisc add dev eth0 root handle 1: htb default 30
# shape general uplink speed
$tc class add dev eth0 parent 1: classid 1:1 htb rate 5.0mbit burst 6k
$tc class add dev eth0 parent 1:1 classid 1:10 htb rate 2.0mbit ceil 4.0mbit burst 2k prio 1
$tc class add dev eth0 parent 1:1 classid 1:20 htb rate 2.5mbit ceil 4.0mbit burst 3k prio 2
$tc class add dev eth0 parent 1:1 classid 1:30 htb rate 0.5mbit ceil 1.0mbit burst 1k prio 3
# stochastic fairness
$tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
$tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
$tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
# filtering on eth0
$tc filter add dev eth0 parent 1: protocol ip handle 10 fw flowid 1:10
$tc filter add dev eth0 parent 1: protocol ip handle 20 fw flowid 1:20
$tc filter add dev eth0 parent 1: protocol ip handle 30 fw flowid 1:30
# marking packets via iptables
$ipt -t mangle -I FORWARD -i eth1 -o eth0 -s 192.168.1.2 -j MARK --set-mark 20
$ipt -t mangle -I FORWARD -i eth1 -o eth0 -s 192.168.1.4 -j MARK --set-mark 30
$ipt -t mangle -I FORWARD -i eth1 -o eth0 -s 192.168.1.21 -j MARK --set-mark 10
这些设置会导致来自上述来源的数据包(-s) 被分配给上面定义的类别。