zoukankan      html  css  js  c++  java
  • openwrt多wan限上下行速脚本,基于qosv4,imq模块替换成ifb模块[ZT]

    转自: http://www.right.com.cn/forum/thread-169414-1-1.html ,本人未经测试,转来自已备用

    由于树莓派2装openwrt官方没有imq模块, 好像说ifb比较有优势,优势对于普通玩家来说,没用~.
    百度翻遍各种文档,总算凑合起来可以用.有问题再提出来讨论,欢迎测试.
    有些参数是写死在脚本里面,因为暂时设了htb的带宽不可借用的,所以大小好像没关系.
    all_wan_down_speed=1500
    all_wan_up_speed=50

    脚本如下:
    #!/bin/sh
    #copyright by zhoutao0712 modify lynatgz  @2015.07.12

    . /lib/functions.sh

    #装载核心模块
    load_modules(){
        #insmod imq numdevs=2
        #ifb模块 代替 imq模块
        insmod ifb
        insmod cls_fw
        insmod sch_hfsc
        insmod sch_sfq
        insmod sch_red
        insmod sch_htb
        insmod sch_prio
        insmod xt_multiport
        insmod xt_CONNMARK
        insmod xt_length
        insmod xt_hashlimit
        insmod cls_u32
        insmod xt_connlimit
        insmod xt_connbytes
        echo "" > ${qosv4_tmp_pach}/insmod
    }

    bak(){
    <<!
    #必需在函数里面才能多行注释!
            ##sfq 随机公平队列,参数perturb 12秒后重新配置一次散列算法(默认为10). quantum 每轮当前的class能发送的字节数
            #队列 hadnle 编号为 $RULE_ID$IP4 (后面没有用到这条队列!)
            #tc qdisc add dev ifb0 parent 1RULE_ID$IP4 handle $RULE_ID$IP4 sfq perturb 12 quantum 2000
    !
    }

    qos_stop(){
        #for iface in $(tc qdisc show | grep htb | awk '{print $5}'); do
        for iface in $(tc qdisc show | awk '{print $5}'); do
            #ifconfig的所有网卡
            tc qdisc del dev "$iface" root
        done

        #删链重建.NEW meaning that the packet has started a new connection, or otherwise associated with a connection which has not seen packets in both directions
        iptables -t mangle -D PREROUTING -m state --state NEW -j NEWLMT

        #删除旧规则
        iptables -t mangle -D NEWLMT -i pppoe+ -j RETURN
        iptables -D FORWARD -o pppoe+ -p udp -j UDPLMT
        iptables -t mangle -D FORWARD -i pppoe+ -j QOSDOWN
        iptables -t mangle -D POSTROUTING -o pppoe+ -j QOSUP

        #清空链规则
        iptables -t mangle -F QOSDOWN
        iptables -t mangle -F QOSUP
        iptables -t mangle -F NEWLMT
        iptables -F UDPLMT
        #iptables -t mangle -F PUNISH0

        #-X --delete-chain 删除链
        iptables -t mangle -X QOSDOWN
        iptables -t mangle -X QOSUP
        iptables -t mangle -X NEWLMT
        iptables -X UDPLMT
        #iptables -t mangle -X PUNISH0

        [ -f ${qosv4_tmp_pach}/connlimit ] && {
            sh ${qosv4_tmp_pach}/connlimit
            echo "" > ${qosv4_tmp_pach}/connlimit
        }
        echo "QOS DELETE DONE";echo ""
    }

    #创建QOS专用链
    qos_start(){
        #删除各种链
        qos_stop

        #新建链NEWLMT, 用于新建连接控制  -N --new-chain
        iptables -t mangle -N NEWLMT

        #PREROUTING下一规则NEWLMT, 当匹配到新建链接全部入NEWLMT链规则
        iptables -t mangle -I PREROUTING -m state --state NEW -j NEWLMT

        #放行本地地址访问局域网
        iptables -t mangle -A NEWLMT -s $(uci get network.lan.ipaddr)/24 -d $(uci get network.lan.ipaddr)/24 -j RETURN
        #放行upd端口53,67,68,1900 53端口为DNS端口,67和68是DHCP端口,
        iptables -t mangle -A NEWLMT -p udp -m multiport --dports 53,67,68,1900 -j RETURN
        #udp链接数超过100的包丢弃
        iptables -t mangle -A NEWLMT -p udp -m connlimit --connlimit-above 120 -j DROP
        #点对点的tcp握手包链接数超过200的包丢弃, 握手包SYN、ACK、FIN.connlimit: Allows you to restrict the number of parallel connections  to  a  server  per  client  IP address
        iptables -t mangle -A NEWLMT -p tcp --syn -m connlimit --connlimit-above 200 -j DROP
        #为每个源IP(收与发)建立匹配项, 产生速度25/s, 放行匹配的数据包, 超过速率的就可能丢弃了
        iptables -t mangle -A NEWLMT -m hashlimit --hashlimit-name newlmt --hashlimit-mode srcip --hashlimit 40 -j RETURN
        #限制tcp 80端口的请求包低于25/秒
        iptables -t mangle -A NEWLMT -p tcp --dport 80 -m limit --limit 40 -j RETURN
        #其他全部丢弃
        iptables -t mangle -A NEWLMT -j DROP
        #NEWLMT -I 插入首规则: 当网卡N收到数据, 回原路PREROUTING. 对端发起连接时,放行
        iptables -t mangle -I NEWLMT -i pppoe+ -j RETURN

        #新建链 UDPLMT, 用于控制udp, 不指定则入filter表
        iptables -N UDPLMT
        #为每个源IP(收与发)建立匹配项, 产生速度120/s, 放行匹配的数据包, 超过速率的就可能丢弃了
        iptables -A UDPLMT -m hashlimit --hashlimit-name udplmt --hashlimit-mode srcip --hashlimit 120 -j RETURN
        #限制udp 30, 8000端口的请求包低于30/秒
        iptables -A UDPLMT -p udp -m multiport --dports 53,8000 -m limit --limit 30 -j RETURN
        #其他全部丢弃
        iptables -A UDPLMT -j DROP
        #FORWARD -I 插入首规则:当网卡N发送数据udp, 入UDPLMT,
        iptables -I FORWARD -o pppoe+ -p udp -j UDPLMT

        iptables -t mangle -N QOSDOWN
        iptables -t mangle -N QOSUP
        #FORWARD -I 插入首规则:当网卡N收到数据, 入QOSDOWN    #INPUT 可能是访问路由的, 不限制路由自身下行
        iptables -t mangle -I FORWARD -i pppoe+ -j QOSDOWN
        #FORWARD -I 插入首规则:当网卡N发送数据, 入QOSUP
        iptables -t mangle -I POSTROUTING -o pppoe+ -j QOSUP

    <<!
        #小包不进入后面的打标记,小包不进入tc限速
    !
        #放下行upd外部端口为53的, 53端口为DNS端口
        iptables -t mangle -A QOSDOWN -p udp --sport 53 -j RETURN
        #放上行upd外部端口为53的,53端口为DNS端口
        iptables -t mangle -A QOSUP -p udp --dport 53 -j RETURN
        #放下行tcp 不是初始包, 长度0:100字节的
        iptables -t mangle -A QOSDOWN -p tcp ! --syn -m length --length :100 -j RETURN
        #放上行tcp 不是初始包, 长度0:80字节的
        iptables -t mangle -A QOSUP -p tcp ! --syn -m length --length :80 -j RETURN

        #以下3条规则是一起生效的
        # iptables -t mangle -A PREROUTING -p tcp -m connmark ! --mark 80 -m web --path ".exe$ .rar$ .iso$ .zip$ .rm$ .rmvb$ .wma$ .avi$" -j CONNMARK --set-mark 80
        #connmark连接打标记, mask为80的, 设置连接mark为80
        #iptables -t mangle -A QOSDOWN -m connmark --mark 80 -j MARK --set-mark 80
        #iptables -t mangle -A QOSUP -m connmark --mark 80 -j MARK --set-mark 80

    <<!
        #大包作特殊标记
    !
        #QOSDOWN tcp包长度0:768字节的,下一规则为MARK,标记为255(配合TC做QOS流量限制或应用策略路由)
        #iptables -t mangle -A QOSDOWN -p tcp -m length --length :768 -j MARK --set-mark 255
        #QOSUP tcp包长度0:512字节的,下一规则为MARK,标记为255(配合TC做QOS流量限制或应用策略路由)
        #iptables -t mangle -A QOSUP -p tcp -m length --length :512 -j MARK --set-mark 255

        ##CONNBYTES模块
        ##tcp 80,443,25,110 QOSDOWN下一规则为CONNBYTES, 可能这一写法是错误的
        #iptables -t mangle -A QOSDOWN -p tcp -m multiport --sports 80,443,25,110 -j CONNBYTES
        #iptables -t mangle -A QOSUP -p tcp -m multiport --dports 80,443,25,110 -j CONNBYTES

        ##--connbytes 1:200 match packets from a connection whose packets/bytes/average packet size is more than FROM and less than TO bytes/packets
        ##QOSUP tcp 80,443,25,110 端口 双向的数据达到 0:51200字节, 下一规则为MARK,标记为254
        #iptables -t mangle -A QOSUP -p tcp -m multiport --sports 80,443,25,110  -m connbytes  --connbytes :51200 --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 254
        ##QOSDOWN tcp 80,443,25,110 端口 双向的数据达到 0:102400字节, 下一规则为MARK,标记为254
        #iptables -t mangle -A QOSDOWN -p tcp -m multiport --sports 80,443,25,110 -m connbytes  --connbytes :102400 --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 254

        #http://segmentfault.com/a/1190000000666869
        #http://blog.chinaunix.net/uid-7396260-id-3294466.html
        #http://it.chinawin.net/internet/article-24b44.html
        #http://www.cnblogs.com/endsock/archive/2011/12/09/2281519.html
        #tc cl ad dev ifb0 缩写写法.

        #ifb0-下行控制,  ifb1-上行控制
        ifconfig ifb1 up

        #下载速度控制,限制内网网卡发送给用户的数据包速度

        #1. htb可以很容易地保证每个类别的带宽, 虽然它也允许特定的类可以突破带宽上限, 占用别的类的带宽
        #根队列规则, 把htb队列绑定到 ifb0 , 并指定了一个 handle 句柄 1: (效果1:0) 用于标识它下面的子类, 没标识的分配默认子类 9999 (默认值只是设置而已, 可以不用)
        tc qdisc add dev eth0 root handle 1: htb default 999
        tc qdisc add dev ifb1 root handle 1: htb default 999

        #2. 为队列建一个主干类, htb的主干类不能互相借用带宽, 但是一个父类的所有子类之间可以借用带宽, parent 1: 是刚才建立的 handle 1: , 父类为1:0 , 分类号 1:1
        #ceil 不配则值与rate一样, prio 0 burst 1599b cburst 1599b
        tc class add dev eth0 parent 1: classid 1:1 htb rate $((all_wan_down_speed))kbps
        tc class add dev ifb1 parent 1: classid 1:1 htb rate $((all_wan_up_speed))kbps

        #每个IP限速, 下行 & 上行
        config_foreach   get_qos_ip_limit   qos_ip

        #tc class add dev ifb0 parent 1:1 classid 1:a254 htb rate $((GLOBAL_DOWN/10))kbps ceil $((GLOBAL_DOWN*7/10))kbps quantum 8000 prio 3
        ##sfq 随机公平队列,参数perturb 12秒后重新配置一次散列算法(默认为10). quantum 每轮当前的class能发送的字节数
        #tc qdisc add dev ifb0 parent 1:a254 handle a254 sfq perturb 12 quantum 1500
        #tc filter add dev ifb0 parent 1: protocol ip prio 10 handle 254 fw flowid 1:a254
    }

    wan_list=$(ifconfig | grep "oint-to-Point Protocol" | cut -d" " -f1)
    #所有普通IP单独限速 (暂不调用)
    qos_ip_limit() {
        #传入参数: 1-limit_ip   2-DOWNLOADR 保证    3-DOWNLOADC 最大  
        #               4-UPLOADR 保证   5-UPLOADC 最大    6-ip_prio        7-tcplimit  8-udplimit
        #保存IP第4个数字
        start=$(echo $1|cut -d '-' -f1|cut -d '.' -f4)
        end=$(echo $1|cut -d '-' -f2|cut -d '.' -f4)
        #NET 保存前3个数字 192.168.1
        NET=$(echo $1|cut -d '.' -f1-3)
        #记录在处理第几条规则
        RULE_ID=$((RULE_ID+1))
        echo "QOS_IP_LIMIT  limit_ip=$1  DOWNLOADR=$2   DOWNLOADC=$3  UPLOADR=$4 UPLOADC=$5 ip_prio=$6  tcplimit=$7  udplimit=$8"
        while [ $start -le $end ]
        do
            #不足2位前面补0
            IP4=$(printf "%02x" $start)
            echo "$NET.start  end=$end  RULE_ID=$RULE_ID IP4=$IP4"

            #QOSDOWN 标记tc需要限速的包, 标记为255
            iptables -t mangle -A QOSDOWN -d $NET.$start -j MARK --set-mark $start
            #QOSUP 标记tc需要限速的包, 标记为 1255
            iptables -t mangle -A QOSUP -s $NET.$start -j MARK --set-mark $((start+1000))
            ##u32过滤器匹配ip目标地址, u32 match ip dst 10.0.0.229/32  ##防火墙标记过滤器 handle 254 fw
            #eth0 叶分类,parent 1:1能借用带宽, 不想借用,写成parent 1:, 改用主干类, 主干ceil不启作用
            tc class add dev eth0 parent 1: classid 1RULE_ID$IP4 htb rate $2kbps ceil $3kbps prio $6
            #3. 设过滤器, handle 255 fw-根据防火墙标识控制标记为 255 的包,(与 iptables, set-mark对应), 父类1:, 送到子类1RULE_ID$IP4处理
            tc filter add dev eth0 parent 1: protocol ip prio 1 handle $start fw flowid 1RULE_ID$IP4

            #ifb1 叶分类,parent 1:1能借用带宽, 不想借用,写成parent 1:, 改用主干类
            tc class add dev ifb1 parent 1: classid 1RULE_ID$IP4 htb rate $4kbps ceil $5kbps prio $6
            tc filter add dev ifb1 parent 1: protocol ip prio 1 handle $((start+1000)) fw flowid 1:$RULE_ID$IP4

            for pppoe_ifconfig in $wan_list;
            do
                #pppoe 重定向到 ifb0    #redirect 会进入blackhole
                [ -z $init ] && {
                    tc qdisc add dev $pppoe_ifconfig root handle 1: htb default 999
                }
                tc class add dev $pppoe_ifconfig parent 1: classid 1:$RULE_ID$IP4 htb rate $4kbps ceil $5kbps prio $6
                tc filter add dev $pppoe_ifconfig parent 1: protocol ip prio 1 handle $((start+1000)) fw flowid 1:$RULE_ID$IP4 action mirred egress mirror dev ifb1
            done
            init=1

            #tc class add dev ifb1 parent 1: classid 1:$RULE_ID$IP4 htb rate $4kbps ceil $5kbps prio $6
            #tc filter add dev ifb1 parent 1: protocol ip prio 1 u32 match ip src $NET.$start flowid 1:$RULE_ID$IP4

    <<!
            #TCP UDP 连接数限制
            [ "$7" != "0" ] && {
                echo "iptables -t mangle -D FORWARD -p tcp -d $NET.$start -m connlimit --connlimit-above $7 -j DROP" >> $qosv4_tmp_pach/connlimit
                iptables -t mangle -A FORWARD -p tcp -d $NET.$start -m connlimit --connlimit-above $7 -j DROP
            }
            [ "$8" != "0" ] && {
                echo "iptables -t mangle -D FORWARD -p udp -d $NET.$start -m connlimit --connlimit-above $8 -j DROP" >> $qosv4_tmp_pach/connlimit
                iptables -t mangle -A FORWARD -p udp -d $NET.$start -m connlimit --connlimit-above $8 -j DROP
            }
    !
            start=$((start+1))
        done
    }

    #没有配置限速的IP, 设置默认规则
    qos_default_limit(){
        tc class add dev ifb1 parent 1:1 classid 1:999 htb rate 8kbps ceil 12kbps prio 7
        tc class add dev ifb0 parent 1:1 classid 1:999 htb rate 250kbps ceil 300kbps prio 7
    }

    #QOS白名单
    qos_white(){
        #192.168.1.8,192.168.1.80-192.168.1.90有zhoutao0712发放的免死金牌
        #iptables -t mangle -I PUNISH0 -m iprange --src-range 192.168.1.80-192.168.1.90 -j RETURN
        iptables -t mangle -I PUNISH0 -s $nolimit_ip -j RETURN
    }

    <<!
        config qos_settings
            option UP '100'
            option UPLOADR2 '1'
            option UPLOADC2 '5'
            option DOWNLOADR2 '1'
            option DOWNLOADC2 '2'
            option DOWNLOADR '50'
            option UPLOADR '20'
            option qos_scheduler '0'
            option DOWN '2600'
            option enable '0'
    !
    #读取总网速配置
    get_qos_config(){
        config_get GLOBAL_ENABLE $1 enable
        config_get GLOBAL_UP $1 UP
        config_get GLOBAL_DOWN $1 DOWN
        #config_get GLOBAL_UPLOADR2 $1 UPLOADR2
        #config_get GLOBAL_UPLOADC2 $1 UPLOADC2
        #config_get GLOBAL_DOWNLOADR2 $1 DOWNLOADR2
        #config_get GLOBAL_DOWNLOADC2 $1 DOWNLOADC2
        #config_get qos_scheduler $1 qos_scheduler
        echo "get_qos_config: GLOBAL_ENABLE=$GLOBAL_ENABLE GLOBAL_UP=$GLOBAL_UP  GLOBAL_DOWN=$GLOBAL_DOWN"
    }


    <<!
        config qos_ip
            option enable '1'
            option limit_ips '192.168.1.12'
            option limit_ipe '192.168.1.19'
            option UPLOADR '10'  保证
            option UPLOADC '16'  最大
            option DOWNLOADR '150'  保证
            option DOWNLOADC '2200'  最大
            option tcplimit '0'
            option udplimit '0'
            option ip_prio '5'
    !
    #循环读取每条IP限速规则, 并调用限速
    get_qos_ip_limit(){
        config_get qos_limit_enable $1 enable
        config_get limit_ips $1 limit_ips
        config_get limit_ipe $1 limit_ipe
        config_get ip_prio $1 ip_prio
        config_get UPLOADC $1 UPLOADC
        config_get DOWNLOADC $1 DOWNLOADC
        config_get UPLOADR $1 UPLOADR
        config_get DOWNLOADR $1 DOWNLOADR
        config_get tcplimit $1 tcplimit
        config_get udplimit $1 udplimit
        limit_ip=$limit_ips-$limit_ipe

        #echo "get_qos_ip_limit: enable=$qos_limit_enable limit_ips=$limit_ips  limit_ipe=$limit_ipe ip_prio=$ip_prio UPLOADC=$UPLOADC DOWNLOADC=$DOWNLOADC"
        #放在这里调用是因为foreach循环调用
        [ "$qos_limit_enable" == "1" ] && qos_ip_limit $limit_ip $DOWNLOADR $DOWNLOADC $UPLOADR $UPLOADC $ip_prio $tcplimit $udplimit
    }

    <<!
        config 'qos_nolimit_ip'
            option 'nolimit_ip' '192.168.1.1'
            option 'nolimit_mac' '00:00:00:00:00'
            option 'enable' '0'
    !
    #读取不限制ip和mac
    get_qos_nolimit_ip(){
        config_get enable $1 enable
        config_get nolimit_ip $1 nolimit_ip
        config_get nolimit_mac $1 nolimit_mac
        [ "$enable" == "1" ]&&printf "|grep -v  $nolimit_mac " >>${qosv4_tmp_pach}/qosv4_nolimit_mac
    }

    usage() {
    cat << EOF
        Usage: $0 [start|stop]
    EOF
        exit 1
    }

    #lan_net
    #单位: kbps--千字节/s
    all_wan_down_speed=1500
    all_wan_up_speed=50
    #each_wan_up_speed=30
    qosv4_tmp_pach="/tmp/qosv4"
    [ -d $qosv4_tmp_pach ] || mkdir -p ${qosv4_tmp_pach}
    case $1 in
        start)
            config_load qosv4
            echo "start qosv4........"
            rm -rf ${qosv4_tmp_pach}/qosv4_nolimit_mac
            config_foreach   get_qos_config   qos_settings
            #GLOBAL_ENABLE=1
            echo "qosv4 enable=$GLOBAL_ENABLE "
            if [ "$GLOBAL_ENABLE" == "1" ];then
                #存在insmod文件表示已经加载过了
                [ -f ${qosv4_tmp_pach}/insmod ] || load_modules >/dev/null 2>&1
                qos_start
                #qos_default_limit
                #QOS白名单
                #config_foreach   get_qos_nolimit_ip   qos_nolimit_ip
                #qos_white
            else
                echo "ENABLE = 0.";echo ""
                qos_stop
            fi
            ;;
        stop)
            qos_stop
            #qos_stop >/dev/null 2>&1
            ;;
        *) usage;;
    esac

  • 相关阅读:
    jquery css 主菜单样式的跳转
    JS学习笔记-事件绑定
    CAS—认证原理
    uva 1203
    简化delegate写法
    使用apache htpasswd生成加密的password文件,并使用.htaccess控制文件夹訪问
    菜鸟学Java(二十)——你知道long和Long有什么差别吗?
    【spring cloud】【spring boot】网管服务-->配置文件添加endpoints.enabled = false,SpringBoot应用监控Actuator使用的安全隐患
    【Devops】【docker】【CI/CD】Jenkins源码管理,设置gitlab上项目的clone地址 + jenkins构建报错:Please make sure you have the correct access rights and the repository exists.
    【Devops】【docker】【CI/CD】jenkins源码管理,添加SSH地址后报错+Jenkins构建报错:Please make sure you have the correct access rights and the repository exists.
  • 原文地址:https://www.cnblogs.com/d9394/p/10611690.html
Copyright © 2011-2022 走看看