#!/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