#!/bin/bash # ultimate.sh for ns.chsoft.biz # Based on Wonder Shaper v1.1a echo "/usr/sbin/ultimate.sh: " # Please read the README before filling out these values. # Set the following values to somewhat less than your actual download # and upload speed in kilobits. Also set the device that is to be shaped. # Run a speed test from netspeed.stanford.edu with no shaping enabled. # UPLINK comes from "client to server" and DNLINK comes from "server to client" # Multiply the reported rates in Kb/s by ~.95 and enter them here: # Example: DNLINK=1.62M*.95 = 1539 # UPLINK=2.08*.95 = 1907.6 # Run the stanford test again. Note: stanford uses high ports. # Watch the logs for "some class has too small rate" even with quantum set. # See /root/speedtests. Best DNLINK to date (5Sep06) is 2.94M # UPLINK value below is 100% of best per tests # DNLINK applies to IFI and IMQ # CEIL applies to IMQ # 10Apr07 netspeed.stanford.edu test: Dn 3.47 Up 2.57 (see calc below) # so changed from 4632, 4400 and 3170 CEIL=3554 # 3.47*1024=3553 # 3.47*1024*.95=3375 DNLINK=3376 # SkyRiver DSL has tested over 4600 (4632*.95=4400) # 2.57*10248.90=2369 UPLINK=2370 # SkyRiver DSL (Spec: 1500*.90=1350) # Percentages, egress first: # sum(Ie + Ae + Be + Pe) _MUST_ = 100 Ie=5 # Interactive Ae=50 # Accelerated Be=33 # Bulk Pe=12 # Penalized # ingress (IFI, not IMQ): # sum(Ii + Ai + Bi + Pi) _MUST_ = 100 Ii=1 # Interactive Ai=51 # Accelerated Bi=40 # Bulk Pi=8 # Penalized # IMQ: # sum(IMi + IMb) _MUST_ = 100 IMi=5 # Interactive IMa=30 # Accelerated IMb=65 # Bulk # Example: IFE=ppp0 IFI=eth0 # Ingress NIC; Internal Interface IFE=eth1 # Egress NIC; External Interface IMQ=imq0 # Local IPs: CHS="66.209.101.192/29" # SkyRiver (chsoft.biz) NEWS="66.209.101.195" # news.chsoft.biz YIC="66.209.101.194" # yesican.chsoft.biz # Remote IPs: AAsia1="211.99.141.150" # AppfinityAsia (HiPrio) AAsia2="218.249.71.210" # AppfinityAsia (HiPrio) ATJ=`cat /etc/firewall/Duron` # andthatsjazz ADE3="216.196.97.142" # news3.news.adelphia.net and news.iswest.com CBANK="63.202.114.131" # Cathay Bank HBED1="62.146.66.160/27" # H+BEDV (antivirus) HBED2="217.11.60.0/27" # H+BEDV (antivirus) ISW1="207.178.128.0/24" # iswest ISW2="216.166.71.0/24" # iswest ISW3="216.196.105.0/24" # iswest (giganews) LHD1="12.29.97.200/29" # L. H. Dottie T1 LHD2="65.255.215.200/29" # L. H. Dottie wireless UNS1="63.223.5.0/24" # usenetserver (west = nntp2) UNS2="64.154.60.0/24" # usenetserver ###### EXPLANATION # See 'INGRESS' below for information about incoming packets. All of this # except for that refers to queueing outgoing packets. # # Most of what is sent goes out on a randomly selected high SOURCE port # ('sport') to a specific DESTINATION port ('dport'). For example, an http # request is sent with 'dport' = 80 and 'sport' = random. Therefore, 'sport' # specifications are rarely applicable. The port number is located in the # packet header and is specified thus: # "u32 match ip dport PORT# 0xffff" or "u32 match ip sport PORT# 0xffff" # # Since shaping means quequeing OUTGOING packets, your IP Address(es) are # SOURCEs ('src') and the remote machine's IP Address(es) are DESTINATIONs # ('dst') - so, as with 'sport', 'src' specifications are rarely applicable. # The IP Address is located in the packet header and is specified thus: # "u32 match ip src IP-ADDRESS" or "u32 match ip dst IP-ADDRESS" # # Read the HOWTO "All the filtering commands you will normally need" for # protocol information (TCP, UDP, ICMP, GRE, IPSEC). Also see the TOS and # ICMP sections below. ###### # Sometimes you may notice low priority OUTGOING traffic slowing down important # traffic. In that case, the following eLoPrio options may help you: ## * * * * Structure: ## {1} * * * * * IFE DEFINITIONS ## {2} * * * * * EGRESS on IFE (SERVERS --> INTERNET) ## {3} * * * * * INGRESS policing on IFE (INTERNET --> SERVERS) ## {4} * * * * * IFI DEFINITIONS ## {5} * * * * * EGRESS on IFI (INTERNET --> SERVERS) ## {6} * * * * * there is no INGRESS shaping on IFI (SERVERS --> INTERNET) ###### {1} External Interface DEFINITIONS: # Ports: # eLoPrioSPORT ('sport') # Set this to source ports that should have low priority. If you have # an unimportant webserver on your traffic, set this to 80. # These go into class 40 # (some ports ) 20 21 22 23 25 53 80 113 119 873 # (and what they are:) FTPd FTPc SSH SMTP DNS HTTP IDENT NNTP Rsync # 9001 and 9030 are tor # Matches (apparently) nothing. eLoPrioSPORT="21 23 67 68 79 135 137 138 139 389 445 446 901 1026 1027 1028 1029 1234 5018 9001 9030" # eHiPrioSPORT ('sport') # These go into class 20. ssh is interactive (class 10). # *** Make sure no eLoPrioSPORTs are duplicated here! *** # Matches (apparently) nothing. eHiPrioSPORT="873" # eLoPrioDPORT ('dport') # Set this to destination ports that should have low priority. # The following are from my TARPIT list: 79 135 137 138 139 445 901 # Matches DIR=FROM? remote:PORT eLoPrioDPORT="21 23 67 68 79 135 137 138 139 389 445 446 901 1026 1027 1028 1029 1234 5018 9001 9030" # eHiPrioDPORT ('dport') # *** Make sure no eLoPrioDPORTs are duplicated here! *** ssh is interactive. # Matches DIR=FROM? ?:PORT eHiPrioDPORT="113 123 873 5900 6502 8200" # IPs / Netmasks: # Set this to hosts or netmasks in your network that should have low priority. # Low priority OUTGOING traffic. You can leave this blank if you want. # Matches (apparently) nothing. eLoPrioCIDR_Src="" # See EXPLANATION above; these do not need to be here. # Matches (apparently) nothing. #ex eHiPrioCIDR_Src="$ADE3 $ATJ $ISW1 $ISW2 $UNS1" eHiPrioCIDR_Src="$AAsia1 $AAsia2 $ATJ $LHD1 $LHD2" # Set this to hosts or netmasks on the internet that should have low priority. # Matches FROM REMOTE eLoPrioCIDR_Dst="221.0.0.0/8" # high priority destination netmasks ('dst'): # Matches DIR? REMOTE:IP #eHiPrioCIDR_Dst="$ADE3 $ATJ $ISW1 $ISW2 $UNS1" eHiPrioCIDR_Dst="$AAsia1 $AAsia2 $ATJ $LHD1 $LHD2" ###### End External Interface DEFINITIONS if [ "$1" = "status" ]; then echo "Sent on $IFE (SkyRiver):" # tc -s filter show dev $IFE tc -s qdisc ls dev $IFE tc -s class ls dev $IFE echo "'rate #bit' means Bytes per Second" echo "Received on $IMQ (SkyRiver):" # tc -s filter show dev $IMQ tc -s qdisc ls dev $IMQ tc -s class ls dev $IMQ echo "'rate #bit' is meaningless. Use Backlog and Dropped." echo "Sent on $IFI: (ns to servers):" # tc -s filter show dev $IFI tc -s qdisc ls dev $IFI tc -s class ls dev $IFI echo "'rate #bit' means Bytes per Second" exit fi # Clean existing setup, hiding errors tc qdisc del dev $IFE root 2> /dev/null > /dev/null tc qdisc del dev $IFE ingress 2> /dev/null > /dev/null tc qdisc del dev $IFI root 2> /dev/null > /dev/null tc qdisc del dev $IFI ingress 2> /dev/null > /dev/null iptables -t mangle -D PREROUTING -i $IFE -j IMQ --todev 0 2>/dev/null > /dev/null tc qdisc del dev $IMQ root 2> /dev/null > /dev/null ip link set $IMQ down 2> /dev/null > /dev/null modprobe -r ipt_IMQ modprobe -r imq modprobe -r cls_u32 modprobe -r sch_esfq modprobe -r sch_htb modprobe -r sch_ingress if [ "$1" = "stop" ]; then exit fi ###### {2} uplink (EGRESS) on IFE # This part shapes on the external interface: SERVERS --> INTERNET # See '###### downlink (INGRESS) on IFI' below for the internal interface. # Install root HTB, point default traffic to 1:30: tc qdisc add dev $IFE root handle 1: htb default 30 # Shape everything at $UPLINK speed - this prevents huge queues in your # DSL modem which destroy latency: tc class add dev $IFE parent 1: classid 1:1 htb rate ${UPLINK}kbit burst 32k cburst 20k # High prio (interactive) class 1:10: tc class add dev $IFE parent 1:1 classid 1:10 htb rate $[Ie*$UPLINK/100]kbit \ ceil $[100*$UPLINK/100]kbit burst 32k quantum 1514 prio 1 # Accelerated class 1:20 - the HIPRIO stuff: tc class add dev $IFE parent 1:1 classid 1:20 htb rate $[Ae*$UPLINK/100]kbit \ ceil $[96*$UPLINK/100]kbit burst 16k cburst 10k quantum 1514 prio 2 # Bulk & default class 1:30 - gets a low priority: tc class add dev $IFE parent 1:1 classid 1:30 htb rate $[Be*$UPLINK/100]kbit \ ceil $[Ae*$UPLINK/100]kbit burst 8k cburst 5k quantum 1514 prio 3 # Set above ceil to rate of previous class # ceil $[96*$UPLINK/100]kbit burst 8k cburst 5k quantum 1514 prio 3 # Penalized class 1:40 - the LOPRIO stuff gets the lowest rate and priority: tc class add dev $IFE parent 1:1 classid 1:40 htb rate $[Pe*$UPLINK/100]kbit \ ceil $[Be*$UPLINK/100]kbit burst 2k quantum 1514 prio 4 # Set above ceil to rate of previous class # ceil $[Pe*$UPLINK/100]kbit burst 2k quantum 1514 prio 4 # Some get Stochastic Fairness: # LARTC mailing list indicates that interactive should not be included. Andy # Furniss suggests that bulk be the only thing subject to SF. I set a long # perturb for accelerated and exclude interactive. #tc qdisc add dev $IFE parent 1:10 handle 10: esfq limit 64 depth 64 divisor 10 hash classic perturb 20 tc qdisc add dev $IFE parent 1:20 handle 20: esfq limit 64 depth 64 divisor 10 hash classic perturb 99 tc qdisc add dev $IFE parent 1:30 handle 30: esfq limit 64 depth 64 divisor 10 hash classic perturb 20 tc qdisc add dev $IFE parent 1:40 handle 40: esfq limit 64 depth 64 divisor 10 hash classic perturb 10 # ARP: tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match u16 0x0806 0xffff at -2 flowid 1:40 ###### Accelerate (interactive) the following: # To speed up downloads while an upload is going on, put ACK packets in # the interactive class 1:10: # IP header length 0x5 (32 bit words) # IP total length 0x34 (ACK + 12 bytes of TCP options) # TCP ACK set (bit 5, offset 33) # ("at nexthdr+33" = "at 13") ## Match ACK on all TCP packets with the ACK bit set: ## Caveat!: This can match packets up to 64K; don't do it. Match small. #tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ # match ip protocol 6 0xff \ # match u8 0x10 0xff at nexthdr+13 \ # flowid 1:10 # Match TCP packets smaller than 128 bytes: # Because of the mask, can only match powers of 2 (32, 64, 128...) # 0xfff8 - 8 # 0xfff0 - 16 # 0xffe0 - 32 # 0xffc0 - 64 # 0xff80 - 128 # Remarked out ACK, normally 5th line: match u8 0x10 0xff at 33 \ # "match u8 0x05 0x0f at 0" makes sure the IP header is 20 bytes. tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip protocol 6 0xff \ match u8 0x05 0x0f at 0 \ match u16 0x0000 0xff80 at 2 \ flowid 1:10 # SSH is interactive: tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip dport 22 0xffff flowid 1:10 tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip sport 22 0xffff flowid 1:10 # DNS is interactive: tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip dport 53 0xffff flowid 1:10 tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip sport 53 0xffff flowid 1:10 ###### Some traffic is preferred, so in our class 1:20: for a in $eHiPrioDPORT; do tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip dport $a 0xffff flowid 1:20 done for a in $eHiPrioSPORT; do tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip sport $a 0xffff flowid 1:20 done for a in $eHiPrioCIDR_Src; do tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip src $a flowid 1:20 done for a in $eHiPrioCIDR_Dst; do tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip dst $a flowid 1:20 done ###### Give these short shrift: # Penalized traffic suffers a worse fate in our slowest class 1:40: for a in $eLoPrioDPORT; do tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip dport $a 0xffff flowid 1:40 done for a in $eLoPrioSPORT; do tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip sport $a 0xffff flowid 1:40 done for a in $eLoPrioCIDR_Src; do tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip src $a flowid 1:40 done for a in $eLoPrioCIDR_Dst; do tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip dst $a flowid 1:40 done if [ -f /etc/firewall/shitlist ]; then while read SLIST; do SLIST=$(echo "$SLIST" | awk '{print $1}') tc filter add dev $IFE parent 1: protocol all prio 5 u32 \ match ip dst $SLIST flowid 1:40 done SERVERS # Install root HTB, point default traffic to 1:30: tc qdisc add dev $IFI root handle 1: htb default 30 # Shape everything at $DNLINK speed tc class add dev $IFI parent 1: classid 1:1 htb rate ${DNLINK}kbit burst 32k cburst 20k # High prio (interactive) class 1:10: tc class add dev $IFI parent 1:1 classid 1:10 htb rate $[Ii*$DNLINK/100]kbit \ ceil $[100*$DNLINK/100]kbit burst 32k quantum 1514 prio 1 # Accelerated class 1:20 - the HIPRIO stuff: tc class add dev $IFI parent 1:1 classid 1:20 htb rate $[Ai*$DNLINK/100]kbit \ ceil $[96*$DNLINK/100]kbit burst 16k cburst 10k quantum 1514 prio 2 # Bulk & default class 1:30 - gets a low priority: tc class add dev $IFI parent 1:1 classid 1:30 htb rate $[Bi*$DNLINK/100]kbit \ ceil $[Ai*$DNLINK/100]kbit burst 8k cburst 5k quantum 1514 prio 3 # Set above ceil to rate of previous class # ceil $[96*$DNLINK/100]kbit burst 8k cburst 5k quantum 1514 prio 3 # Penalized class 1:40 - the LOPRIO stuff gets the lowest rate and priority: tc class add dev $IFI parent 1:1 classid 1:40 htb rate $[Pi*$DNLINK/100]kbit \ ceil $[Bi*$DNLINK/100]kbit burst 2k quantum 1514 prio 4 # Set above ceil to rate of previous class # ceil $[Pi*$DNLINK/100]kbit burst 2k quantum 1514 prio 4 # Some get Stochastic Fairness: # LARTC mailing list indicates that interactive should not be included. Andy # Furniss suggests that bulk be the only thing subject to SF. I set a long # perturb for accelerated and exclude interactive. #tc qdisc add dev $IFI parent 1:10 handle 10: esfq limit 64 depth 64 divisor 10 hash classic perturb 20 tc qdisc add dev $IFI parent 1:20 handle 20: esfq limit 64 depth 64 divisor 10 hash classic perturb 99 tc qdisc add dev $IFI parent 1:30 handle 30: esfq limit 64 depth 64 divisor 10 hash classic perturb 20 tc qdisc add dev $IFI parent 1:40 handle 40: esfq limit 64 depth 64 divisor 10 hash classic perturb 10 # ARP: tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match u16 0x0806 0xffff at -2 flowid 1:40 ###### Accelerate (interactive) the following: # To speed up downloads while an upload is going on, put ACK packets in # the interactive class 2:15: # IP header length 0x5 (32 bit words) # IP total length 0x34 (ACK + 12 bytes of TCP options) # TCP ACK set (bit 5, offset 33) # ("at nexthdr+33" = "at 13") ## Match ACK on all TCP packets with the ACK bit set: ## Caveat!: This can match packets up to 64K; Don't do it. Match small. #tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ # match ip protocol 6 0xff \ # match u8 0x10 0xff at nexthdr+13 \ # flowid 1:10 # Match TCP packets smaller than 128 bytes: # 0xfff8 - 8 # 0xfff0 - 16 # 0xffe0 - 32 # 0xffc0 - 64 # 0xff80 - 128 # Remarked out ACK, normally 5th line: match u8 0x10 0xff at 33 \ # "match u8 0x05 0x0f at 0" makes sure the IP header is 20 bytes. tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip protocol 6 0xff \ match u8 0x05 0x0f at 0 \ match u16 0x0000 0xff80 at 2 \ flowid 1:10 # SSH is interactive: tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip dport 22 0xffff flowid 1:10 tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip sport 22 0xffff flowid 1:10 # DNS is interactive: tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip dport 53 0xffff flowid 1:10 tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip sport 53 0xffff flowid 1:10 ###### Some traffic is preferred, so in our class 1:20: for a in $iHiPrioDPORT; do tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip dport $a 0xffff flowid 1:20 done for a in $iHiPrioSPORT; do tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip sport $a 0xffff flowid 1:20 done for a in $iHiPrioCIDR_Src; do tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip src $a flowid 1:20 done for a in $iHiPrioCIDR_Dst; do tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip dst $a flowid 1:20 done ###### Give these short shrift: # Penalized traffic suffers a worse fate in our slowest class 1:40: for a in $iLoPrioDPORT; do tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip dport $a 0xffff flowid 1:40 done for a in $iLoPrioSPORT; do tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip sport $a 0xffff flowid 1:40 done for a in $iLoPrioCIDR_Src; do tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip src $a flowid 1:40 done for a in $iLoPrioCIDR_Dst; do tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip dst $a flowid 1:40 done if [ -f /etc/firewall/shitlist ]; then while read SLIST; do SLIST=$(echo "$SLIST" | awk '{print $1}') tc filter add dev $IFI parent 1: protocol all prio 5 u32 \ match ip dst $SLIST flowid 1:40 done INTERNET) # Done ultimate.sh