使用IMQ(中介队列设备)模块

前面两篇日志都是为了做使用IMQ设备的准备。因为IMQ模块并没有包括在标准核心中,所以,需要我们另行编译。而这今天的日志中,我用一个几乎是最简单的例子,来说明如何使用IMQ设备模块。其中使用到tc的相关知识,如果您还不知道该怎么做,请先回头看看前几天的日志,否则会有点不知所云的。

一、准备工作
首要的准备工作,当然是要让您的系统支持IMQ模块,有三个条件:
1、核心支持imq设备
引用
# uname -a
Linux openvz91 2.6.9-42.7AX.imq #1 Fri May 30 10:50:00 CST 2008 i686 i686 i386 GNU/Linux
# ll /lib/modules/2.6.9-42.7AX.imq/kernel/drivers/net/imq.ko
-rwxr--r--  1 root root 8340  5月 30 14:05 /lib/modules/2.6.9-42.7AX.imq/kernel/drivers/net/imq.ko

2、netfilter支持IMQ模块
引用
# ll /lib/modules/2.6.9-42.7AX.imq/kernel/net/ipv4/netfilter/ipt_IMQ.ko
-rwxr--r--  1 root root 3264  5月 30 14:05 /lib/modules/2.6.9-42.7AX.imq/kernel/net/ipv4/netfilter/ipt_IMQ.ko
# ll /lib/modules/2.6.9-42.7AX.imq/kernel/net/ipv6/netfilter/ip6t_IMQ.ko
-rwxr--r--  1 root root 3264  5月 30 14:05 /lib/modules/2.6.9-42.7AX.imq/kernel/net/ipv6/netfilter/ip6t_IMQ.ko

3、iptables支持IMQ模块
引用
# ll /lib/iptables/libip*_IMQ.so
-rwxr-xr-x  1 root root 3860  6月  2 17:04 /lib/iptables/libip6t_IMQ.so
-rwxr-xr-x  1 root root 3856  6月  2 17:04 /lib/iptables/libipt_IMQ.so

以上要求缺一不可。(如果不需要支持ipv6,可以不考虑ipv6的模块)
4、加载模块
引用
# modprobe imq numdevs=2
# modprobe ipt_IMQ
# ifconfig imq0 up
# ifconfig imq1 up

一切正常的话,会发现多了两个虚拟网卡,他们是支持tc的:
引用
# ifconfig imq0 && ifconfig imq1
imq0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
         UP RUNNING NOARP  MTU:1500  Metric:1
         RX packets:9726 errors:0 dropped:0 overruns:0 frame:0
         TX packets:9726 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:30
         RX bytes:3903679 (3.7 MiB)  TX bytes:3903679 (3.7 MiB)

imq1      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
         UP RUNNING NOARP  MTU:1500  Metric:1
         RX packets:12223 errors:0 dropped:0 overruns:0 frame:0
         TX packets:12220 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:30
         RX bytes:13794660 (13.1 MiB)  TX bytes:13791620 (13.1 MiB)
# tc qdisc show
qdisc pfifo_fast 0: dev eth0 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev imq0 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev imq1 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

二、演示脚本
IMQ模块虚拟出来的两个网卡(默认两个:imq0、imq1),可用于把队列规定qdiscs分别附加到它们上面,然后由iptables转发数据包到这两个设备,以 实现利用egress qdiscs (出口队列规定)来对流经设备的数据整形。 这样结果就是,无论出口流量,还是入口流量都可得到分类和控制的目的了。
脚本如下:
引用
#!/bin/bash
modprobe imq numdevs=2
modprobe ipt_IMQ
ifconfig imq0 up
ifconfig imq1 up

tc qdisc del dev imq0 root
tc qdisc del dev imq1 root

#IMQ 0
tc qdisc add dev imq0 root handle 1: htb default 20
tc class add dev imq0 parent 1: classid 1:1 htb rate 2mbit burst 15k
tc class add dev imq0 parent 1:1 classid 1:10 htb rate 1mbit
tc class add dev imq0 parent 1:1 classid 1:20 htb rate 1mbit
tc qdisc add dev imq0 parent 1:10 handle 10: pfifo
tc qdisc add dev imq0 parent 1:20 handle 20: sfq
tc filter add dev imq0 parent 1:0 protocol ip prio 1 u32 match ip dst 192.168.228.30 flowid 1:10

