流量控制

    最近在做流量控制的需求,钻研了大半个月,有些心得,特记下,方便以后查阅。

    流量控制的实现方案是netfilter + l7-filter + tc。netfilter从内核获取数据包,通过l7-filter实现不同协议数据包的不同mark,针对不同mark做不同的tc命令,实现不同协议的流控。原理如此,但在实施过程中还是有诸多困难的。

    首先l7-filter的移植,l7-filter使用C++实现,公司项目使用C实现,且项目代码比较混乱,包含C++库引入很多问题,无赖之下,将l7-filter用C改写了一遍(还好代码不多),改写基于的版本是l7-filter-userspace-0.12-beta1。如果有和我情况差不多的童鞋,一定要移植完全,否则流控根本无法做。

    l7-filter用户空间代码分两块,一块是nfq_queue获取packet,然后设置包mark;另一块是nf_conntrack跟踪流信息,将一条流相关的包放入一个buffer中。这两部分协调工作,标记流的mark,这样才能流控。比如一条流(src-->dst, dst ---> src)可能只是头几个包有明显的特征信息,这样l7-filter匹配只能匹配头一个包的信息,如果没有nf_conntrack将接下来的数据一起放到buffer里面,后面的数据就无法匹配,那么流控就无法进行。我最初也是想当然的只移植了nfq_queue部分,最后当然无法实现流控。

    mark设置完成后,流控就是tc的事情了。tc虽然很复杂,但是实现流控也就几条特定的命令,我的命令如下

下载

tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 10: htb default 256
tc class add dev eth0 parent 10: classid 10:1 htb rate 1mbit ceil 1mbit
tc class add dev eth0 parent 10:1 classid 10:10 htb rate 40kbps ceil 40kbps prio 1
tc qdisc add dev eth0 parent 10:10 handle 101: sfq perturb 10
tc filter add dev eth0 parent 10: protocol ip prio 10 handle 14 fw classid 10:10
上传

tc qdisc del dev eth1 root
tc qdisc add dev eth1 root handle 10: htb default 256
tc class add dev eth1 parent 10: classid 10:1 htb rate 1mbit ceil 1mbit
tc class add dev eth1 parent 10:1 classid 10:10 htb rate 100kbps ceil 100kbps prio 1
tc qdisc add dev eth1 parent 10:10 handle 101: sfq perturb 10
tc filter add dev eth1 parent 10: protocol ip prio 3 handle 19 fw classid  10:10
设置tc命令,一定要分清在哪个设备上,如eth0或eth1。一般的tc命令是在dev的out队列做流控。所以要限制上传,则需要在out口限制,而下载则在in口限制。

比如网络环境如下, 192.168.9.2  ---> eth0 ---> eth1 ---> 192.168.8.2。如果要对192.168.9.2做上传流控,则需要在eth1上设置上传tc的速率,而192.168.9.2的下载流控,则需要在eth0上设置下载tc的速率。

    这样总的来说,流控的框架就打好了,过来的包,通过l7-filter标记mark,然后到达tc,实现流控。比如此时使用http完全可以实现上传和下载的控制。但真要做好流控还要很长的路要走。

    比如ftp,ftp传输数据的使用子流,而子流的数据库没有任何的特征信息,l7-filter根据无法mark,那么流控也无从做起。网上说ftp的流控需要使用modprobe ip_nat_ftp,modprobe ip_conntrack_ftp,这也是l7-filter网络推荐的。但我在实际使用过程中没有任何效果,也没有任何报错信息,所以后来就放弃了,如果有哪位童鞋真的成功过,还请给点意见。最后无赖之下,ftp使用方案是根据客户端建立子流传输文件时的端口规律,实现控制。

    当然还有P2P的流,传输过程中也没有任何特征信息,l7-filter也无法标记,流控也很难。

    总的来说,l7-filter只能标记部分包的信息,所以做起流控,还是很难,不知道是不是因为我对l7-filter的理解不够深刻。

你可能感兴趣的:(tc,流控控制,l7-filter)