流量控制 (tc) 过滤器不工作

流量控制 (tc) 过滤器不工作

我正在使用 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) 被分配给上面定义的类别。

相关内容