一、TC概述

TC规则主要涉及到“队列(QUEUE) 分类器(CLASS) 过滤器(FILTER)”三项。TC除对可以对内网访问外网流量进行管理外,TC还可以配合filter的set-mark功能做流量上传管控。TC具有两种流量管控方式:HTC和CBQ。HTB是CBQ管理方式的优化,本身不需要写太多复杂代码就可以很好的实现QoS的需求,也是平时我们经常会用的方式。

二、网速变慢的原因及TC的工作原理

1、速度变慢的原因

a、tcp/ip 协议规定每个封包都需要有ACKNOWLEDGE讯息的回传,也就是说,传输的资料需要有一个收到资料的讯息回复,才能决定后面的传输速度,并决定是否重 新传输遗失的资料,上行的带宽一部分就是用来传输这些ACK资料的。上行带宽占用大的时候,就会影响ACK资料的传送速度,进而影响到下载速度,

b、试验证明,当上传满载时,下载速度变为原来速度的40%,甚至更低,,因为上载文件(包括ftp上传,发邮件SMTP),如果较大,一个的通讯量令带宽饱和,那么所有的数据包按照先进先出的原则进行排队和等待,这就可以解释为什么网内其中有人用ftp上载文件或发送大邮件的时候,整个网速变得很慢的原因。

2、TC的工作原理

为了解决这些速度问题,对经过线路的数据进行了有规则的分流。把本来在宽带上的瓶颈转移到我们的LINUX路由器上,可以把带宽控制的比我们购买的带宽小一点。 这样,我们就可以方便的用tc技术对经过的数据进行分流与控制。

我们的想像就像马路上的车道一样,有高速道,还有小车道,大车道,需要高速的syn ack icmp ssh等走高速道,需要大量传输的ftp-data,smtp等走大车道,不能让它堵塞整条马路,各行其道。

3、tc 和iptables的配合

我们设置过滤器以便用iptables对数据包进行分类,因为iptables更灵活,而且还可以为每个规则设置计数器,iptables用 mangle链来mark数据包,告诉了内核,数据包会有一个特定的FWMARK标记值(handle x fw) 表明它应该送给那个类(classid x:x),而prio是优先值,表明那些重要数据应该优先通过那个通道,首先选择队列(选择htb),

一般系统默认的是fifo的先进先出队列,就是说包是按照先来先处理的原则,如果有一个大的数据包在前面,那么后面的包只能等前面的发完后才能接着发了,这样就算后面既使是一个小小的ack包,也要等待了,这样上传就影响了下载,就算你有很大的下载带宽也无能为力。

HTB(Hierarchical token bucket,分层的令牌桶),就像CBQ一样工作,但是并不靠计算闲置时间来整形,它是一个分类的令牌桶过滤器。,它只有很少的参数。

