xeno add
[firewall-squeep] / shaper.sh
1 #!/bin/sh
2
3 # settings
4 UPLINK=11232 #kbit
5 BURST=15 #k
6 SHAPE_CHAIN='SHAPER-OUT'
7 #
8
9 set -e
10
11 # . ./common.sh
12 IPTABLES=$(which iptables)
13 IP6TABLES=$(which ip6tables)
14 IPSET=$(which ipset)
15 TC=$(which tc)
16
17 if [ $# -lt 1 ]
18 then
19 echo "Usage: $(basename "$0") external_interface" 1>&2
20 exit 64
21 fi
22
23 EXT_IF="$1"
24 if ! ip link show "${EXT_IF}" >/dev/null 2>&1
25 then
26 echo "'${EXT_IF}' does not seem to be a valid interface"
27 exit 1
28 fi
29
30 function shape_if(){
31 local ext_if="$1" uplink="$2" burst="$3"
32
33 $TC qdisc del dev ${ext_if} root >/dev/null 2>&1 || true
34
35 $TC qdisc add dev ${ext_if} root handle 1: htb default 30
36 $TC class add dev ${ext_if} parent 1: classid 1:1 htb rate ${uplink}kbit burst ${burst}k
37
38 $TC class add dev ${ext_if} parent 1:1 classid 1:10 htb rate ${uplink}kbit burst ${burst}k prio 1
39 $TC class add dev ${ext_if} parent 1:1 classid 1:20 htb rate ${uplink}kbit burst ${burst}k prio 2
40 $TC class add dev ${ext_if} parent 1:1 classid 1:30 htb rate $(expr 9 \* ${uplink} / 10)kbit burst ${burst}k prio 3
41 $TC class add dev ${ext_if} parent 1:1 classid 1:40 htb rate $(expr 5 \* ${uplink} / 10)kbit burst ${burst}k prio 4
42 $TC class add dev ${ext_if} parent 1:1 classid 1:50 htb rate $(expr 5 \* ${uplink} / 10)kbit burst $(expr 2 \* ${burst} / 3)k prio 5
43
44 for x in $(seq 5)
45 do
46 # $TC qdisc add dev ${ext_if} parent 1:${x}0 handle ${x}0: sfq perturb 10
47 $TC qdisc add dev ${ext_if} parent 1:${x}0 handle ${x}0: fq_codel
48 $TC filter add dev ${ext_if} parent 1: prio 0 protocol ip handle ${x} fw flowid 1:${x}0
49 done
50 }
51
52 function shape(){
53 local prio="$1"
54 shift
55 if ! $IPTABLES -t mangle -C "${SHAPE_CHAIN}" "$@" -j MARK --set-mark ${prio} >/dev/null 2>&1
56 then
57 $IPTABLES -t mangle -A "${SHAPE_CHAIN}" "$@" -j MARK --set-mark ${prio}
58 fi
59 if ! $IP6TABLES -t mangle -C "${SHAPE_CHAIN}" "$@" -j MARK --set-mark ${prio} >/dev/null 2>&1
60 then
61 $IP6TABLES -t mangle -A "${SHAPE_CHAIN}" "$@" -j MARK --set-mark ${prio}
62 fi
63 }
64
65 shape_if "${EXT_IF}" "${UPLINK}" "${BURST}"
66
67 if ! $IPTABLES -t mangle -L "${SHAPE_CHAIN}" >/dev/null 2>&1
68 then
69 echo "initializing ipv4 chain '${SHAPE_CHAIN}'"
70 $IPTABLES -t mangle -N "${SHAPE_CHAIN}"
71 fi
72 if ! $IP6TABLES -t mangle -L "${SHAPE_CHAIN}" >/dev/null 2>&1
73 then
74 echo "initializing ipv6 chain '${SHAPE_CHAIN}'"
75 $IP6TABLES -t mangle -N "${SHAPE_CHAIN}"
76 fi
77
78 # prioritize small and responsive things
79 shape 1 -p icmp
80 shape 1 -p ipv6-icmp
81 shape 1 -p udp
82 shape 1 -p tcp -m length --length :64
83 shape 1 -p tcp --syn -m length --length 40:68
84 shape 1 -p tcp --tcp-flags ALL ACK -m length --length 40:100
85 shape 1 -p tcp --tcp-flags ALL RST
86 shape 1 -p tcp --tcp-flags ALL ACK,RST
87 shape 1 -p tcp --tcp-flags ALL ACK,FIN
88
89 # favor ssh
90 shape 2 -p tcp --dport 22
91
92 # defavor ftp
93 shape 4 -p tcp --dport 20
94 shape 4 -p tcp --dport 115
95
96 # bulk bittorrent
97 shape 5 -p tcp --dport 8881:8899
98 shape 5 -p tcp --sport 8881:8899
99
100 # default everything else to middle
101 shape 3 -m mark --mark 0
102
103 if ! $IPTABLES -t mangle -C POSTROUTING -o "${EXT_IF}" -j "${SHAPE_CHAIN}" >/dev/null 2>&1
104 then
105 $IPTABLES -t mangle -I POSTROUTING -o "${EXT_IF}" -j "${SHAPE_CHAIN}"
106 fi
107
108 if ! $IP6TABLES -t mangle -C POSTROUTING -o "${EXT_IF}" -j "${SHAPE_CHAIN}" >/dev/null 2>&1
109 then
110 $IP6TABLES -t mangle -I POSTROUTING -o "${EXT_IF}" -j "${SHAPE_CHAIN}"
111 fi
112
113 if [[ ! -e /etc/local.d/shaper.start ]]
114 then
115 echo "add shaper to local rc start!"
116 fi