iptables -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0

#IMQ 1
tc qdisc add dev imq1 root handle 2: htb default 20
tc class add dev imq1 parent 2: classid 2:1 htb rate 4mbit burst 15k
tc class add dev imq1 parent 2:1 classid 2:10 htb rate 1mbit ceil 4mbit
tc class add dev imq1 parent 2:1 classid 2:20 htb rate 1mbit ceil 4mbit
tc qdisc add dev imq1 parent 2:10 handle 10: pfifo
tc qdisc add dev imq1 parent 2:20 handle 20: sfq
tc filter add dev imq1 parent 2:0 protocol ip prio 1 u32 match ip dst 192.168.228.30 flowid 2:10

iptables -t mangle -A POSTROUTING -o eth0 -j IMQ --todev 1

这里的机器只有一块网卡eth0,而根据tc的原理,原来只能对上传进行整形(限速)的。但通过该脚本,我们即可发现,下载时,数据流会由iptables转交给imq0,以实现入口整形的效果。(下载被分类、限速了)同样的,上传时,也会由imq1处理。
※请特别留意,不能让一个imq设备同时处理PREROUTING和POSTROUTING,否则,会出现kernel panic的。
脚本下载:

这例子比较简单,但能充分的说明问题: 把imq设备作为一个中间介质,对经其发送的数据整形以达到最终目的。 分类可通过u32或iptables MARK实现,这里就不再详细说明了。有需要的话,可参考前面的日志内容,或这里:
linux下TC控制流量文档(脚本)

使用 IMQ+HTB+iptable 统一流量控制心得




脚本:::::::::::::::

#!/bin/bash
#linux下TC控制流量文档
#脚本文件名: imq
######################################################################################### 
#原脚本"用TC+HTB(Traffic Control)解决ADSL宽带速度瓶颈技术 Ver.1.0 powered by KindGeorge" 
#部分注释参考自CU的coolend兄博客上的文章,本人只是修改成使用IMQ的TC流量整形脚本。
######################################################################################### 
#此脚本经过实验通过,更多的信息请参阅http://lartc.org 
#tc+iptables+HTB+SFQ+IMQ流量控制 
#
#1、下行2048K 意味着什么? 
#因为 1Byte=8Bit ,一个字节由8个位(bit)组成,一般用大写B表示Byte,小写b表示Bit. 
#所以 2048K=2048Kbps=2048K bits/s=256K bytes/s. 
#2、 上行512K 意味着什么? 
# 512K=512Kbps=512K bits/s=64K bytes/s. 
#就是说,个人所能独享的最大下载和上传速度,整条线路在没任何损耗,最理想的时候, 
#下载只有256K bytes/s,上传只有最大64K bytes/s的上传网速. 

#3.ADSL上传速度对下载的影响 
#(1)TCP/IP协议规定,每一封包,都需要有acknowledge讯息的回传,也就是说,传输的资料, 
#需要有一个收到资料的讯息回复,才能决定后面的传输速度,K决定是否重新传输遗失 
#的资料。上行的带宽一部分就是用泶?溥@些acknowledge(确认)資料的,当上传资料
#大的时候,就会影响acknowledge资料的传送速度,并进而影响到下载速度。这对非对称 
#数字环路也就是ADSL这种上行带宽远小于下载带宽的连接来说影响尤为明显。 
#(2)试验证明,当上传满载时,下载速度变为原来速度的40%,甚至更低.因为上载文件(包括ftp 
#上传,发邮件smtp),如果较大,一个人的通讯量已经令整条adsl变得趋向饱和,那么所有的数据 
#包只有按照先进先出的原则进行排队和等待.这就可以解释为什么网内其中有人用ftp上载文件, 
#或发送大邮件的时候,整个网速变得很慢的原因。 

