#!/bin/bash # # Jim diGriz's QoS Scheduler (http://digriz.org.uk/jdg-qos-script/) # [remove 'junk-this' to mail me] # GPL V2 blar blar blar # Version: 030805 (aka 5th August 2003) # # Dependencies # 1) HTB3 patch (if <2.4.18) and 'tc' patch # 2) RED (in kernel 2.4.x) # 3) iptables (in kernel 2.4.x) # 4) ESFQ patch (http://www.ssi.bg/~alex/esfq/index.html) and 'tc' patch # 5) IMQ patch (http://trash.net/~kaber/imq/) and 'tc' patch # # N.B. # shaping only works for OUTGOING packets simply so think which interface to use # # Useful Info # IPTables TOS Fields: # Minimize-Delay 16 (0x10) # Maximize-Throughput 8 (0x08) # Maximize-Reliability 4 (0x04) # Minimize-Cost 2 (0x02), # Normal-Service 0 (0x00). # Dependencies (when you need IMQ): # 1) for NAT must have IMQ # 2) for QoS to affect locally generated traffic in a non ethernet bridge setup # you must have IMQ # debug on.... set -x # local programs TC=/usr/local/sbin/tc IPTABLES=/sbin/iptables IP=/sbin/ip MODPROBE=/sbin/modprobe # ballpark configuration details (all in kbit) DWIF=eth1 # LAN facing interface DWIFLIMIT=1638 # Download Speed (2048*0.8) UPIF=eth0 # WAN facing interface UPIFSPEED=100000 # speed of LAN card UPIFLIMIT=204 # Upload Speed (256*0.8) NAT=0 # 1 || 0 (yes || no) LOCAL_TRAFFIC=192.168.0.0/16 # 'local' LAN address QOS_GATEWAY_TRAFFIC=1 # 1 || 0 (yes || no) ETHERNET_BRIDGE=1 # 1 || 0 (yes || no) # do not change anything below here....I mean it.....I am talking to you buster! HTB_DEBUG=0000000000000000 REAL_UPIF=$UPIF REAL_DWIF=$DWIF if (( ( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE ) || $NAT )) then UPIF=imq0 fi if (( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE )) then DWIF=imq1 fi if [ "$1" = "status" ] then $TC -s qdisc ls dev $DWIF $TC -s qdisc ls dev $UPIF $IPTABLES -t mangle -L SHAPER-OUT -v -n $IPTABLES -t mangle -L SHAPER-IN -v -n exit fi if [ "$1" = "pollbuckets" ] then watch -n1 "$TC -s qdisc show dev $DWIF; echo \"--------\"; $TC -s qdisc show dev $UPIF" exit fi if [ "$1" = "pollrules" ] then watch -n1 "$IPTABLES -t mangle -L SHAPER-OUT -v -n; echo \"--------\"; $IPTABLES -t mangle -L SHAPER-IN -v -n" exit fi if ( [ "$1" != "stop" ] && [ "$1" != "start" ] && [ "$1" != "restart" ] ) then exit fi $TC qdisc del dev $DWIF root &> /dev/null $IPTABLES -t mangle -D PREROUTING -i $REAL_UPIF -j SHAPER-IN &> /dev/null $TC qdisc del dev $UPIF root &> /dev/null $IPTABLES -t mangle -D PREROUTING -i $REAL_DWIF -j SHAPER-OUT &> /dev/null if (( ( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE ) || $NAT )) then $IPTABLES -t mangle -D POSTROUTING -o $REAL_UPIF -j IMQ --todev 0 &> /dev/null fi if (( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE )) then $IPTABLES -t mangle -D PREROUTING -i $REAL_UPIF -j IMQ --todev 1 &> /dev/null fi if (( $QOS_GATEWAY_TRAFFIC )) then $IPTABLES -t mangle -D OUTPUT -m mark --mark 0 -j SHAPER-OUT &> /dev/null fi if (( ( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE ) || $NAT )) then $IP link set $UPIF down &> /dev/null if (( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE )) then $IP link set $DWIF down &> /dev/null fi $MODPROBE -r imq &> /dev/null fi $IPTABLES -t mangle -F SHAPER-IN &> /dev/null $IPTABLES -t mangle -X SHAPER-IN &> /dev/null $IPTABLES -t mangle -F SHAPER-OUT &> /dev/null $IPTABLES -t mangle -X SHAPER-OUT &> /dev/null if ( [ "$1" = "stop" ] ) then exit fi ############# configuring QoS system ###################### $IPTABLES -t mangle -N SHAPER-OUT $IPTABLES -t mangle -N SHAPER-IN if (( ( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE ) || $NAT )) then if (( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE )) then $MODPROBE imq numdevs=2 $IP link set $DWIF up else $MODPROBE imq numdevs=1 fi $IP link set $UPIF up fi if (( $QOS_GATEWAY_TRAFFIC )) then $IPTABLES -t mangle -I OUTPUT -m mark --mark 0 -j SHAPER-OUT fi ###### uplink # install root HTB, point default traffic to 1:27: $TC qdisc add dev $UPIF root handle 1: htb default 1 debug $HTB_DEBUG $TC class add dev $UPIF parent 1: classid 1:2 htb rate ${UPIFLIMIT}kbit # shape everything at $UPIFLIMIT speed - this prevents huge queues in your # DSL modem which destroy latency: for LOOP in `seq 0 9` do # high prio class 1:20 to low prio class 1:29: $TC class add dev $UPIF parent 1:2 classid 1:$[$LOOP+20] htb \ rate $[(5-($LOOP/2))*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio $LOOP # all get Enchanced Stochastic Fairness (depending on src ip): $TC qdisc add dev $UPIF parent 1:$[$LOOP+20] handle $[$LOOP+20]: esfq \ perturb 10 hash src # setup $IPTABLES hooks $TC filter add dev $UPIF parent 1: prio $LOOP protocol ip \ handle $[$LOOP+20] fw flowid 1:$[$LOOP+20] done if (( ( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE ) || $NAT )) then $IPTABLES -t mangle -I POSTROUTING -o $REAL_UPIF -j IMQ --todev 0 fi $IPTABLES -t mangle -I PREROUTING -i $REAL_DWIF -j SHAPER-OUT # DW as PREROUTING ########## downlink ############# # slow downloads down to somewhat less than the real speed to prevent # queuing at our ISP. Tune to see how high you can set it. # ISPs tend to have *huge* queues to make sure big downloads are fast # $TC qdisc add dev $DWIF root handle 1: htb default 1 debug $HTB_DEBUG $TC class add dev $DWIF parent 1: classid 1:2 htb rate ${DWIFLIMIT}kbit $TC class add dev $DWIF parent 1:2 classid 1:20 htb rate $[$DWIFLIMIT/2]kbit \ ceil ${DWIFLIMIT}kbit burst 6k prio 0 $TC class add dev $DWIF parent 1:2 classid 1:21 htb rate $[$DWIFLIMIT/2]kbit \ ceil ${DWIFLIMIT}kbit burst 6k prio 1 $TC qdisc add dev $DWIF parent 1:20 handle 20: esfq perturb 10 hash dst # ---- RED_MIN=$[$DWIFLIMIT*1000/8/4] # starts dropping at 25% bandwidth RED_MAX=$[$DWIFLIMIT*1000/8] RED_LIMIT=$[$RED_MAX*2] RED_AVPKT=1000 # ---- $TC qdisc add dev $DWIF parent 1:21 handle 21: red \ probability 0.02 limit ${RED_LIMIT} min ${RED_MIN} max ${RED_MAX} \ avpkt ${RED_AVPKT} burst $[((2*$RED_MIN)+($RED_MAX))/(3*$RED_AVPKT)] $TC filter add dev $DWIF parent 1: prio 0 protocol ip handle 20 fw flowid 1:20 $TC filter add dev $DWIF parent 1: prio 1 protocol ip handle 21 fw flowid 1:21 if (( $QOS_GATEWAY_TRAFFIC && ! $ETHERNET_BRIDGE )) then $IPTABLES -t mangle -I PREROUTING -i $REAL_UPIF -j IMQ --todev 1 fi $IPTABLES -t mangle -I PREROUTING -i $REAL_UPIF -j SHAPER-IN # UP as PREROUTING ################## finish QoS configuration ######################### ################# begin packet classification ####################### # `Advanced' users can tweak the iptables section at the end of the script. # For upload you have ten `buckets' (numbered 20 to 29, where 29 is low priority) # to pick from. You work out a chain of iptables rules to decide what type of # packet goes into which bucket. Treat the beginning of the chain to set a base # `MARK', and then later iptable rules adjust the packet so when you leave the # chain the packet has the desired MARKing (and so priority). For downloading, # you have only two buckets, number 20 where traffic cannot be dropped, such as # ICMP and UDP traffic (and also high priority); whilst number 21 is for bulk # traffic which can be dropped safely with knowledge that it is not going to # generate more traffic, such as TCP traffic. # # upload (20->29) $IPTABLES -t mangle -A SHAPER-OUT -d $LOCAL_TRAFFIC -j RETURN # local traffic $IPTABLES -t mangle -A SHAPER-OUT -p icmp -j MARK --set-mark 20 # icmp (ping) $IPTABLES -t mangle -A SHAPER-OUT -p tcp -m tcp --tcp-flags SYN,RST SYN \ -j MARK --set-mark 21 # SYN and SYN/ACK $IPTABLES -t mangle -A SHAPER-OUT -p tcp -m tcp --tcp-flags ACK ACK \ -m length --length :128 -m tos --tos ! Normal-Service \ -j MARK --set-mark 21 # regular ACK $IPTABLES -t mangle -A SHAPER-OUT -p tcp -m tcp --tcp-flags ACK ACK \ -m length --length 128: -j MARK --set-mark 29 # P2P traffic ACK $IPTABLES -t mangle -A SHAPER-OUT -p tcp -m tcp --tcp-flags RST RST \ -j MARK --set-mark 21 # RST packets $IPTABLES -t mangle -A SHAPER-OUT -p tcp -m tcp --tcp-flags FIN FIN \ -j MARK --set-mark 21 # FIN packet $IPTABLES -t mangle -A SHAPER-OUT -p tcp -m tos --tos Minimize-Delay \ -j MARK --set-mark 23 # low latency traffic $IPTABLES -t mangle -A SHAPER-OUT -p tcp --sport ssh:telnet \ -j MARK --set-mark 22 # ssh/telnet $IPTABLES -t mangle -A SHAPER-OUT -p tcp --dport ssh:telnet \ -j MARK --set-mark 22 # ssh/telnet $IPTABLES -t mangle -A SHAPER-OUT -p udp -j MARK --set-mark 24 # udp traffic $IPTABLES -t mangle -A SHAPER-OUT -p tcp --sport http \ -j MARK --set-mark 26 # web traffic $IPTABLES -t mangle -A SHAPER-OUT -p tcp --dport http \ -j MARK --set-mark 26 # web traffic $IPTABLES -t mangle -A SHAPER-OUT -p tcp -m tos --tos Maximize-Throughput \ -j MARK --set-mark 28 # get ssh bulk and other bulk traffic $IPTABLES -t mangle -A SHAPER-OUT -p tcp --dport 20 \ -j MARK --set-mark 28 # (ftp data) (should not be needed) $IPTABLES -t mangle -A SHAPER-OUT -p tcp --sport 20 \ -j MARK --set-mark 28 # (ftp data) (should not be needed) $IPTABLES -t mangle -A SHAPER-OUT -m mark --mark 0 -p tcp --sport :1024 \ -j MARK --set-mark 25 # default for privilaged services $IPTABLES -t mangle -A SHAPER-OUT -m mark --mark 0 -p tcp --dport :1024 \ -j MARK --set-mark 25 # default for privilaged services $IPTABLES -t mangle -A SHAPER-OUT -m mark --mark 0 \ -j MARK --set-mark 27 # default for everything un-marked # download (20->21) $IPTABLES -t mangle -A SHAPER-IN -d $LOCAL_TRAFFIC -j RETURN # local traffic $IPTABLES -t mangle -A SHAPER-IN -p ! tcp \ -j MARK --set-mark 20 # non-tcp traffic $IPTABLES -t mangle -A SHAPER-IN -p tcp -m tcp --tcp-flags SYN,RST SYN \ -j MARK --set-mark 20 # regular SYN and SYN/ACK $IPTABLES -t mangle -A SHAPER-IN -p tcp -m tcp --tcp-flags ACK ACK \ -m length --length :128 -m tos --tos ! Normal-Service \ -j MARK --set-mark 20 # regular ACK $IPTABLES -t mangle -A SHAPER-IN -p tcp -m tcp --tcp-flags RST RST \ -j MARK --set-mark 20 # RST packets $IPTABLES -t mangle -A SHAPER-IN -p tcp -m tcp --tcp-flags FIN FIN \ -j MARK --set-mark 20 # FIN packet $IPTABLES -t mangle -A SHAPER-IN -p tcp --sport ssh:telnet \ -j MARK --set-mark 20 # ssh/telnet $IPTABLES -t mangle -A SHAPER-IN -p tcp --dport ssh:telnet \ -j MARK --set-mark 20 # ssh/telnet $IPTABLES -t mangle -A SHAPER-IN -p tcp -m tos --tos Minimize-Delay \ -j MARK --set-mark 20 # low latency traffic $IPTABLES -t mangle -A SHAPER-IN -p tcp -m tos --tos Maximize-Throughput \ -j MARK --set-mark 21 # bulk traffic $IPTABLES -t mangle -A SHAPER-IN -m mark --mark 0 \ -j MARK --set-mark 21 # default for the rest ################### end packet classification #######################