有些队列的功能是非常简单的,它们对报文分组实行先来先走的策略。有些队列则功能复杂,会将不同的报文分组进行排队、分类,并根据不同的原则,以不同的顺序发送队列中的报文分组。为实现这样的功能,这些复杂的队列需要使用不同的过滤器(Filter)来把报文分组分成不同的类别(Class)。这里把这些复杂的队列称为可分类(ClassfuI)的队列。通常,要实现功能强大的流量控制,可分类的队列是必不可少的。因此,类别(class)和过滤器(Filter)也是流量控制的另外两个重要的基本概念。图2所示的是一个可分类队列的例子。
图2多类别队列
由图2可以看出,类别(CIass)和过滤器(Filter)都是队列的内部结构,并且可分类的队列可以包含多个类别,同时,一个类别又可以进一步包含有子队列,或者子类别。所有进入该类别的报文分组可以依据不同的原则放入不同的子队列或子类别中,以此类推。而过滤器(Filter)是队列用来对数据报文进行分类的工具,它决定一个数据报文将被分配到哪个类别中。
二、使用TC
在Linux中,流量控制都是通过TC这个工具来完成的。通常,要对网卡进行流量控制的配置,需要进行如下的步骤:
◆为网卡配置一个队列;
◆在该队列上建立分类;
◆根据需要建立子队列和子分类;
◆为每个分类建立过滤器。
在Linux中,可以配置很多类型的队列,比如CBQ、HTB等,其中CBQ比较复杂,不容易理解。HTB(HierarchicaITokenBucket)是一个可分类的队列,与其他复杂的队列类型相比,HTB具有功能强大、配置简单及容易上手等优点。在TC中,使用"major:minor"这样的句柄来标识队列和类别,其中major和minor都是数字。
对于队列来说,minor总是为0,即"major:0"这样的形式,也可以简写为"major:比如,队列1:0可以简写为1:。需要注意的是,major在一个网卡的所有队列中必须是惟一的。对于类别来说,其major必须和它的父类别或父队列的major相同,而minor在一个队列内部则必须是惟一的(因为类别肯定是包含在某个队列中的)。举个例子,如果队列2:包含两个类别,则这两个类别的句柄必须是2:x这样的形式,并且它们的x不能相同,比如2:1和2:2。
下面,将以HTB队列为主,结合需求来讲述TC的使用。假设eth0出口有100mbit/s的带宽,分配给WWW、E-mail和Telnet三种数据流量,其中分配给WWW的带宽为40Mbit/s,分配给Email的带宽为40Mbit/s,分配给Telnet的带宽为20Mbit/S。如图3所示。
需要注意的是,在TC中使用下列的缩写表示相应的带宽:
◆KbpskiIobytespersecond,即"千字节每秒;
◆Mbpsmegabytespersecond,即"兆字节每秒,
◆Kbitkilobitspersecond,即"千比特每秒;
◆Mbitmegabitspersecond,即"兆比特每秒。
三、创建HTB队列
有关队列的TC命令的一般形式为:
#tcqdisc[add|change|replace|link]devDEV[parentqdisk-id|root][handleqdisc-id]qdisc[qdiscspecificparameters]
首先,需要为网卡eth0配置一个HTB队列,使用下列命令:
#tcqdiscadddeveth0roothandle1:htbdefault11
这里,命令中的"add表示要添加,"deveth0表示要操作的网卡为eth0。"root表示为网卡eth0添加的是一个根队列。"handle1:表示队列的句柄为1:。"htb表示要添加的队列为HTB队列。命令最后的"default11是htb特有的队列参数,意思是所有未分类的流量都将分配给类别1:11。
四、为根队列创建相应的类别
有关类别的TC命令的一般形式为:
#tcclass[add|change|replace]devDEVparentqdisc-id[classidclass-id]qdisc[qdiscspecificparameters]
可以利用下面这三个命令为根队列1创建三个类别,分别是1:11、1:12和1:13,它们分别占用40、40和20mb[t的带宽。
#tcclassadddeveth0parent1:classid1:1htbrate40mbitceil40mbit
#tcclassadddeveth0parent1:classid1:12htbrate40mbitceil40mbit
#tcclassadddeveth0parent1:cllassid1:13htbrate20mbitceil20mbit
命令中,"parent1:"表示类别的父亲为根队列1:。"classid1:11"表示创建一个标识为1:11的类别,"rate40mbit"表示系统
将为该类别确保带宽40mbit,"ceil40mbit",表示该类别的最高可占用带宽为40mbit。
五、为各个类别设置过滤器
有关过滤器的TC命令的一般形式为:
#tcfilter[add|change|replace]devDEV[parentqdisc-id|root]protocolprotocolpriopriorityfiltertype[filtertypespecificparameters]flowidflow-id
由于需要将WWW、E-mail、Telnet三种流量分配到三个类别,即上述1:11、1:12和1:13,因此,需要创建三个过滤器,如下面的三个命令:
#tcfilteradddeveth0protocolipparent1:0prio1u32matchipdport800xffffflowid1:11
#tcfilteradddeveth0prtocolipparent1:0prio1u32matchipdport250xffffflowid1:12
#tcfilteradddeveth0protocolipparent1:0prio1u32matchipdport23oxffffflowid1:13
这里,"protocolip"表示该过滤器应该检查报文分组的协议字段。"pr[o1"表示它们对报文处理的优先级是相同的,对于不同优先级的过滤器,系统将按照从小到大的优先级。
顺序来执行过滤器,对于相同的优先级,系统将按照命令的先后顺序执行。这几个过滤器还用到了u32选择器(命令中u32后面的部分)来匹配不同的数据流。以第一个命令为例,判断的是dport字段,如果该字段与Oxffff进行与操作的结果是8O,则"flowid1:11"表示将把该数据流分配给类别1:11。更加详细的有关TC的用法可以参考TC的手册页。
六、复杂的实例
在上面的例子中,三种数据流(www、Email、Telnet)之间是互相排斥的。当某个数据流的流量没有达到配额时,其剩余的带宽并不能被其他两个数据流所借用。在这里将涉及如何使不同的数据流可以共享一定的带宽。
首先需要用到HTB的一个特性,即对于一个类别中的所有子类别,它们将共享该父类别所拥有的带宽,同时,又可以使得各个子类别申请的各自带宽得到保证。这也就是说,当某个数据流的实际使用带宽没有达到其配额时,其剩余的带宽可以借给其他的数据流。而在借出的过程中,如果本数据流的数据量增大,则借出的带宽部分将收回,以保证本数据流的带宽配额。
下面考虑这样的需求,同样是三个数据流WWW、E-mail和Telnet,其中的Telnet独立分配20Mbit/s的带宽。另一方面,VWVW和SMTP各自分配40Mbit/s。同时,它们又是共享的关系,即它们可以互相借用带宽。如图3所示。
需要的TC命令如下:
#tcqdiscadddeveth0roothandle1:htbdefault21
#tcclassadddeveth0partent1:classid1:1htbrate20mbitceil20mbit
#tcclassadddeveth0parent1:classid1:2htbrate80mbitceil80mbit
#tcclassadddeveth0parent1:classid1:21htbrate40mbitceil20mbit
#tcclassadddeveth0parent1:2classid1:22htbrate40mbitceil80mbit
#tcfilteradddeveth0protocolparent10prio1u32matchipdport800xffffflowid1:21
#tcfilteradddeveth0protocolparent1:0prio1u32matchipdport250xffffflowid1:22
#tcfilteradddeveth0protocolparent1:0prio1u32matchipdport230xffffflowid1:1
这里为根队列1创建两个根类别,即1:1和1:2,其中1:1对应Telnet数据流,1:2对应80Mbit的数据流。然后,在1:2中,创建两个子类别1:21和1:22,分别对应WWW和E-mail数据流。由于类别1:21和1:22是类别1:2的子类别,因此他们可以共享分配的80Mbit带宽。同时,又确保当需要时,自己的带宽至少有40Mbit。
从这个例子可以看出,利用HTB中类别和子类别的包含关系,可以构建更加复杂的多层次类别树,从而实现的更加灵活的带宽共享和独占模式,达到企业级的带宽管理目的。
QOS无非就是使用了linux的2个工具,tc和iptables,不管管理界面做的多么垃圾还是多么强大,都是最终翻译成这2个工具的script去执行,并且无论多么NB的管理界面都有很大的局限性(整半天界面也就是实现了命令行下的几个参数的功能而已),所以无法完全发挥这2个工具的作用.不要以为TOMATO的QOS就很NB,其实就是对这2个工具做了比较好的封装罢了,都是linux,用好了,分不出什么高下的.如果你懂linuxshell编程,并且懂数据挖掘与机器学习的理论,你完全可以根据一些算法写出带有人工智能特性的QOS脚本,wayos的QOS其实就是这么实现的而已.(美好的展望一下,不多说了,进入正题)
TC是干什么的呢:TC就是建立数据通道的,建立的通道有数据包管理方式,通道的优先级,通道的速率(这就是限速)
iptables又是干什么的呢是决定哪个ip或者mac或者某个应用,走哪个通道的.
这就是QOS+限速的原理,大伙明白了吧
详细的我就不写了,看上面的好好学习,这里我就贴出来我的学习成果吧,直接可用的限速脚本:以下说的是单位是kbps,跟普通迅雷上看到的下载速度的换算关系是除以81600/8=200K,迅雷上看到的就是200KB/s
本帖隐藏的内容
#现在开始用TC建立数据的上行和下行通道TCA=”tcclassadddevbr0″TFA=”tcfilteradddevbr0″tcqdiscdeldevbr0roottcqdiscadddevbr0roothandle1:htbtcclassadddevbr0parent1:classid1:1htbrate1600kbit#这个1600是下行总速度$TCAparent1:1classid1:10htbrate200kbitceil400kbitprio2#这个是10号通道的下行速度,最小200,最大400,优先级为2$TCAparent1:1classid1:25htbrate1000kbitceil1600kbitprio1#这是我自己使用的特殊25号通道,下行速度最小1000,最大1600,优先级为1,呵呵,待遇就是不一样$TFAparent1:0prio2protocoliphandle10fwflowid1:10$TFAparent1:0prio1protocoliphandle25fwflowid1:25tcqdiscadddevbr0ingress$TFAparentffff:protocoliphandle35fwpolicerate800kbitmtu12kburst10kdrop#这是我自己使用的35号上行通道,最大速度800$TFAparentffff:protocoliphandle50fwpolicerate80kbitmtu12kburst10kdrop#这是给大伙使用的50号上行通道,最大速度80
#好了,现在用iptables来觉得哪些人走哪些通道吧,哈哈,由于ddwrt的iptables不支持iprange,所以只能每个IP写一条语句,否则命令无效
iptables-tmangle-APOSTROUTING-d192.168.1.22-jMARK–set-mark10#ip为192.168.1.22的走10号通道iptables-tmangle-APOSTROUTING-d192.168.1.22-jRETURN#给每条规则加入RETURN,这样效率会更高.iptables-tmangle-APOSTROUTING-d192.168.1.23-jMARK–set-mark25#ip为192.168.1.23的走25号特殊通道,23是我的ip,所以特殊点iptables-tmangle-APOSTROUTING-d192.168.1.23-jRETURN#给每条规则加入RETURN,这样效率会更高.
iptables-tmangle-APREROUTING-s192.168.1.22-jMARK–set-mark50#ip为22的走50号上行通道iptables-tmangle-APREROUTING-s192.168.1.22-jRETURN#给每条规则加入RETURN,这样效率会更高.iptables-tmangle-APREROUTING-s192.168.1.23-jMARK–set-mark35#ip为23的走35号上行通道,我自己的IP.呵呵iptables-tmangle-APREROUTING-s192.168.1.23-jRETURN#给每条规则加入RETURN,这样效率会更高.
现在来看看如何限制TCP和UDP的连接数吧,很NB的(不知道标准版本和简化版是否支持,一下语句不保证可用,因个人路由器环境而定):iptables-IFORWARD-ptcp-mconnlimit–connlimit-above100-jDROP#看到了吧,在FORWARD转发链的时候,所有tcp连接大于100的数据包就丢弃!是针对所有IP的限制iptables-IFORWARD-pudp-mlimit–limit5/sec-jDROP#UDP是无法控制连接数的,只能控制每秒多少个UDP包,这里设置为每秒5个,5个已经不少了,10个就算很高了,这个是封杀P2P的利器,一般设置为每秒3~5个比较合理.如何查看命令是否生效呢:执行iptables-LFORWARD就可以看到如下结果:DROPtcp–anywhereanywhere#conn/32>100DROPudp–anywhereanywherelimit:avg5/secbu如果出现了这2个结果,说明限制连接数的语句确实生效了,如果没有这2个出现,则说明你的dd-wrt不支持connlimit限制连接数模块.
现在我想给自己开个后门,不受连接数的限制该怎么做呢看下面的:iptables-IFORWARD-s192.168.1.23-jRETURN#意思是向iptables的FORWARD链的最头插入这个规则,这个规则现在成为第一个规则了,23是我的IP,就是说,只要是我的IP的就不在执行下面的连接数限制的规则语句了,利用了iptables链的执行顺序规则,我的IP被例外了.
告诉大家一个查看所有人的连接数的语句:sed-n‘s%.*src=\(192.168.[0-9.]*\).*%\1%p’/proc/net/ip_conntrack|sort|uniq-c#执行这个就可以看到所有IP当前所占用的连接数
对于上面的脚本,有一些比较疑惑人的地方,现在来讲讲:br0:这个是一个ddwrt的网桥,这个网桥桥接了无线和有线的接口,所以在这上面卡流量,就相当于卡了所有无线和有线的用户.具体信息可以输入ifconfig命令进行查看.规则链顺序问题:在br0上iptables规则链的顺序是比较奇怪的,正常的顺序入站的数据包先过PERROUTING链,出站数据包先过POSTROUTING链,但是ddwrt的br0网桥顺序与正常的顺序正好相反!在ddwrt上入站的数据包被当成出站的,出站的数据包被当成入站的,所以上面的脚本会那么写.
TC命令tc可以使用以下命令对QDisc、类和过滤器进行操作:add在一个节点里加入一个QDisc、类或者过滤器。添加时,需要传递一个祖先作为参数,传递参数时既可以使用ID也可以直接传递设备的根。如果要建立一个QDisc或者过滤器,可以使用句柄(handle)来命名;如果要建立一个类,可以使用类识别符(classid)来命名。
remove删除有某个句柄(handle)指定的QDisc,根QDisc(root)也可以删除。被删除QDisc上的所有子类以及附属于各个类的过滤器都会被自动删除。
change以替代的方式修改某些条目。除了句柄(handle)和祖先不能修改以外,change命令的语法和add命令相同。换句话说,change命令不能一定节点的位置。
replace对一个现有节点进行近于原子操作的删除/添加。如果节点不存在,这个命令就会建立节点。
link只适用于DQisc,替代一个现有的节点。
历史tc由AlexeyN.Kuznetsov编写,从Linux2.2版开始并入Linux内核。SEEALSOtc-cbq(8)、tc-htb(8)、tc-sfq(8)、tc-red(8)、tc-tbf(8)、tc-pfifo(8)、tc-bfifo(8)、tc-pfifo_fast(8)、tc-filters(8)Linux从kernel2.1.105开始支持QOS,不过,需要重新编译内核。运行makeconfig时将EXPERIMENTAL_OPTIONS设置成y,并且将ClassBasedQueueing(CBQ),TokenBucketFlow,TrafficShapers设置为y,运行makedep;makeclean;makebzilo,生成新的内核。
在Linux操作系统中流量控制器(TC)主要是在输出端口处建立一个队列进行流量控制,控制的方式是基于路由,亦即基于目的IP地址或目的子网的网络号的流量控制。流量控制器TC,其基本的功能模块为队列、分类和过滤器。Linux内核中支持的队列有,ClassBasedQueue,TokenBucketFlow,CSZ,FirstInFirstOut,Priority,TEQL,SFQ,ATM,RED。这里我们讨论的队列与分类都是基于CBQ(ClassBasedQueue)的,而过滤器是基于路由(Route)的。
配置和使用流量控制器TC,主要分以下几个方面:分别为建立队列、建立分类、建立过滤器和建立路由,另外还需要对现有的队列、分类、过滤器和路由进行监视。
其基本使用步骤为:
1)针对网络物理设备(如以太网卡eth0)绑定一个CBQ队列;
2)在该队列上建立分类;
3)为每一分类建立一个基于路由的过滤器;
4)最后与过滤器相配合,建立特定的路由表。
先假设一个简单的环境
流量控制器上的以太网卡(eth0)的IP地址为192.168.1.66,在其上建立一个CBQ队列。假设包的平均大小为1000字节,包间隔发送单元的大小为8字节,可接收冲突的发送最长包数目为20字节。
假如有三种类型的流量需要控制:
1)是发往主机1的,其IP地址为192.168.1.24。其流量带宽控制在8Mbit,优先级为2;
2)是发往主机2的,其IP地址为192.168.1.26。其流量带宽控制在1Mbit,优先级为1;
3)是发往子网1的,其子网号为192.168.1.0,子网掩码为255.255.255.0。流量带宽控制在1Mbit,优先级为6。
1.建立队列
一般情况下,针对一个网卡只需建立一个队列。
将一个cbq队列绑定到网络物理设备eth0上,其编号为1:0;网络物理设备eth0的实际带宽为10Mbit,包的平均大小为1000字节;包间隔发送单元的大小为8字节,最小传输包大小为字节。
tcqdiscadddeveth0roothandle1:cbqbandwidth10Mbitavpkt1000cell8mpu
2.建立分类
分类建立在队列之上。一般情况下,针对一个队列需建立一个根分类,然后再在其上建立子分类。对于分类,按其分类的编号顺序起作用,编号小的优先;一旦符合某个分类匹配规则,通过该分类发送数据包,则其后的分类不再起作用。
1)创建根分类1:1;分配带宽为10Mbit,优先级别为8。
tcclassadddeveth0parent1:0classid1:1cbqbandwidth10Mbitrate10Mbitmaxburst20allot1514prio8avpkt1000cell8weight1Mbit
该队列的最大可用带宽为10Mbit,实际分配的带宽为10Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为8,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相应于实际带宽的加权速率为1Mbit。
2)创建分类1:2,其父分类为1:1,分配带宽为8Mbit,优先级别为2。
tcclassadddeveth0parent1:1classid1:2cbqbandwidth10Mbitrate8Mbitmaxburst20allot1514prio2avpkt1000cell8weight800Kbitsplit1:0bounded
该队列的最大可用带宽为10Mbit,实际分配的带宽为8Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为1,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相应于实际带宽的加权速率为800Kbit,分类的分离点为1:0,且不可借用未使用带宽。
3)创建分类1:3,其父分类为1:1,分配带宽为1Mbit,优先级别为1。
tcclassadddeveth0parent1:1classid1:3cbqbandwidth10Mbitrate1Mbitmaxburst20allot1514prio1avpkt1000cell8weight100Kbitsplit1:0
该队列的最大可用带宽为10Mbit,实际分配的带宽为1Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为2,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相应于实际带宽的加权速率为100Kbit,分类的分离点为1:0。
4)创建分类1:4,其父分类为1:1,分配带宽为1Mbit,优先级别为6。
tcclassadddeveth0parent1:1classid1:4cbqbandwidth10Mbitrate1Mbitmaxburst20allot1514prio6avpkt1000cell8weight100Kbitsplit1:0
该队列的最大可用带宽为10Mbit,实际分配的带宽为Kbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为1,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相应于实际带宽的加权速率为100Kbit,分类的分离点为1:0。
3.建立过滤器
过滤器主要服务于分类。一般只需针对根分类提供一个过滤器,然后为每个子分类提供路由映射。
1)应用路由分类器到cbq队列的根,父分类编号为1:0;过滤协议为ip,优先级别为100,过滤器为基于路由表。
tcfilteradddeveth0parent1:0protocolipprio100route
2)建立路由映射分类1:2,1:3,1:4
tcfilteradddeveth0parent1:0protocolipprio100routeto2flowid1:2
tcfilteradddeveth0parent1:0protocolipprio100routeto3flowid1:3
tcfilteradddeveth0parent1:0protocolipprio100routeto4flowid1:4
4.建立路由
该路由是与前面所建立的路由映射一一对应。
1)发往主机192.168.1.24的数据包通过分类2转发(分类2的速率8Mbit)
iprouteadd192.168.1.24deveth0via192.168.1.66realm2
2)发往主机192.168.1.30的数据包通过分类3转发(分类3的速率1Mbit)
iprouteadd192.168.1.30deveth0via192.168.1.66realm3
3)发往子网192.168.1.0/24的数据包通过分类4转发(分类4的速率1Mbit)
iprouteadd192.168.1.0/24deveth0via192.168.1.66realm4
注:一般对于流量控制器所直接连接的网段建议使用IP主机地址流量控制限制,不要使用子网流量控制限制。如一定需要对直连子网使用子网流量控制限制,则在建立该子网的路由映射前,需将原先由系统建立的路由删除,才可完成相应步骤。
5.监视
主要包括对现有队列、分类、过滤器和路由的状况进行监视。
1)显示队列的状况
简单显示指定设备(这里为eth0)的队列状况
tcqdisclsdeveth0qdisccbq1:rate10Mbit(bounded,isolated)priono-transmit
详细显示指定设备(这里为eth0)的队列状况
tc-sqdisclsdeveth0qdisccbq1:rate10Mbit(bounded,isolated)priono-transmitSent76731bytes13232pkts(dropped0,overlimits0)borrowed0overactions0avgidle31undertime0
这里主要显示了通过该队列发送了13232个数据包,数据流量为76731个字节,丢弃的包数目为0,超过速率限制的包数目为0。
2)显示分类的状况
简单显示指定设备(这里为eth0)的分类状况
tcclasslsdeveth0classcbq1:rootrate10Mbit(bounded,isolated)priono-transmitclasscbq1:1parent1:rate10Mbitpriono-transmit#no-transmit表示优先级为8classcbq1:2parent1:1rate8Mbitprio2classcbq1:3parent1:1rate1Mbitprio1classcbq1:4parent1:1rate1Mbitprio6
详细显示指定设备(这里为eth0)的分类状况
tc-sclasslsdeveth0classcbq1:rootrate10Mbit(bounded,isolated)priono-transmitSent17725304bytes32088pkts(dropped0,overlimits0)borrowed0overactions0avgidle31undertime0classcbq1:1parent1:rate10Mbitpriono-transmitSent16627774bytes28884pkts(dropped0,overlimits0)borrowed16163overactions0avgidle587undertime0classcbq1:2parent1:1rate8Mbitprio2Sent628829bytes3130pkts(dropped0,overlimits0)borrowed0overactions0avgidle4137undertime0classcbq1:3parent1:1rate1Mbitprio1Sent0bytes0pkts(dropped0,overlimits0)borrowed0overactions0avgidle159654undertime0classcbq1:4parent1:1rate1Mbitprio6Sent5552879bytes8076pkts(dropped0,overlimits0)borrowed3797overactions0avgidle159557undertime0
这里主要显示了通过不同分类发送的数据包,数据流量,丢弃的包数目,超过速率限制的包数目等等。其中根分类(classcbq1:0)的状况应与队列的状况类似。
例如,分类classcbq1:4发送了8076个数据包,数据流量为5552879个字节,丢弃的包数目为0,超过速率限制的包数目为0。
显示过滤器的状况
tc-sfilterlsdeveth0filterparent1:protocolippref100routefilterparent1:protocolippref100routefh0xffff0002flowid1:2to2filterparent1:protocolippref100routefh0xffff0003flowid1:3to3filterparent1:protocolippref100routefh0xffff0004flowid1:4to4
这里flowid1:2代表分类classcbq1:2,to2代表通过路由2发送。
显示现有路由的状况
iproute192.168.1.66deveth0scopelink192.168.1.24via192.168.1.66deveth0realm2202.102.24.216devppp0protokernelscopelinksrc202.102.76.5192.168.1.30via192.168.1.66deveth0realm3192.168.1.0/24via192.168.1.66deveth0realm4192.168.1.0/24deveth0protokernelscopelinksrc192.168.1.66172.16.1.0/24via192.168.1.66deveth0scopelink127.0.0.0/8devloscopelinkdefaultvia202.102.24.216devppp0defaultvia192.168.1.254deveth0
如上所示,结尾包含有realm的显示行是起作用的路由过滤器。
6.维护
主要包括对队列、分类、过滤器和路由的增添、修改和删除。
增添动作一般依照"队列->分类->过滤器->路由"的顺序进行;修改动作则没有什么要求;删除则依照"路由->过滤器->分类->队列"的顺序进行。
1)队列的维护
一般对于一台流量控制器来说,出厂时针对每个以太网卡均已配置好一个队列了,通常情况下对队列无需进行增添、修改和删除动作了。
2)分类的维护
增添
增添动作通过tcclassadd命令实现,如前面所示。
修改
修改动作通过tcclasschange命令实现,如下所示:
tcclasschangedeveth0parent1:1classid1:2cbqbandwidth10Mbitrate7Mbitmaxburst20allot1514prio2avpkt1000cell8weight700Kbitsplit1:0bounded
对于bounded命令应慎用,一旦添加后就进行修改,只可通过删除后再添加来实现。
删除
删除动作只在该分类没有工作前才可进行,一旦通过该分类发送过数据,则无法删除它了。因此,需要通过shell文件方式来修改,通过重新启动来完成删除动作。
3)过滤器的维护
增添动作通过tcfilteradd命令实现,如前面所示。
修改动作通过tcfilterchange命令实现,如下所示:
tcfilterchangedeveth0parent1:0protocolipprio100routeto10flowid1:8
删除动作通过tcfilterdel命令实现,如下所示:
tcfilterdeldeveth0parent1:0protocolipprio100routeto10
4)与过滤器一一映射路由的维护
增添动作通过iprouteadd命令实现,如前面所示。
修改动作通过iproutechange命令实现,如下所示:
iproutechange192.168.1.30deveth0via192.168.1.66realm8
删除动作通过iproutedel命令实现,如下所示:
iproutedel192.168.1.30deveth0via192.168.1.66realm8iproutedel192.168.1.0/24deveth0via192.168.1.66realm4
C规则涉及到队列(QUEUE)分类器(CLASS)过滤器(FILTER),filter划分的标志位可用U32或iptables的set-mark来实现)一般是"控发"不控收linux下有两块网卡,一个eth1是外网,另一块eth0是内网.在eth0上做HTB。(注意:filter划分标志位可用u32打标功能或iptables的set-mark功能,如果用iptables来打标记的话,下行速LV在eth0处控制,但打标应在进入eth0之前进行,所以,“-ieth1";例子:
主要命令就下面三句:创建一个HTB的根
1.tcqdiscadddeveth0roothandle1:htbdefault20创建一个HTB的类,流量的限制就是在这里限制的,并设置突发.
2.tcclassadddeveth0parent1:classid1:1htbrate200kbit(速率)ceil200kbitburst20k(突发流量)
创建一个过滤规则把要限制流量的数据过滤出来,并发给上面的类来限制速度3.tcfilteradddeveth0parent1:prio1(优先级)protocolipu32matchipsport800xfffflowid1:1
sshtelnetdnsquake3ircftp控制smtp命令和带有SYN标记的数据包,都应属于这一类。为了保证上行数据流不会伤害下行流,还要把ACK数据包排在队列前面,因为下行数据的ACK必须同上行流进行竟争。
TC+IPTABLES+HTB+SFQ
1tcp/ip协议规定,每个封包,都需要有ACKNOWLEDGE讯息的回传,也就是说,传输的资料需要有一个收到资料的讯息回复,才能决定后面的传输速度,并决定是否重新传输遗失的资料,上行的带宽一部分就是用来传输这些ACK资料的.上行带宽点用大的时候,就会影响ACK资料的传送速度,并进而影响到下载速度,
2试验证明,当上传满载时,下载速度变为原来速度的40%,甚至更低,,因为上载文件(包括ftp上传,发邮件SMTP),如果较大,一个的通讯量令带宽超向包和,那么所有的数据包按照先进先出的原则进行排队和等待,这就可以解释为什么网内其中有人用ftp上载文件或发送大邮件的时候,整个网速变得很慢的原因.
解决速度之道:
1为了解决这些速度问题,对经过线路的数据进行了有规则的分流.把本来在宽带上的瓶颈转移到我们的LINUX路由器上,可以把带宽控制的比我们购买的带宽小一点.这样,我们就可以方便的用tc技术对经过的数据进行分流与控制.
我们的想像就像马路上的车道一样,有高速道,还有小车道,大车道,需要高速的synackicmpssh等走高速道,需要大量传输的ftp-data,smtp等走大车道,不能让它堵塞整条马路,各行其道.
linux下的TC(trafficcontrol)就有这样的作用,只要控制得当,一定会有明显的效果.tc和iptables结合是最好的简单运用的结合方法.
我们设置过滤器以便用iptables对数据包进行分类,因为iptables更灵活,而且还可以为每个规则设置计数器,iptables用mangle链来mark数据包,告诉了内核,数据包会有一个特定的FWMARK标记值(handlexfw)表明它应该送给那个类(classidx:x),而prio是优先值,表明那些重要数据应该优先通过那个通道,首先选择队列(选择htb),
一般系统默认的是fifo的先进先出队列,就是说包是按照先来先处理的原则,如果有一个大的数据包在前面,那么后面的包只能等前面的发完后才能接着发了,这样就算后面既使是一个小小的ack包,也要等待了,这样上传就影响了下载,就算你有很大的下载带宽也无能为力.
结构简图:1:
~~~~~~~~~~~~~~~~`~~~~~
~~~~~~~_________1:1~~~~~~~~~1:2________
|~~~|~~~~|~~~~|~~~~~|~~~~~~~~|~~~~~~~~|~~~~~~~|
1:11~~~1:12~~~~~~~~~~~~1:21~~~1:22~~~1:23~~1:24
优先顺序:1:111:121:211:221:231:24
根据上面的例子,开始脚本:
关于参数的说明:
rate:是一个类保证得到的带宽值,如果有不只一个类,请保证所有子类总和是小于或等于父类,
ceil:ceil是一个类最大能得到带宽值.
prio:是优先权的设置,数值越大,优先权越小,如果是分配剩余带宽,就是数值小的会最优先取得剩余的空闲的带宽权.
一般大数据的话,控制在50%-80%左右吧,而ceil最大建议不超过85%,以免某一个会话占用过多的带宽.
rate可按各类所需要分配:
1:11是很小而且最重要的数据包通道,当然要多分点,甚至必要时先全部占用,不过一般不会的,所以给全速.
1:12是很重要的数据道,给多点,最少给一半,但需要时可以再多一点
rate规划1:2=1:21+1:22+1:23+1:24一般总在50%-80%左右.
1:22我打算给smtp用,优先低于1:21,以防发大的附件大量占用带宽.
1:23我打算给ftp-data,和1:22一样,很可能大量上传文件,所以,rate不能给的太多,而当其他有剩时可以给大些,ceil设置大些.
1:24是无所谓通道,就是一般不是我们平时工作上需要的通道,给小点防止这些人妨碍有正常工作需要的人.
上行uplink320K,设置销低于理论值.
DEV="PPP0"
UPLINK=300
下行downlink3200K大概一半左右,以便能够得到更多的关发连接.
DOWNLINK=1500
1曾加一个根队列,没有进行分类的数据包都走这个1:24是缺省类:
tcqdiscadddev$DEVparent1:htbdefault24
1.1增加一个根队下面主干类1:速率为$UPLINKk
tccladdadddev$DEVparent1:classid1:1htbrate${UPLINK}kbitceil${UPLINK}kbitprio0
1.1.1在主干类1下建立第一叶子类,这是一个最高优先权的类,需要高优先和高速的包走这条通道,比如SYNACKICMP等.
tcclassadddev$DEVparent1:1classid1:11htbrate${$uplink}kbitceil${uplink}kbitprio1
1.1.2在主类1下建立第二叶子类,这是一个次高优先权的类,比如我们重要的CRM数据。
tcclassadddev$DEVparent1:1classid1:12htbrate${$uplink-150}kbitceil${uplink-50}kbitprio2
1.2在根类下建立次干类classid1:2,此次干类的下面全部优先权低于主干类,以防重要数据堵塞。
tcclassadddev$DEVparent1:classid1:2htbrate${$UPLINK-150]kbitprio3
tcclassadddev$DEVparent1:2classid1:21htbrate100kbitceil${$uplink-150}kbitprio4
1.2.2在次干类下建立第二叶子类,不要太高的速度,以防发大的附件大量占用带宽,便如smtp等。
tcclassadddev$DEVparent1:2classid1:22htbrate30kbitceil${uplink-160}kbitprio5
1.2.3在次干类下建立第三叶子类,不要太高的带宽,以防大量的数据堵塞网络,例如:ftp-data.
tcclassadddev$DEVparent1:2classid1:23htbrate15kbitceil${UPLINK-170}kbitprio6
1.2.4在次干类下建立第四叶子类。无所谓的数据通道,无需要太多的带宽,以防无所谓的人在阻碍正务。
tcclassadddev$DEVparent1:2classid1:24htbrate5kbitceil${UPLINK-250}kbitprio7
在每个类下面再附加上另一个队列规定,随机公平队列(SFQ),不被某个连接不停占用带宽,以保证带宽的平均公平使用。
#SFQ(stochasticfairnessqueueing随机公平队列),SFQ的关键词是“会话”(或称作流),主要针对一个TCP会话或者UDP流,流量被分成相当多数量的FIFO队列中,每个队列对应一个会话。
数据按照简单轮转的方式发送,每个会话都按顺序得到发送机会。这种方式非常公平,保证了每个会话都不会被其它会话所淹没,SFQ之所以被称为“随机”,是因为它并不是真的为每个会话创建一个队列,而是使用一个散列算法,把所有的会话映射到有限的几个队列中去。
#参数perturb是多少秒后重新配置一次散列算法,默认为10秒.
tcqdiscadddev$DEVparent1:11handle111:sfqperturb5
tcqidscadddev$DEVparent1:12handle112:sfqperturb5
tcqdiscadddev$DEVparent1:21handle121:sfqperturb10
tcqidscadddev$DEVparent1:22handle122:sfqperturb10
tcqidscadddev$DEVparent1:23handle123:sfqperturb10
tcqidscadddev$DEVparent1:24handle124:sfqperturb10
设置过滤器,handle是iptables作mark的值,让被iptables在mangle链做了mark的不同的值选择不同的通道classid,而prio是过滤器的优先级别
tcfilteradddev$DEVparent1:0protocolipprio1handle1fwclassid1:11
tcfilteradddev$DEVparent1:0protocolipprio2handle2fwclassid1:12
tcfilteradddev$DEVparent1:0protocolipprio3handle3fwclassid1:21
tcfilteradddev$DEVparent1:0protocolipprio4handle4fwclassid1:22
tcfilteradddev$DEVparent1:0protocolipprio5handle5fwclassid1:23
tcfilteradddev$DEVparent1:0protocolipprio6handle6fwclassid1:24
##################################################
##################################
下行的限制:
1把下行速率控制在大概1000-1500K(大约为带宽的50%),因为这个速度已经够用了,以便能够得到更多的并发下载连接.
tcqdiscadddev$DEVhandleffff:ingress
tcfilteradddev$DEVparentffff:protocolipprio50handle8fwpolicerate${downlink}kbitburst10kdropflowid:8
如果内部网数据流不是很疯狂的话,就不用做下载的限制了,用#符号屏蔽上面两行既可.
如果要对任何进来的数据进行限速的话,可以用下面这句.
tcfilteradddev$DEVparentffff:protocolipprio10u32matchipsrc0.0.0.0/0policerate${downlink}kbitburst10kdropflowid:1
################################
开始给数据包打标记
把出去的不同类数据包(为dport)给mark上标记1---6,让它走不同的通道.
把进来的数据包(为sport)给mark上标记8,让它受到下行的限制,以免速度太快而影响全局.
每条规则下跟着return的意思是可以通过RETURN方法避免遍历所有的规则,加快了处理速度.
设置TOS的处理:
iptables-tmangle-APREROUTING-mtos--tosMinimize-Delay-jMARK--set-mark1
iptables-tmangle-APREROUTING-mtos--tosMinimize-Delay-jRETURN
iptables-tmangle-APREROUTING-mtos--tosMinimize-Cost-jMARK--set-mark4
iptables-tmangle-APREROUTING--mtos--tosMinimize-Cost-jRETURN
iptables-tmangle-APREROUTING-mtos--tosMaximize-Throughput-jMARK--set-mark5
iptables-tmangle-APREROUTING-mtos--tosMaximize-Througput-jRETURN
##提高TCP初始连接(也就是带有SYN的数据包)的优先权是非常明智的.
iptables-tmangle-APREROUTING-ptcp-mtcp--tcp-flagsSYN,RST,ACKSYN-jMARK--set-mark1
iptables-tmangle-APREROUTING-ptcp-mtcp--tcp-flagsSYN,RST,ACKSYN-jRETURN
#想ICMP想ping有良好的反应,放在第一类。
iptables-tmangle-APREROUTING-picmp-jMARK--set-mark1
iptables-tmangle-APREROUTING-Picmp-jRETURN
#smallpackets(probablyjustACKS)长度小于64的小包通常是需要快些的,一般是用来确认tcp的连接的,让它跟快些的通道吧。
iptables-tmangle-APREROUTING-ptcp-mlength--length:64-jMARK--set-mark2
iptables-tmangle-APREROUTING-ptcp-mlength--length:64-jRETURN
#ftp放第二类,因为一般是小包,ftp-data放在第5类,因为一般是大时数据的传送。
iptables-tmangle-APREROUTING-ptcp-mtcp--dportftp-jMARK--set-mark2
iptables-tmangle-APREROUTING-ptcp-mtcp--dportftp-jRETURN
iptables-tmangle-APRETOUTING-ptcp-mtcp--dportftp-data-jMARK--set-mark5
iptables-tmangle-APREROUTING-ptcp-mtcp--dport-jRETURN
iptables-tmangle-APREROUTING-ptcp-mtcp--sportftp-jMARK--set-mark8
iptables-tmangle-APREROUTING-ptcp-mtcp--sportftp-jRETURN
iptables-tmangle-APREROUTING-ptcp-mtcp--sportftp-data-jMARK--set-mark8
iptables-tmangle-APREROUTING-ptcp-mtcp--sportftp-data-jRETURN
###提高SSH数据包的优先权:放在第1类,要知道SSH是交互式的和重要的,不容待慢:
iptables-tmangle-APREROUTING-ptcp-mtcp--dport22-jMARK--set-mark1
##SMTP邮件,放在第4类,因为有时有人发送很大的邮件,为避免它堵塞,让它跑第4道吧
iptables-tmangle-APREROUTING-ptcp-mtcp--dport25-jMARK--st-mark4
iptables-tmangle-APREROUTING-ptcp-mtcp--dport25-jRETURN
iptables-tmangle-APREROUTING-ptcp-mtcp--sport25-jMARK--set-mark8
iptables-tmangle-APREROUTING-ptcp-mtcp--sport25-jRETURN
##name-domainserver:放在第1类,这样连接带有域名的连接才能快速找到对应有的地址,提高速度
iptables-tmangle-APREROUTING-pudp-mudp--dport53-jMARK--set-mark1
iptables-tmangle-APREROUTING-Pudp-mudp--dport53-jRETURN
###HTTP:放在第3类,是最常用的,最多人用的
iptables-tmangle-APREROUTING-ptcp-mtcp--dport80-jMARK--set-mark3
iptables-tmangle-APREROUTING-ptcp-mtcp--dport80-jRETURN
iptables-tmangle-APREROUTING-ptcp-mtcp--sport80-jMARK--set-mark8
iptables-tmangle-APREROUTING-ptcp-mtcp--sport80-jRETURN
###pop邮件放在第3类:
iptables-tmangle-APREROUTING-ptcp-mtcp--dport110-jMARK--set-mark3
iptables-tmangle-APREROUTING-ptcp-mtcp--dprot110-jRETURN
iptables-tmangle-APREROUTING-ptcp-mtcp--sport110-jMARK--set-mark8
iptables-tmangle-APREROUTING-ptcp-mtcp--sport110-jRETURN
###MICSOSOFT-SQL-SERVE:放在第2类,我这里认为较重要,一定保证速度和优先的
iptables-tmangle-APREROUTING-ptcp-mtcp--dport1433-jMARK--set-mark3
iptables-tmangle-APREROUTING-ptcp-mtcp--dport1433-jRETURN
iptables-tmangle-APREROUTING-ptcp-mtcp--sport1433-jMARK--set-mark8
iptables-tmangle-APREROUTING-ptcp-mtcp--sport1433-jRETURN
iptables-tmangle-APREROUTING-ptcp-mtcp--dport443-jMARK--set-mark3
iptables-tmangle-APREROUTING-ptcpm-mtcp--dport443-jRETURN
iptables-tmangle-APREROUTING-ptcp-mtcp--sport443-jMAKR--set-mark8
iptables-tmangle-APREROUTING-Ptcp-mtcp--sport443-jRETURN
###voip用,提高,语音要保持高速才不会断续
iptables-tmangle-APREROUTING-ptcp-mtcp--dport1720-jMARK--SET-MARK1
iptables-tmangle-APREROUTING-ptcp-mtcp--dport1720-jRETURN
iptables-tmangle-APREROUTING-ptcp-mtcp--sport1720-jMAKR--set-mark8
iptables-tmangle-APREROUTING-ptcp-mtcp--sport1720-jRETURN
###VPN用作voip的,也要走高速路,才不会断续
iptables-tmangle-APREROUTING-pudp-mudp--dport7707-jMARK--set-mark1
iptables-tmangle-APREROUTING-pudp-mudp--dport7707-jRETURN
###放在第1类,因为我觉得客观存在要我心中很重要,优行:
iptables-tmangle-APREROUTING-ptcp-mtcp--dport7070-jMARK--set-mark1
##提高本地数据包的优先权:放在第1类
iptables-tmangle-AOUTPUT-ptcp-mtcp--dport22-jMARK--set-mark1
iptables-tmangle-AOUTPUT-ptcp-mtcp--dport22-jRETURN
iptables-tmangle-AOUTPUT-picmp-jMARK--set-mark1
iptables-tmangle-AOUTPUT-picmp-jRETURN
###本地smallpacket(probablyjustACKS)
iptables-tmangle-AOUTPUT-ptcp-mlength--length:64--set-mark2
iptables-tmangle-AOUTPUT-ptcp-mlength--length:64-jRETURN
#################################################
##向PRETOUTRIN中添加完mangle规则后,用这条规则结束prerouting表:也就是说前面没有打过标记的数据包就交给1:24来处理实际上是不必要的,因为1:24是缺省类,但仍然打上标记是为了保持整个设置的协调一致,而且这样,还能看到规则的数据包计数:
iptables-tmangle-APREROUTING-i$DEV-jMARK--set-mark6
###对某人限制:iptables-tmangle-IPREROUTING1-s192.168.xx.xx-jMAKR--set-mark6
###iptables-tmangle-IPREROUTING2-s192.168.xx.xx-jRETURN
###################################################
u32的应用:
tcfilteradddeveth0parent1:0protocolipprio1u32......这就是所谓的u32匹配,可以匹配数据包的任意部分.
根据源/目的地址:matchipsrc0.0.0.0/0
matchipdst1.2.3.0/24
单个IP地址可以用/32来表示
根据源/目的端口可以这样表示:matchipsport800xffff
matchipdport800xffff
根据IP协议:matchipprotocol(udptcpicmpgreipsec)
比如icmp协议是1matchipprotocol10xff
举例:
tcfilteradddev$DEVparent1:0protocolipprio1u32matchipdst4.3.2.1/32flowid10:1