#二.解决ADSL速度之道 
#1. 为解决这些速度问题,我们按照数据流和adsl的特点,对经过线路的数据进行了有规则的分流. 
#把本来在adsl modem上的瓶颈转移到我们linux路由器上,可以把带宽控制的比adsl modem上的小一点, 
#这样我们就可以方便的用tc技术对经过的数据进行分流和控制. 
#我们的想象就象马路上的车道一样,有高速道,还有小车道,大车道.需要高速的syn,ack,icmp等走 
#高速道,需要大量传输的ftp-data,smtp等走大车道,不能让它堵塞整条马路.各行其道. 
#2. linux下的TC(Traffic Control)就有这样的作用.只要控制得当,一定会有明显的效果. 
#首先选择队列,cbq和htb是不错的选择,经过实验,htb更为好用,所以以下脚本采用htb来处理 
#3. 一般系统默认的是fifo的先进先出队列,就是说数据包按照先来先处理的原则,如果有一个大的数 
#据包在前面,那么后面的包只能等前面的发完后才能接着发了,这样就算后面即使是一个小小的ack包, 
#也要等待了,这样上传就影响了下载,就算你有很大的下载带宽也无能为力. 
#HTB(Hierarchical Token Bucket, 分层的令牌桶) 
#更详细的htb参考 http://luxik.cdi.cz/~devik/qos/htb/ 
#HTB就象CBQ一样工作,但是并不靠计算闲置时间来整形。它是一个分类的令牌桶过滤器。它只有很少的参数 
#他的分层(Hierarchical)能够很好地满足这样一种情况:你有一个固定速率的链路,希望分割给多种不同的 
#用途使用,为每种用途做出带宽承诺并实现定量的带宽借用。 
#-------------------------------------------------------------------------------------------- 
#5.根据上面的例子,开始脚本 
#通常adsl用pppoe连接,的得到的是ppp0,所以公网网卡上绑了ppp0 
#关于参数的说明 
#(1)rate: 是一个类保证得到的带宽值.如果有不只一个类,请保证所有子类总和是小于或等于父类. 
#(2)ceil: ceil是一个类最大能得到的带宽值. 
#(3)prio: 是优先权的设置,数值越大,优先权越小.如果是分配剩余带宽,就是数值小的会最优先取得剩余 
#的空闲的带宽权. 
#具体每个类要分配多少rate,要根据实际使用测试得出结果. 
#一般大数据的话,控制在50%-80%左右吧,而ceil最大建议不超过85%,以免某一个会话占用过多的带宽. 
#rate可按各类所需分配, 

#一个队列规定只能处理一块网卡的流量,无法设置全局的限速。 
#IMQ就是用来解决上述两个局限的。简单地说,你可以往一个队列规定中放任何东西。
#被打了特定标记的数据包在netfilter的NF_IP_PRE_ROUTING 和NF_IP_POST_ROUTING两个钩子函数处被拦截,
#并被送到一个队列规定中,该队列规定附加到一个IMQ设备上。对数据包打标记要用到iptables的一种处理方法。
#IMQ 是中介队列设备的简称,是一个虚拟的网卡设备,与物理网卡不同的是,通过它可以进行全局的流量整形,不需要一个网卡一个网卡地限速。
#这对有多个ISP接入的情况特别方便。配合 Iptables,可以非常方便地进行上传和下载限速。

#数据包流程分析
#要明白怎么控制流量,在什么地方控制,首先得弄清楚数据包从进网卡到出网卡这个过程中,
#内核对数据包做了哪些操作,具体可以看这里的图示: http://www.docum.org/docum.org/kptd/
#下面就客户机上传下载时,数据包的流程走向进行一些分析
#下载流程
#========
#    PC 向 Internet 发起数据下载请求
#    Internet 回应相应数据
#    数据包通过 eth1 流入 Router [src: TARGET_IP, dst: INET_IP]
#    Router 重写目的地址(DNAT) [src:TARGET_IP, dst: LAN_IP]
#    <==================== 流量控制点 ==========================>
#    转发到局域网网卡 eth0
#    通过 eth0 流出 Router, 进入局域网
#    PC 接收到数据
#    显然,要控制 PC 的下载速率,在 DNAT 之后可以做到
#    小结: 下载控制, 控制外网向客户机发送数据的速率 
#         (在 DNAT之后, iptables 的 POSTROUTING 链)
#
#上传流程
#========
#    Internet 向 PC 发起数据上传请求
#    PC 回应相应数据
#    数据包通过 eth0 流入 Router [src: LAN_IP, dst: TARGET_IP]
#    <================== 流量控制点 =======================>
#    Router 重写源标地址(SNAT) [src:INET_IP, dst: TARGET_IP]
#    转发到广域网网卡 eth1
#    通过 eth1 流出 Router, 进入 Internet
#    Internet 接收到数据
#
#    显然,要控制 PC 的上传速率,在 SNAT 之前可以做到
#
#    小结: 上传控制, 控制客户机向外网发送数据的速率 
#          (在 SNAT之前, iptables 的 PREROUTING 链)

