TC流控配置及使用

整理iptables mark 使用命令

Posted by JKJUN on February 27, 2018

##linux下使用iptables和tc限制速度

linux下使用iptables和tc限制速度的方法,记录一下。

假设本地搭建了PPTPD服务,又或者有多个网卡,需要对其中一些接口做限速处理的情况,非常有用. 本文基于CentOS 6.4 64bit。 详细参考@zhukun __

###1、初始配置

yum install /sbin/tc
 
vim /etc/sysctl.conf
修改net.ipv4.ip_forward = 1
sysctl -p
 
#清除原来的mangle表规则
iptables -t mangle -F
 
#加载sch_htb模块
modprobe sch_htb
echo "modprobe sch_htb" >> /etc/rc.local

###2、TC限速设置

  • 假设现在有两块网卡
    • eth0:xx.xx.xx.xx(外网上网地址)
    • eth1:192.168.2.9(内网网关地址)

####下载限速配置 因为tc框架对数据包的控制是:控发不控收。因此下载限速要在eth1上面做,判断数据包的目的地址来做限制。tc包括三部分:队列、类、过滤器。我使用了htb方式去限制速度,也可以使用cbq,但cbq配置比较复杂一点,而且据说性能没htb好。

#删除原来的tc规则队列
/sbin/tc qdisc del dev eth1 root
#添加tc规则队列
/sbin/tc qdisc add dev eth1 root handle 10: htb default 256
#生成根类
/sbin/tc class add dev eth1 parent 10: classid 10:1 htb rate 100mbit ceil 100mbit
#支类列表用于限制速度
#这里的rate指的是保证带宽,ceil是最大带宽。
/sbin/tc class add dev eth1 parent 10:1 classid 10:10 htb rate 400kbps ceil 400kbps prio 1
 
#添加支类规则队列
#采用sfq伪随机队列,并且10秒重置一次散列函数。
/sbin/tc qdisc add dev eth1 parent 10:10 handle 101: sfq perturb 10
 
#建立网络包过滤器,设置fw。
/sbin/tc filter add dev eth1 parent 10: protocol ip prio 10 handle 1 fw classid 10:10
  • 分类数据包到对应的队列里,目前我使用两种方法
    • 在iptables里面设定mark值,与上面的handle值对应
    • 在iptables里设定set-class 为叶子节点1:10
  1. 标记mark值
    iptables -t mangle -A POSTROUTING -d 192.168.2.130 -j MARK --set-mark 1
    iptables -t mangle -A POSTROUTING -d 192.168.2.130 -j RETURN
    
  2. 标记classid
    iptables -t mangle -A POSTROUTING -d 192.168.2.130 -j CLASSIFY --set-class 1:10
    iptables -t mangle -A POSTROUTING -d 192.168.2.130 -j RETURN
    

通过上面的代码就可以限制172.16.44.130这台机子的下载速度到400kbps。

需要注意的是:

1,172.16.44.130也可以写成网段的形式,例如172.16.44.0/24

2,这里的kbps实际上就是KB/S(每秒千字节),另一个单位是kbit,这个才是每秒千比特。

####上传限速配置 上传限速的原理其实跟下载的差不多,只不过限制的网卡不同,要在eth0上过滤来源地址去限制。

##下面是我做qos的脚本代码,贴上来,有需要的可以参考一下

  #!/usr/bin/env bash

# qos test script

addtc() {
    DEV=eth1
    #加载sch_htb模块
    modprobe sch_htb
    # 创建调度器
    #添加tc规则队列
    tc qdisc add dev $DEV root handle 1: htb default 256

    # class 1:1, which is direct descendant of root(1:),
    # this class gets assigned also an HTB qdisc, and then it sets a max rate of 6mbits,
    # whith a burst of 15k
    # sc: 限制带宽
    # ul:
    #生成根类
    tc class add dev $DEV parent 1: classid 1:1 htb rate 100kbps ceil 2000kbps

    #tc class add dev $DEV parent 1: classid 1:10 htb rate 10kbps burst 1k
    #支类列表用于限制速度
    #这里的rate指的是保证带宽,ceil是最大带宽。
    tc class add dev $DEV parent 1:1 classid 1:10 htb rate 50kbps ceil 200kbps prio 1
    #添加支类规则队列
    #采用sfq伪随机队列,并且10秒重置一次散列函数。
    tc qdisc add dev $DEV parent 10:10 handle 101: sfq perturb 10
    #tc qdisc add dev $DEV parent 1:2  handle 2:  sfq perturb 10
    #tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10

}
deltc() {
    tc qdisc del dev eth1 root
    #iptables -t mangle -F
}
init() {
    iptables -t mangle -N QOS
    iptables -t mangle -N QOS_LAN
    iptables -t mangle -I POSTROUTING -j QOS
    iptables -t mangle -I QOS -j NDPI
    iptables -t mangle -A QOS -o eth1 -j QOS_LAN
}

qos_exist_ndpi() {
    exist=`iptables -t mangle -S QOS | grep NDPI | wc -l`
    if [ "0" == $exist ]; then
        return 1
    else
        return 0
    fi
}

add() {
    qos_exist_ndpi || iptables -t mangle -I QOS -j NDPI
    iptables -t mangle -A QOS_LAN -m ndpi --protos "$1" -j CLASSIFY --set-class 1:10
    iptables -t mangle -A QOS_LAN -m ndpi --protos "$1" -j RETURN
}

clean() {
    iptables -t mangle -F QOS_LAN       2> /dev/null
    iptables -t mangle -D QOS -j NDPI   2> /dev/null
    iptables -t mangle -F               2> /dev/null
    iptables -F FORWARD                 2> /dev/null
}

show() {
    iptables -t mangle -S QOS -v
    iptables -t mangle -S QOS_LAN -v
    iptables -S FORWARD -v
}
ban() {
    iptables -I FORWARD -m ndpi --protos "$1" -j DROP
}

case "$1" in
    init)init     ;;
    tc)  addtc    ;;
    deltc) deltc  ;;
    add) add "$2" ;;
    ban) ban "$2" ;;
    del) del "$2" ;;
    clean) clean  ;;
    show)  show   ;;
    *) echo "no thing to do" ;;
esac