This repository has been archived by the owner on Sep 3, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
hfsc
207 lines (165 loc) · 6.66 KB
/
hfsc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/bin/sh
# Uplink and downlink speeds
DOWNLINK=$3
UPLINK=$4
# Device that connects you to the Internet
DEV=$2
# Action to be performed
ACTION=$1
# IP addresses of the VoIP phones,
# if none, set VOIPIPS=""
VOIPIPS=""
# Interactive class: SSH Terminal, DNS and gaming (Quake)
INTERACTIVEPORTS="22 53 3389 5900 27015:27020"
# VoIP telephony
#VOIPPORTS="5060:5100 10000:11000 5000:5059 8000:8016 5004 1720 1731"
VOIPPORTS="5060:5100 16000:16050"
# WWW, jabber and IRC
BROWSINGPORTS="80 443 8080"
# The lowest priority traffic: eDonkey, Bittorrent, etc.
P2PPORTS="110 25 21 143 445 137:139 4662 4664 62090:62110"
########################################################################
# Configuration ends here
########################################################################
#function check_device() {
if [ -z "$DEV" ] ; then
echo "$0: stop requires a device, aborting."
exit 0
fi
#}
case "$ACTION" in
status)
# check_device
echo "[qdisc]"
tc -s qdisc show dev $DEV
echo ""
echo "[class]"
tc -s class show dev $DEV
echo ""
echo "[filter]"
tc -s filter show dev $DEV
echo ""
echo "[iptables]"
iptables -t mangle -L THESHAPER -v -x 2> /dev/null
exit
;;
stop)
# check_device
# Reset everything to a known state (cleared)
tc qdisc del dev $DEV root > /dev/null 2>&1
tc qdisc del dev $DEV ingress > /dev/null 2>&1
# Flush and delete tables
iptables -t mangle --delete POSTROUTING -o $DEV -j THESHAPER > /dev/null 2>&1
iptables -t mangle --flush THESHAPER 2> /dev/null > /dev/null
iptables -t mangle --delete-chain THESHAPER 2> /dev/null > /dev/null
echo "Shaping removed on $DEV."
exit
;;
start)
# check_device
if [ -z "$DOWNLINK" ] ; then
echo "$0: start requires a downlink speed, aborting."
exit -1
fi
if [ -z "$UPLINK" ] ; then
echo "$0: start requires an uplink speed, aborting."
exit -1
fi
# Traffic classes:
# 1:2 Interactive (SSH, DNS, ACK, Quake)
# 1:3 Low latency (VoIP)
# 1:4 Browsing (HTTP, HTTPs)
# 1:5 Default
# 1:6 Low priority (p2p, pop3, smtp, etc)
# add HFSC root qdisc
tc qdisc add dev $DEV root handle 1: hfsc default 5
# add main rate limit class
tc class add dev $DEV parent 1: classid 1:1 hfsc \
sc rate ${UPLINK}kbit ul rate ${UPLINK}kbit
# Interactive traffic: guarantee realtime full uplink for 50ms, then
# 5/10 of the uplink
tc class add dev $DEV parent 1:1 classid 1:2 hfsc \
rt m1 ${UPLINK}kbit d 50ms m2 $((5*$UPLINK/10))kbit \
ls m1 ${UPLINK}kbit d 50ms m2 $((7*$UPLINK/10))kbit \
ul rate ${UPLINK}kbit
# VoIP: guarantee full uplink for 200ms, then 3/10
tc class add dev $DEV parent 1:1 classid 1:3 hfsc \
sc m1 ${UPLINK}kbit d 200ms m2 $((3*$UPLINK/10))kbit \
ul rate ${UPLINK}kbit
# Browsing: Don't guarantee anything for the first second, then
# guarantee 1/10
tc class add dev $DEV parent 1:1 classid 1:4 hfsc \
sc m1 0 d 1s m2 $((1*$UPLINK/10))kbit \
ul rate ${UPLINK}kbit
# Default traffic: don't guarantee anything for the first two seconds,
# then guarantee 1/20
tc class add dev $DEV parent 1:1 classid 1:5 hfsc \
sc m1 0 d 2s m2 $((1*$UPLINK/20))kbit \
ul rate ${UPLINK}kbit
# Default traffic: don't guarantee anything for the first 10 seconds,
# then guarantee 1/20
tc class add dev $DEV parent 1:1 classid 1:6 hfsc \
sc m1 0 d 10s m2 $((1*$UPLINK/20))kbit \
ul rate ${UPLINK}kbit
# add THESHAPER chain to the mangle table in iptables
iptables -t mangle --new-chain THESHAPER
iptables -t mangle --insert POSTROUTING -o $DEV -j THESHAPER
# To speed up downloads while an upload is going on, put short ACK
# packets in the interactive class:
iptables -t mangle -A THESHAPER \
-p tcp \
-m tcp --tcp-flags FIN,SYN,RST,ACK ACK \
-m length --length :64 \
-j CLASSIFY --set-class 1:2
# put large (512+) icmp packets in browsing category
iptables -t mangle -A THESHAPER \
-p icmp \
-m length --length 512: \
-j CLASSIFY --set-class 1:4
# ICMP (ip protocol 1) in the interactive class
iptables -t mangle -A THESHAPER \
-p icmp \
-m length --length :512 \
-j CLASSIFY --set-class 1:2
setclassbyport() {
port=$1
CLASS=$2
iptables -t mangle -A THESHAPER -p udp --sport $port -j CLASSIFY --set-class $CLASS
iptables -t mangle -A THESHAPER -p udp --dport $port -j CLASSIFY --set-class $CLASS
iptables -t mangle -A THESHAPER -p tcp --sport $port -j CLASSIFY --set-class $CLASS
iptables -t mangle -A THESHAPER -p tcp --dport $port -j CLASSIFY --set-class $CLASS
}
for port in $INTERACTIVEPORTS; do setclassbyport $port 1:2; done
for port in $VOIPPORTS; do setclassbyport $port 1:3; done
for port in $BROWSINGPORTS; do setclassbyport $port 1:4; done
for port in $P2PPORTS; do setclassbyport $port 1:6; done
for VOIP in $VOIPIPS
do
iptables -t mangle -A THESHAPER --src $VOIP -j CLASSIFY --set-class 1:3
iptables -t mangle -A THESHAPER --dst $VOIP -j CLASSIFY --set-class 1:3
done
# Try to control the incoming traffic as well.
# Set up ingress qdisc
tc qdisc add dev $DEV handle ffff: ingress
# Filter everything that is coming in too fast
# It's mostly HTTP downloads that keep jamming the downlink, so try to restrict
# them to 6/10 of the downlink.
tc filter add dev $DEV parent ffff: protocol ip prio 50 \
u32 match ip src 0.0.0.0/0 \
match ip protocol 6 0xff \
match ip sport 80 0xffff \
police rate $((6*${DOWNLINK}/10))kbit \
burst 10k drop flowid :1
tc filter add dev $DEV parent ffff: protocol ip prio 50 \
u32 match ip src 0.0.0.0/0 \
match ip protocol 6 0xff \
match ip dport 80 0xffff \
police rate $((6*${DOWNLINK}/10))kbit \
burst 10k drop flowid :1
;;
*)
echo "$0 [ACTION] [device]"
echo "ACTION := { start [downlink] [uplink] | stop | status }"
exit
;;
esac