#具体思路如下:定义2个根队列,分别绑定于两个IMQ虚拟设备(imq0,imq1),其中,imq0为上行限速用,imq1为下行限速用。
#此两根队列分别作上行和下行流量整形控制,增加各队列的主干类/次干类等分类来具体规划.

#加载imq模块
modprobe imq >/dev/null 2>&1
modprobe imq number=2 >/dev/null 2>&1
modprobe ipt_IMQ >/dev/null 2>&1

#DEV0控制上行带宽设备imq0,DEV1为控制下行带宽设备imq1
DEV0="imq0" 
DEV1="imq1"

#本环境512K uplink,2M downlink的线路.一般设置为总带宽的75%--85%之间
#使得可以把ADSL猫的带宽瓶颈转移到路由器上面.形成队列在路由器..
UPLINK=450
DOWNLINK=1664
echo "==================== Packetfilter and Traffic Control 流量控制 By Ting(心雨天)====================" 
start_routing() {
#开启imq0,imq1设备
ip link set $DEV0 up
ip link set $DEV1 up

echo -n "上行队列设置开始..uplink start......" 
#1.增加一个根队列,没有进行分类的数据包都走这个1:24是缺省类:
tc qdisc add dev $DEV0 root handle 1: htb default 24 
#1.1增加一个根队下面主干类1: 速率为$UPLINK k 
tc class add dev $DEV0 parent 1: classid 1:1 htb rate ${UPLINK}kbit ceil ${UPLINK}kbit burst 10K prio 0 
#1.1.1 在主干类1下建立第一叶子类,这是一个最高优先权的类.需要高优先和高速的包走这条通道,比如SYN,ACK,ICMP等
tc class add dev $DEV0 parent 1:1 classid 1:11 htb rate $[$UPLINK]kbit prio 1 
#1.1.2 在主类1下建立第二叶子类 ,这是一个次高优先权的类。比如我们重要的crm数据. 
tc class add dev $DEV0 parent 1:1 classid 1:12 htb rate 120kbit ceil 200kbit prio 2
#1.2 在根类下建立次干类 classid 1:2 。此次干类的下面全部优先权低于主干类,以防重要数据堵塞. 
tc class add dev $DEV0 parent 1: classid 1:2 htb rate $[$UPLINK]kbit ceil ${UPLINK}kbit burst 10k prio 3
#1.2.1 在次干类下建立第一叶子类,可以跑例如http,pop等. 
tc class add dev $DEV0 parent 1:2 classid 1:21 htb rate 240kbit ceil 320kbit prio 4 
#1.2.2 在次干类下建立第二叶子类。不要太高的速度,以防发大的附件大量占用带宽,例如smtp等 
tc class add dev $DEV0 parent 1:2 classid 1:22 htb rate 160kbit ceil 240kbit prio 5 
#1.2.3 在次干类下建立第三叶子类。不要太多的带宽,以防大量的数据堵塞网络,例如ftp-data等, 
tc class add dev $DEV0 parent 1:2 classid 1:23 htb rate 120kbit ceil 180kbit prio 6 
#1.2.4 在次干类下建立第四叶子类。无所谓的数据通道,无需要太多的带宽,以防无所谓的人在阻碍正务. 
tc class add dev $DEV0 parent 1:2 classid 1:24 htb rate 80kbit ceil 240kbit prio 7 

#在每个类下面再附加上另一个队列规定,随机公平队列(SFQ),不被某个连接不停占用带宽,以保证带宽的平均公平使用: 
#SFQ(Stochastic Fairness Queueing,随机公平队列),SFQ的关键词是“会话”(或称作“流”) , 
#主要针对一个TCP会话或者UDP流。流量被分成相当多数量的FIFO队列中,每个队列对应一个会话。 
#数据按照简单轮转的方式发送, 每个会话都按顺序得到发送机会。这种方式非常公平,保证了每一 
#个会话都不会没其它会话所淹没。SFQ之所以被称为“随机”,是因为它并不是真的为每一个会话创建 
#一个队列,而是使用一个散列算法,把所有的会话映射到有限的几个队列中去。 
#只有当你的出口网卡确实已经挤满了的时候,SFQ才会起作用!否则在你的Linux机器中根本就不会有队列,SFQ也就不会起作用。
#参数perturb是多少秒后重新配置一次散列算法。默认为10 
tc qdisc add dev $DEV0 parent 1:11 handle 111: sfq perturb 5 
tc qdisc add dev $DEV0 parent 1:12 handle 112: sfq perturb 5 
tc qdisc add dev $DEV0 parent 1:21 handle 121: sfq perturb 5 
tc qdisc add dev $DEV0 parent 1:22 handle 122: sfq perturb 10 
tc qdisc add dev $DEV0 parent 1:23 handle 133: sfq perturb 10 
tc qdisc add dev $DEV0 parent 1:24 handle 124: sfq perturb 10 
echo "上行队列设置成功..uplink done.." 

echo -n "设置上行队列包过滤 Setting up uplink Filters......" 
#这里设置过滤器,让u32分类器匹配到的不同的数据选择不同的通道classid,而prio是过滤器的优先级别. 
#提示: 由于上传限速流量控制点是在 SNAT 之前,那时数据包里面还含有局域网IP的信息,
#故可以直接根据IP源信息来定位,无需再通过 iptables 做 MARK.
#开放高优先级的网内主机
tc filter add dev $DEV0 parent 1:0 protocol ip prio 1 u32 match ip src 192.168.1.179 classid 1:11 
#开放对实时性要求高的SSH服务
tc filter add dev $DEV0 parent 1:0 protocol ip prio 1 u32 match ip src 192.168.1.0/24 match ip dport 22 0xffff classid 1:11
#TOS Minimum Delay
tc filter add dev $DEV0 parent 1:0 protocol ip prio 2 u32 match ip tos 0x10 0xff classid 1:12
#小于64k字节的ACK包
tc filter add dev $DEV0 parent 1:0 protocol ip prio 2 u32 match ip protocol 6 0xff match u8 0x10 0xff at nexthdr+13 match u16 0x0000 0xffc0 at 2 classid 1:12 
#ICMP packets
tc filter add dev $DEV0 parent 1:0 protocol ip prio 2 u32 match ip protocol 1 0xff flowid 1:12

#区配一网段内所有主机,共享式带宽限制。
tc filter add dev $DEV0 parent 1:0 protocol ip prio 4 u32 match ip src 192.168.1.0/24 classid 1:21
echo "设置上行队列过滤器成功..done...."

#===========================================================================================
echo -n "下行队列设置开始.downlink start......" 
#1.增加一个根队列绑定到dev接口,没有进行分类的数据包都走这个2:24是缺省类: 
tc qdisc add dev $DEV1 root handle 2: htb default 24 
#1.1增加一个根队下面主干类1: 速率为$DOWNLOAD k 
tc class add dev $DEV1 parent 2: classid 2:1 htb rate ${DOWNLINK}kbit ceil $[$DOWNLINK]kbit burst 10K prio 0 
#1.1.1 在主干类1下建立第一叶子类,这是一个最高优先权的类.需要高优先和高速的包走这条通道,比如SYN,ACK,ICMP等 
tc class add dev $DEV1 parent 2:1 classid 2:11 htb rate $[$DOWNLINK]kbit ceil $[$DOWNLINK]kbit prio 1 
#1.1.2 在主类1下建立第二叶子类 ,这是一个次高优先权的类。比如我们重要的crm数据. 
tc class add dev $DEV1 parent 2:1 classid 2:12 htb rate 400kbit ceil 480kbit prio 2
#1.2 在根类下建立次干类 classid 1:2 。此次干类的下面全部优先权低于主干类,以防重要数据堵塞. 
tc class add dev $DEV1 parent 2: classid 2:2 htb rate $[$DOWNLINK]kbit ceil $[$DOWNLINK]kbit prio 3
#1.2.1 在次干类下建立第一叶子类,可以跑例如http,pop等. 
tc class add dev $DEV1 parent 2:2 classid 2:21 htb rate 800kbit ceil 1024kbit burst 10k prio 4 
#1.2.2 在次干类下建立第二叶子类。不要太高的速度,以防发大的附件大量占用带宽,例如smtp等 
tc class add dev $DEV1 parent 2:2 classid 2:22 htb rate 320kbit ceil 480kbit prio 5 
#1.2.3 在次干类下建立第三叶子类。不要太多的带宽,以防大量的数据堵塞网络,例如ftp-data等, 
tc class add dev $DEV1 parent 2:2 classid 2:23 htb rate 560kbit ceil 1024kbit prio 6 
#1.2.4 在次干类下建立第四叶子类。无所谓的数据通道,无需要太多的带宽,以防无所谓的人在阻碍正务. 
tc class add dev $DEV1 parent 2:2 classid 2:24 htb rate 160kbit ceil 240kbit prio 7 

tc qdisc add dev $DEV1 parent 2:11 handle 211: sfq perturb 5 
tc qdisc add dev $DEV1 parent 2:12 handle 212: sfq perturb 5 
tc qdisc add dev $DEV1 parent 2:21 handle 221: sfq perturb 10
tc qdisc add dev $DEV1 parent 2:22 handle 222: sfq perturb 10 
tc qdisc add dev $DEV1 parent 2:23 handle 233: sfq perturb 10 
tc qdisc add dev $DEV1 parent 2:24 handle 224: sfq perturb 10 
echo "下行队列设置成功.. downlink done...." 

echo -n "设置下行队列包过滤 Setting up Filters......" 
#这里设置过滤器,让u32分类器匹配到的不同的数据选择不同的通道classid,而prio是过滤器的优先级别. 
#提示: 由于下载限速流量控制点是在 DNAT 之后,转发到eth0准备到局域网之前,那时数据包里面还含有局域网IP的信息,
#故可以直接根据IP目标信息来定位.
tc filter add dev $DEV1 parent 2:0 protocol ip prio 1 u32 match ip dst 192.168.1.179 classid 2:11 
tc filter add dev $DEV1 parent 2:0 protocol ip prio 1 u32 match ip dst 192.168.1.0/24 match ip sport 22 0xffff classid 2:11
tc filter add dev $DEV1 parent 2:0 protocol ip prio 1 u32 match ip dst 192.168.1.0/24 match ip sport 53 0xffff classid 2:12
tc filter add dev $DEV1 parent 2:0 protocol ip prio 2 u32 match ip tos 0x10 0xff classid 2:12
tc filter add dev $DEV1 parent 2:0 protocol ip prio 2 u32 match ip protocol 6 0xff match u8 0x10 0xff at nexthdr+13 match u16 0x0000 0xffc0 at 2 classid 2:12 
tc filter add dev $DEV1 parent 2:0 protocol ip prio 3 u32 match ip protocol 1 0xff flowid 2:21
#对Web、邮件收发以及网内主机全局进行共享式带宽限制
tc filter add dev $DEV1 parent 2:0 protocol ip prio 3 u32 match ip dst 192.168.1.0/24 match ip sport 80 0xffff classid 2:21
tc filter add dev $DEV1 parent 2:0 protocol ip prio 3 u32 match ip dst 192.168.1.0/24 match ip sport 110 0xffff classid 2:22
tc filter add dev $DEV1 parent 2:0 protocol ip prio 3 u32 match ip dst 192.168.1.0/24 match ip sport 25 0xffff classid 2:22
tc filter add dev $DEV1 parent 2:0 protocol ip prio 4 u32 match ip dst 192.168.1.0/24 classid 2:23
echo "设置下行队列过滤器成功..done...." 

# add the single host in netwook into the filter rule (uplink and downlink)对单机带宽限速!
# 针对网内单机严格限制一定范围内的带宽,能有效控制带宽的使用及分配公平性。须把上面的共享式带宽限制注释掉。
#IPs=0
#Cid=0
#total=254
#while [ $IPs -lt $total ]
#do
#IPs=`expr $IPs + 1`
#Cid=`expr $Cid + 1`
#tc class add dev $DEV0 parent 1:2 classid 1:3$Cid htb rate 80kbit ceil 160kbit prio 6
#tc class add dev $DEV1 parent 2:2 classid 2:3$Cid htb rate 240kbit ceil 560kbit prio 6
#tc filter add dev $DEV0 parent 1:0 protocol ip prio 5 u32 match ip src 192.168.1.$IPs classid 1:3$Cid
#tc filter add dev $DEV1 parent 2:0 protocol ip prio 5 u32 match ip dst 192.168.1.$IPs classid 2:3$Cid
#done

}