1结构简图:                1:
2             ~~~~~~~~~~~~~~~~`~~~~~
3  ~_________1:1~~~~~~~~~1:2________
4  |~~~|~~~~|~~~~|~~~~~|~~~~~~~~|~~~~~~~~|~~~~~~~|
5  1:11~~~1:12~~~~~~~~~~~~1:21~~~1:22~~~1:23~~1:24
6  优先顺序: 1:11 1:12 1:21 1:22 1:23 1:24

三、TC命令的用法

1、创建一个HTB的根,默认类为1:20(后面就需要定义1:20的类)

1tc qdisc add dev eth0 root handle 1: htb default 20

2、创建一个HTB的类,流量的限制就是在这里限制的,并设置突发

1tc class add dev eth0 parent 1: classid 1:1 htb rate 200kbit ceil 200kbit burst 20k(突发流量)

3、创建一个过滤规则把要限制流量的数据过滤出来,并发给上面的类来限制速度。

1tc filter add dev eth0 parent 1: prio 1 protocol ip u32 match ip sport 80 0xfff flowid 1:1

参数的说明:

  • rate rate allocated to this class (class can still borrow)
  • burst max bytes burst which can be accumulated during idle period {computed}
  • mpu minimum packet size used in rate computations
  • overhead per-packet size overhead used in rate computations
  • ceil definite upper class rate (no borrows) {rate}
  • cburst burst but for ceil {computed}
  • mtu max packet size we create rate map for {1600}
  • prio priority of leaf; lower are served first {0}
  • quantum how much bytes to serve from leaf at once {use r2q}

平时我们经常用的只有四个

  • burst:突发流量
  • rate:是一个类保证得到的带宽值,如果有不只一个类,请保证所有子类总和是小于或等于父类,
  • ceil: ceil是一个类最大能得到带宽值。
  • prio: 是优先权的设置,数值越大,优先权越小,如果是分配剩余带宽,就是数值小的会最优先取得剩余的空闲的带宽权。

4、另一个和HTB经常配置使用的队列方式——SFQ

随机公平队列(SFQ),SFQ的关键词是“会话”(或称作流),主要针对一个TCP会话或者UDP流,流量被分成相当多数量的FIFO队列中,每个队列对应一个会话。数据按照简单轮转的方式发送,每个会话都按顺序得到发送机会。这种方式非常公平,保证了每个会话都不会被其它会话所淹没,SFQ之所以被称为“随机”,是因为它并不是真的为每个会话创建一个队列,而是使用一个散列算法,把所有的会话映射到有限的几个队列中去。不被某个连接不停占用带宽,以保证带宽的平均公平使用。

1tc qdisc add dev eth0 parent 1:11 handle 111: sfq perturb 5

参数perturb是多少秒后重新配置一次散列算法,默认为10秒。

设置过滤器,handle是iptables作mark的值,让被iptables在mangle链做了mark的不同的值选择不同的通道classid,而prio是过滤器的优先级别

1tc filter add dev eth1 parent 1:0 protocol ip prio 1 handle 1 fw classid 1:11

设置下行的限制例子

1tc qdisc add dev $DEV handle ffff: ingress
2tc filter add dev $DEV parent ffff: protocol ip prio 50 handle 8 fw police rate ${downlink}kbit burst 10k drop flowid :8

设置入队的规则,是因为把一些经常会造成下载大文件的端口进行控制,不让他们来得太快,导致堵塞,来得太快,就直接drop,就不会浪费和占用机器时间和力量去处理了。把下行速率控制在大概1000-1500K(大约为带宽的50%),因为这个速度已经够用了,以便能够得到更多的并发下载连接。

1tc qdisc add dev $DEV handle ffff: ingress
2tc filter add dev $DEV parent ffff: protocol ip prio 50 handle 8 fw police rate ${downlink}kbit burst 10k drop flowid :8

如果内部网数据流不是很疯狂的话,就不用做下载的限制了,用#符号屏蔽上面两行既可。如果要对任何进来的数据进行限速的话,可以用下面这句。

四、tc和iptable的混合用法

开始给数据包打标记:把出去的不同类数据包(为dport)给mark上标记1—6,让它走不同的通道。把进来的数据包(为sport)给mark上标记8,让它受到下行的限制,以免速度太快而影响全局。每条规则下跟着return的意思是可以通过RETURN方法避免遍历所有的规则,加快了处理速度。

 1#设置TOS的处理:
 2iptables -t mangle -A PREROUTING -m tos --tos Minimize-Delay(最小延时) -j MARK --set-mark 1
 3iptables -t mangle -A PREROUTING -m tos --tos Minimize-Delay -j RETURN
 4iptables -t mangle -A PREROUTING -m tos --tos Minimize-Cost(最小成本) -j MARK --set-mark 4
 5iptables -t mangle -A PREROUTING -m tos --tos Minimize-Cost -j RETURN
 6iptables -t mangle -A PREROUTING -m tos --tos Maximize-Throughput(最大吞吐量) -j MARK --set-mark 5
 7iptables -t mangle -A PREROUTING -m tos --tos Maximize-Througput -j RETURN
 8
 9#提高TCP初始连接(也就是带有SYN的数据包)的优先权是非常明智的。
10iptables -t mangle -A PREROUTING -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j MARK --set-mark 1
11iptables -t mangle -A PREROUTING -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j RETURN
12
13#想ICMP 想ping有良好的反应,放在第一类。
14iptables -t mangle -A PREROUTING -p icmp -j MARK --set-mark 1
15iptables -t mangle -A PREROUTING -P icmp -j RETURN
16
17#small packets (probably just ACKS)长度小于64的小包通常是需要快些的,一般是用来确认tcp的连接的,让它跟快些的通道吧。
18iptables -t mangle -A PREROUTING -p tcp -m length --length :64 -j MARK --set-mark 2
19iptables -t mangle -A PREROUTING -p tcp -m length --length:64 -j RETURN
20
21#ftp放第二类,因为一般是小包,ftp-data放在第5类,因为一般是大时数据的传送。
22iptables -t mangle -A PREROUTING -p tcp -m tcp --dport ftp -j MARK --set-mark 2
23iptables -t mangle -A PREROUTING -p tcp -m tcp --dport ftp -j RETURN
24iptables -t mangle -A PRETOUTING -p tcp -m tcp --dport ftp-data -j MARK --set-mark 5
25iptables -t mangle -A PREROUTING -p tcp -m tcp --dport -j RETURN
26iptables -t mangle -A PREROUTING -p tcp -m tcp --sport ftp -j MARK --set-mark 8
27iptables -t mangle -A PREROUTING -p tcp -m tcp --sport ftp -j RETURN
28iptables -t mangle -A PREROUTING -p tcp -m tcp --sport ftp-data -j MARK --set-mark 8
29iptables -t mangle -A PREROUTING -p tcp -m tcp --sport ftp-data -j RETURN
30
31#提高SSH数据包的优先权:放在第1类,要知道SSH是交互式的和重要的,不容待慢:
32iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 22 -j MARK --set-mark 1
33iptables -t mangle -A PREROUTING -p tcp -m tcp --dport -j RETURN
34
35#SMTP邮件,放在第4类,因为有时有人发送很大的邮件,为避免它堵塞,让它跑第4道吧
36iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 25 -j MARK --st-mark 4
37iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 25 -j RETURN
38iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 25 -j MARK --set-mark 8
39iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 25 -j RETURN
40
41#name-domain server:放在第1类,这样连接带有域名的连接才能快速找到对应有的地址,提高速度
42iptables -t mangle -A PREROUTING -p udp -m udp --dport 53 -j MARK --set-mark 1
43iptables -t mangle -A PREROUTING -P udp -m udp --dport 53 -j RETURN
44
45#HTTP: 放在第3类,是最常用的,最多人用的
46iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 80 -j MARK --set-mark 3
47iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 80 -j RETURN
48iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 80 -j MARK --set-mark 8
49iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 80 -j RETURN
50
51#pop邮件放在第3类:
52iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 110 -j MARK --set-mark 3
53iptables -t mangle -A PREROUTING -p tcp -m tcp --dprot 110 -j RETURN
54iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 110 -j MARK --set-mark 8
55iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 110 -j RETURN
56
57#MICSOSOFT-SQL-SERVE:放在第2类,我这里认为较重要,一定保证速度和优先的
58iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 1433 -j MARK --set-mark 3
59iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 1433 -j RETURN
60iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 1433 -j MARK --set-mark 8
61iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 1433 -j RETURN
62
63#https:放在第3类
64iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 443 -j MARK --set-mark 3
65iptables -t mangle -A PREROUTING -p tcpm -m tcp --dport 443 -j RETURN
66iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 443 -j MAKR --set-mark 8
67iptables -t mangle -A PREROUTING -P tcp -m tcp --sport 443 -j RETURN
68
69#voip用,提高,语音要保持高速才不会断续
70iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 1720 -j MARK--SET-MARK 1
71iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 1720 -j RETURN
72iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 1720 -j MAKR --set-mark 8
73iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 1720 -j RETURN
74
75#VPN 用作voip的,也要走高速路,才不会断续
76iptables -t mangle -A PREROUTING -p udp -m udp --dport 7707 -j MARK --set-mark 1
77iptables -t mangle -A PREROUTING -p udp -m udp --dport 7707 -j RETURN
78iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 7070 -j MARK --set-mark 1
79iptables -t mangle -A PREROUTING -p tcp -m tcp --dport -j RETURN
80
81#提高ssh和icmp数据包的优先权:放在第1类
82iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 22 -j MARK --set-mark 1
83iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 22 -j RETURN
84iptables -t mangle -A OUTPUT -p icmp -j MARK --set-mark 1
85iptables -t mangle -A OUTPUT -p icmp -j RETURN
86
87#本地small packet (probably just ACKS)
88iptables -t mangle -A OUTPUT -p tcp -m length --length :64 --set-mark 2
89iptables -t mangle -A OUTPUT -p tcp -m length --length :64 -j RETURN

向PRETOUTRIN中添加完mangle规则后,用这条规则结束prerouting表:也就是说前面没有打过标记的数据包就交给1:24来处理实际 上是不必要的,因为1:24是缺省类,但仍然打上标记是为了保持整个设置的协调一致,而且这样,还能看到规则的数据包计数:

1iptables -t mangle -A PREROUTING -i $DEV -j MARK --set-mark 6

对某人限制

1iptables -t mangle -I PREROUTING 1 -s 192.168.xx.xx -j MAKR --set-mark 6
2iptables -t mangle -I PREROUTING 2 -s 192.168.xx.xx -j RETURN

u32的应用

1tc filter add dev eth0 parent 1:0 protocol ip prio 1 u3

这就是所谓的匹配,可以匹配数据包的任意部分。根据源目的地址单个IP地址可以用/32来表示:

1match ip src 0.0.0.0/0
2match ip dst 1.2.3.0/24

根据源/目的端口可以这样表示:

1match ip sport 80 0xffff
2match ip dport 80 0xffff

根据IP协议:

1match ip protocol (udp tcp icmp gre ipsec)
2比如icmp协议是1 match ip protocol 1 0xff

举例:

1tc filter add dev $DEV parent 1:0 protocol ip prio 1 u32 match ip dst 4.3.2.1/32 flowid 10:1
2tc filter add dev $DEV parent 1:0 protocol ip prio 1 u32 match ip src 4.3.2.1/32 match ip sport 80 0xffff flowid 10:1