fix shaper.sh
[firewall-squeep] / router.sh
1 #!/bin/bash
2
3 set -e
4
5 # some system-specific config...
6
7 EXT=173.164.216.234
8 EXT_IF=eth2
9
10 INT='192.168.0.0/24'
11 INT_IF=eth5
12
13 EXT6_IF=he6
14 INT6_IF=eth5
15 SUBNET6='2001:470:1f05:cb8::/64'
16
17 UPLINK=11232 #kbit
18 BURST=15 #k
19
20 # note that behavior between v4 and v6 is slightly different
21
22 ###
23 ##
24 #
25 IPTABLES=$(which iptables)
26 IP6TABLES=$(which ip6tables)
27 IPSET=$(which ipset)
28 TC=$(which tc)
29 SYSCTL=/usr/sbin/sysctl
30 F2B_CTL="/etc/init.d/fail2ban"
31
32 if [ "commit" != "$1" ]; then
33 IPTABLES="echo ${IPTABLES}"
34 IP6TABLES="echo ${IP6TABLES}"
35 IPSET="echo ${IPSET}"
36 TC="echo ${TC}"
37 SYSCTL="echo ${SYSCTL}"
38 F2B_CTL="echo ${F2B_CTL}"
39 fi
40
41 # fail2ban writes its own chains, don't flush tables before shutting it down
42 f2b_needs_attention=0
43 if f2b_pid=$(cat /var/run/fail2ban/fail2ban.pid)
44 then
45 f2b_comm=`ps -o comm= -p ${f2b_pid}`
46 if [ $? -eq 0 ]; then
47 if [ "fail2ban-server" = "${f2b_comm}" ]; then
48 f2b_needs_attention=1
49 fi
50 fi
51 fi
52
53 function sysctl_set(){
54 if [ "$2" != $($SYSCTL -ne "$1") ]
55 then
56 echo "setting $1 to $2"
57 $SYSCTL -w "$1"="$2"
58 fi
59 }
60
61 # system config
62 # enable forwarding
63 sysctl_set net.ipv4.ip_forward 1
64 sysctl_set net.ipv6.conf.all.forwarding 1
65 # disable routing triangulation; queries go out same interface
66 sysctl_set net.ipv4.conf.all.rp_filter 1
67 # log malformed packets
68 #${SYSCTL} -w net.ipv4.conf.all.log_martians=1
69 sysctl_set net.ipv4.conf.all.log_martians 0
70 # disable redirects
71 sysctl_set net.ipv4.conf.all.send_redirects 0
72 sysctl_set net.ipv4.conf.all.accept_redirects 0
73 # disable source routed packets
74 sysctl_set net.ipv4.conf.all.accept_source_route 0
75 # do syncookies
76 sysctl_set net.ipv4.tcp_syncookies 1
77
78 if [ ${f2b_needs_attention} -eq 1 ]; then
79 ${F2B_CTL} stop
80 fi
81
82 # flush tables
83 ${IPTABLES} -F
84 ${IPTABLES} -F INPUT
85 ${IPTABLES} -F OUTPUT
86 ${IPTABLES} -F FORWARD
87 ${IPTABLES} -F -t mangle
88 ${IPTABLES} -F -t nat
89 ${IPTABLES} -X
90
91 $IP6TABLES -F
92 $IP6TABLES -F INPUT
93 $IP6TABLES -F OUTPUT
94 $IP6TABLES -F FORWARD
95 $IP6TABLES -F -t mangle
96 $IP6TABLES -X
97
98 # default policies
99 $IPTABLES -P INPUT DROP
100 $IPTABLES -P OUTPUT ACCEPT
101 $IPTABLES -P FORWARD ACCEPT
102
103 $IP6TABLES -P INPUT DROP
104 $IP6TABLES -P OUTPUT DROP
105 $IP6TABLES -P FORWARD DROP
106
107 # clear and reset traffic control
108 (
109 set +e
110 if $TC qdisc del dev ${EXT_IF}
111 then
112 echo "removed existing qdisc"
113 else
114 echo "new qdisc"
115 fi
116 if $TC qdisc add dev ${EXT_IF} root handle 1: htb default 30
117 then
118 echo "qdisc root exists"
119 else
120 echo "new qdisc root"
121 fi
122 $TC class add dev ${EXT_IF} parent 1: classid 1:1 htb rate ${UPLINK}kbit burst ${BURST}k
123 $TC class add dev ${EXT_IF} parent 1:1 class 1:10 htb rate ${UPLINK}kbit burst ${BURST}k prio 1
124 $TC class add dev ${EXT_IF} parent 1:1 class 1:20 htb rate ${UPLINK}kbit burst ${BURST}k prio 2
125 $TC class add dev ${EXT_IF} parent 1:1 class 1:30 htb rate $(expr 9 \* ${UPLINK} / 10)kbit burst ${BURST}k prio 3
126 $TC class add dev ${EXT_IF} parent 1:1 class 1:40 htb rate $(expr 5 \* ${UPLINK} / 10)kbit burst ${BURST}k prio 4
127 $TC class add dev ${EXT_IF} parent 1:1 class 1:50 htb rate $(expr 5 \* ${UPLINK} / 10)kbit burst $(expr 2 \* ${BURST} / 3)k prio 5
128
129 for x in $(seq 5)
130 do
131 $TC qdisc add dev ${EXT_IF} parent 1:${x}0 handle ${x}0: sfq perturb 10
132 $TC filter add dev ${EXT_IF} parent 1: prio 0 protocol ip handle ${x} fw flowid 1:${x}0
133 done
134 )
135
136 SHAPE_CHAIN='SHAPER-OUT'
137 # shaper marking
138 $IPTABLES -t mangle -X ${SHAPE_CHAIN}
139 $IPTABLES -t mangle -N ${SHAPE_CHAIN}
140 $IP6TABLES -t mangle -X ${SHAPE_CHAIN}
141 $IP6TABLES -t mangle -N ${SHAPE_CHAIN}
142
143 function shape() {
144 local PRIO=$1
145 shift
146 if ! $IPTABLES -t mangle -C ${SHAPE_CHAIN} "$@" -j MARK --set-mark ${PRIO} >/dev/null 2>&1
147 then
148 $IPTABLES -t mangle -A ${SHAPE_CHAIN} "$@" -j MARK --set-mark ${PRIO}
149 fi
150 if ! $IP6TABLES -t mangle -C ${SHAPE_CHAIN} "$@" -j MARK --set-mark ${PRIO} >/dev/null 2>&1
151 then
152 $IP6TABLES -t mangle -A ${SHAPE_CHAIN} "$@" -j MARK --set-mark ${PRIO}
153 fi
154 }
155
156 # prioritize small and responsive things
157 shape 1 -p icmp
158 shape 1 -p ipv6-icmp
159 shape 1 -p udp
160 #shape 1 -p tcp -m length :64
161 #shape 1 -p tcp --syn -m length 40:68
162 #shape 1 -p tcp --tcp-flags ALL ACK -m length --length 40:100
163 shape 1 -p tcp --tcp-flags ALL RST
164 shape 1 -p tcp --tcp-flags ALL ACK,RST
165 shape 1 -p tcp --tcp-flags ALL ACK,FIN
166
167 # favor ssh
168 shape 2 -p tcp --dport 22
169
170 # defavor ftp
171 shape 4 -p tcp --dport 20
172 shape 4 -p tcp --dport 115
173
174 # bulk bittorrent
175 shape 5 -p tcp --dport 8881:8899
176 shape 5 -p tcp --sport 8881:8899
177
178 # default everything else to middle
179 shape 3 -m mark --mark 0
180
181 # tag traffic
182 $IPTABLES -t mangle -I POSTROUTING -o ${EXT_IF} -j ${SHAPE_CHAIN}
183
184
185 # reserve a special place in hell for some people
186 $IPTABLES -N xenophobe
187 $IPTABLES -A xenophobe -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
188 $IPTABLES -A xenophobe -j REJECT --reject-with icmp-port-unreachable
189
190 $IP6TABLES -N xenophobe
191 $IP6TABLES -A xenophobe -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
192 $IP6TABLES -A xenophobe -j REJECT --reject-with icmp6-port-unreachable
193
194 # create ipsets for v4 and v6
195 for s in xenophobe sinokorea
196 do
197 $IPSET create "$s" -exist hash:net counters
198 $IPSET create "$s"6 -exist hash:net family inet6 counters
199 done
200 for s in trusted
201 do
202 $IPSET create "$s" -exist hash:net
203 $IPSET create "$s"6 -exist hash:net family inet6
204 done
205
206 # create ipsets shared by v4 and v6
207 for s in allowed_udp allowed_tcp
208 do
209 $IPSET create "$s" -exist bitmap:port range 0-65535
210 done
211
212
213 ###
214 ##
215 #
216
217 # allow local traffics
218 $IPTABLES -A INPUT -i lo -j ACCEPT
219 $IP6TABLES -A INPUT -i lo -j ACCEPT
220 $IP6TABLES -A OUTPUT -o lo -j ACCEPT
221
222 # allow anything out to v6
223 $IP6TABLES -A OUTPUT -o ${EXT6_IF} -j ACCEPT
224
225 # allow all internal traffic in
226 $IP6TABLES -I INPUT -i ${INT6_IF} -j ACCEPT
227
228 # allow icmp
229 $IPTABLES -A INPUT -p icmp -j ACCEPT
230 $IP6TABLES -A INPUT -p ipv6-icmp -j ACCEPT
231 $IP6TABLES -A OUTPUT -p ipv6-icmp -j ACCEPT
232 $IP6TABLES -A FORWARD -p ipv6-icmp -j ACCEPT
233
234 # drop source-route headered v6
235 $IP6TABLES -A INPUT -m rt --rt-type 0 -j DROP || echo "MISSING RT MATCH" 1>&2
236
237 # drop bad packets; these are all illegal combinations
238 for flags in 'ALL FIN,URG,PSH' 'ALL ALL' 'ALL SYN,RST,ACK,FIN,URG' 'ALL NONE' 'SYN,RST SYN,RST' 'SYN,FIN SYN,FIN'
239 do
240 $IPTABLES -A INPUT -p tcp --tcp-flags ${flags} -j DROP
241 done
242
243 # allow trusted things
244 $IPTABLES -A INPUT -m set --match-set trusted src -j ACCEPT
245 $IP6TABLES -A INPUT -m set --match-set trusted6 src -j ACCEPT
246
247 # drop sketchy things
248 $IPTABLES -A INPUT -m set --match-set xenophobe src -j xenophobe
249 $IP6TABLES -A INPUT -m set --match-set xenophobe6 src -j xenophobe
250
251 # drop asia from ssh and smtp
252 $IPTABLES -A INPUT -m set --match-set sinokorea src -m multiport -p tcp --dports ssh,smtp -j xenophobe
253 $IP6TABLES -A INPUT -m set --match-set sinokorea6 src -m multiport -p tcp --dports ssh,smtp -j xenophobe
254
255 # don't forward packets in
256 $IPTABLES -A FORWARD -i ${EXT_IF} -m conntrack --ctstate NEW,INVALID -j DROP
257
258 # forward from internal site subnet
259 $IP6TABLES -A FORWARD -i ${INT6_IF} -o ${EXT6_IF} -s ${SUBNET6} -m conntrack --ctstate NEW -j ACCEPT
260
261 # allow things we've dealt with
262 $IPTABLES -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
263 $IP6TABLES -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
264 $IP6TABLES -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
265
266 # accept ipv6 link-local
267 $IP6TABLES -A INPUT -s fe80::/10 -j ACCEPT
268 $IP6TABLES -A OUTPUT -s fe80::/10 -j ACCEPT
269
270 # accept ipv6 multicast
271 $IP6TABLES -A INPUT -s ff00::/8 -j ACCEPT
272 $IP6TABLES -A OUTPUT -s ff00::/8 -j ACCEPT
273
274 # many:1 NAT
275 $IPTABLES -t nat -A POSTROUTING -o ${EXT_IF} -j SNAT --to ${EXT}
276
277 # accept internal network traffic
278 $IPTABLES -A INPUT -i ${INT_IF} -j ACCEPT
279
280 # accept list of external ports
281 $IPTABLES -A INPUT -i ${EXT_IF} -p tcp -m set --match-set allowed_tcp dst -j ACCEPT
282 $IPTABLES -A INPUT -i ${EXT_IF} -p udp -m set --match-set allowed_udp dst -j ACCEPT
283 $IP6TABLES -A INPUT -i ${EXT6_IF} -p tcp -m set --match-set allowed_tcp dst -j ACCEPT
284 $IP6TABLES -A INPUT -i ${EXT6_IF} -p udp -m set --match-set allowed_udp dst -j ACCEPT
285
286 # load rules
287 # inserts, so stack order matters
288 ./sinokorea.sh
289 ./xenophobe.sh
290 ./trusted.sh
291
292 if [ ${f2b_needs_attention} -eq 1 ]; then
293 ${F2B_CTL} start
294 fi