#7. 开始给数据包打标记,往PREROUTING链中添加mangle规则:
start_mangle() { 
echo -n "开始给数据包打标记......start mangle mark......" 
#下面是封P2P,要使用须打上l7proto补丁.
#iptables -t mangle -A POSTROUTING -s 192.168.1.179 -m layer7 --l7proto bittorrent -j ACCEPT
#iptables -t mangle -A POSTROUTING -d 192.168.1.179 -m layer7 --l7proto bittorrent -j ACCEPT
#iptables -t mangle -A POSTROUTING -m layer7 --l7proto bittorrent -j DROP
#iptables -t mangle -A POSTROUTING -m layer7 --l7proto xunlei -j DROP
#iptables -t mangle -A POSTROUTING -m layer7 --l7proto imap -j DROP

# 上传限速, 入口 eth0,为应对电信封共享更改了TTL。
iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-set 129
iptables -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0
# 下载限速,出口 eth0
iptables -t mangle -A POSTROUTING -o eth0 -j IMQ --todev 1
echo "标记完毕! mangle mark done!" 


#----------------------------------------------------------------------------------------------------- 
#8.取消mangle标记用的自定义函数 
stop_mangle() { 
echo -n "stop mangle table......" 
(iptables -t mangle -F && echo "ok." ) || echo "error." 

#9.取消队列用的 
stop_routing() { 
echo -n "(删除所有队列......)" 
( tc qdisc del dev $DEV0 root && echo "ok.uplink del success!" ) || echo "error." 
( tc qdisc del dev $DEV1 root && echo "ok.downlink del success!" ) || echo "error." 
ip link set $DEV0 down
ip link set $DEV1 down
echo "ip link set imq0 imq1 down....OK!."

#10.显示状态 
status() { 
echo "1.show qdisc $DEV0 (显示上行队列):----------------------------------------------" 
tc -s qdisc show dev $DEV0 
echo "2.show class $DEV0 (显示上行分类):----------------------------------------------" 
tc class show dev $DEV0
echo "3. tc -s class show dev $DEV0 (显示上行队列和分类流量详细信息):------------------" 
tc -s class show dev $DEV0 
echo "说明:设置总队列上行带宽 $UPLINK k." 
echo "======list the uplink rules hit status in dev imq0.======"
tc -s filter show dev $DEV0

echo "1.show qdisc $DEV1 (显示下行队列):----------------------------------------------" 
tc -s qdisc show dev $DEV1 
echo "2.show class $DEV1 (显示下行分类):----------------------------------------------" 
tc class show dev $DEV1 
echo "3. tc -s class show dev $DEV1 (显示下行队列和分类流量详细信息):------------------" 
tc -s class show dev $DEV1 
echo "说明:设置总队列下行带宽 $DOWNLINK k." 
echo "======list the downlink rules hit status in dev imq1.======"
tc -s filter show dev $DEV1

echo "1. classid 1:11 ssh、dns、和带有SYN标记的数据包。这是最高优先权的类包并最先类 " 
echo "2. classid 1:12 重要数据,这是较高优先权的类。" 
echo "3. classid 1:21 web,pop 服务 " 
echo "4. classid 1:22 smtp服务 " 
echo "5. classid 1:23 ftp-data服务 " 
echo "6. classid 1:24 其他服务 " 

#11.显示帮助 
usage() { 
echo "使用方法(usage): `basename $0` [start | stop | restart | status | mangle ]" 
echo "参数作用:" 
echo "start 开始流量控制" 
echo "stop 停止流量控制" 
echo "restart 重启流量控制" 
echo "status 显示队列流量" 
echo "mangle 显示mangle标记" 

#---------------------------------------------------------------------------------------------- 
#12. 下面是脚本运行参数的选择的控制 

kernel=`eval kernelversion` 
case "$kernel" in 
2.2) 
echo " (!) Error: won't do anything with 2.2.x 不支持内核2.2.x" 
exit 1 
;; 
2.4|2.6) 
case "$1" in 
start) 
( start_routing && start_mangle && echo "开始流量控制! TC started!" ) || echo "error." 
exit 0 
;; 
stop) 
( stop_routing && stop_mangle && echo "停止流量控制! TC stopped!" ) || echo "error." 
exit 0 
;; 
restart) 
stop_routing 
stop_mangle 
start_routing 
start_mangle 
echo "流量控制规则重新装载!" 
;; 
status) 
status 
;; 
mangle) 
echo "iptables -t mangle -nvL (显示目前mangle表表标记详细):" 
iptables -t mangle -vnL 
;; 
*) usage 
exit 1 
;; 
esac 
;; 
*) 
echo " (!) Error: Unknown kernel version. ?check it !" 
exit 1 
;; 
esac 
echo "script done!" 
exit 1

#三.结束语 
#1. 需要U32分类器支持,请到相关网站下载有关补丁,重新编译! 
#此脚本是参考http://kindgeorge.at.3322.org和<Linux的高级路由和流量控制HOWTO>修改而成!
#经过测试并得出的总结结果,在此感谢所有作出贡献的人. 特别是Moddyboot和Kindgeorge!
#2. iptables,在http://www.iptables.org/ .iptables v1.3.6 和tc是DEBIAN 3.1r4下自带的版本. 
#3. 此脚本已经在Debian 3.1r4,内核升级为2.6.15上,内网约40台频繁上网机器的环境下运行数月,事实证明良好. 
#4. 如果ADSL带宽不同或有变,调节相关rate参数及ceil参数即可. 
#5. 需IMQ支持,要重新编译内核.关于补丁和更多的文档请参阅imq网站http://www.linuximq.net/ 
#6. 欢迎转载,但请保留原出处 powered by KindGeorge...Moddfied by ting...
#7. 除了ADSL外,还可以进行其他宽带的控制. 
#8. 为达到更好的效果,结合commlimit来控制Tcp并发数限制,对80,8080端口进行限制将达到更佳的网络环境!
#   Web端口并发数限制:iptables -A FORWARD -p tcp --syn --dport 80 -m connlimit --connlimit-above 30 -j DROP
#   8080端口并发数限制:iptables -A FORWARD -p tcp --syn --dport 8080 -m connlimit --connlimit-above 20 -j DROP 
#   全局并发数限制,可应对bt下载: iptables -A FORWARD -p tcp -m connlimit --connlimit-above 60 -j DROP
#9.使用方法: 整篇文档拷贝后,chmod +x imq,
#执行脚本: ./imq start (或其他参数start | stop | restart | status | mangle )即可 
#如果想每次在ppp启动时就启动,则在/etc/ppp/ip-up.local 文件里面加上一句: /路径/imq restart 
#end---------------------------------------------------------------------------------------

/**********************************************************************************************************************

#原脚本"用TC+HTB(Traffic Control)解决ADSL宽带速度瓶颈技术 Ver.1.0 powered by KindGeorge" 
#部分注释参考自CU的coolend兄博客上的文章,本人只是修改成使用IMQ的TC流量整形脚本。

我是参考KindGeorge的结合IMQ来控制上行下行流量的结语,才由他的脚本更改。IMQ并没有特别的使用方法。

IMQ在应对多线路接入,在上行下行流量控制这两方面实现并简化了本来复杂的操作。


***********************************************************************************************************************/


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值