[8.09] firewall: add an fw_clear function to flush rules, like it's done in trunk
[openwrt/svn-archive/archive.git] / package / firewall / files / uci_firewall.sh
1 #!/bin/sh
2 # Copyright (C) 2008 John Crispin <blogic@openwrt.org>
3
4 . /etc/functions.sh
5
6 IPTABLES="echo iptables"
7 IPTABLES=iptables
8
9 config_clear
10 include /lib/network
11 scan_interfaces
12
13 CONFIG_APPEND=1
14 config_load firewall
15
16 config fw_zones
17 ZONE_LIST=$CONFIG_SECTION
18
19 CUSTOM_CHAINS=1
20 DEF_INPUT=DROP
21 DEF_OUTPUT=DROP
22 DEF_FORWARD=DROP
23
24 load_policy() {
25 config_get input $1 input
26 config_get output $1 output
27 config_get forward $1 forward
28
29 DEF_INPUT="${input:-$DEF_INPUT}"
30 DEF_OUTPUT="${output:-$DEF_OUTPUT}"
31 DEF_FORWARD="${forward:-$DEF_FORWARD}"
32 }
33
34 create_zone() {
35 local exists
36
37 [ "$1" == "loopback" ] && return
38
39 config_get exists $ZONE_LIST $1
40 [ -n "$exists" ] && return
41 config_set $ZONE_LIST $1 1
42
43 $IPTABLES -N zone_$1
44 $IPTABLES -N zone_$1_MSSFIX
45 $IPTABLES -N zone_$1_ACCEPT
46 $IPTABLES -N zone_$1_DROP
47 $IPTABLES -N zone_$1_REJECT
48 $IPTABLES -N zone_$1_forward
49 $IPTABLES -A zone_$1_forward -j zone_$1_$5
50 $IPTABLES -A zone_$1 -j zone_$1_$3
51 $IPTABLES -A output -j zone_$1_$4
52 $IPTABLES -N zone_$1_nat -t nat
53 $IPTABLES -N zone_$1_prerouting -t nat
54 [ "$6" == "1" ] && $IPTABLES -t nat -A POSTROUTING -j zone_$1_nat
55 }
56
57 addif() {
58 local network="$1"
59 local ifname="$2"
60 local zone="$3"
61
62 local n_if n_zone
63 config_get n_if core "${network}_ifname"
64 config_get n_zone core "${network}_zone"
65 [ -n "$n_zone" ] && {
66 if [ "$n_zone" != "$zone" ]; then
67 delif "$network" "$n_if" "$n_zone"
68 else
69 return
70 fi
71 }
72
73 logger "adding $network ($ifname) to firewall zone $zone"
74 $IPTABLES -A input -i "$ifname" -j zone_${zone}
75 $IPTABLES -I zone_${zone}_MSSFIX 1 -o "$ifname" -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
76 $IPTABLES -I zone_${zone}_ACCEPT 1 -o "$ifname" -j ACCEPT
77 $IPTABLES -I zone_${zone}_DROP 1 -o "$ifname" -j DROP
78 $IPTABLES -I zone_${zone}_REJECT 1 -o "$ifname" -j reject
79 $IPTABLES -I zone_${zone}_ACCEPT 1 -i "$ifname" -j ACCEPT
80 $IPTABLES -I zone_${zone}_DROP 1 -i "$ifname" -j DROP
81 $IPTABLES -I zone_${zone}_REJECT 1 -i "$ifname" -j reject
82 $IPTABLES -I zone_${zone}_nat 1 -t nat -o "$ifname" -j MASQUERADE
83 $IPTABLES -I PREROUTING 1 -t nat -i "$ifname" -j zone_${zone}_prerouting
84 $IPTABLES -A forward -i "$ifname" -j zone_${zone}_forward
85 uci_set_state firewall core "${network}_ifname" "$ifname"
86 uci_set_state firewall core "${network}_zone" "$zone"
87 ACTION=add ZONE="$zone" INTERFACE="$network" DEVICE="$ifname" /sbin/hotplug-call firewall
88 }
89
90 delif() {
91 local network="$1"
92 local ifname="$2"
93 local zone="$3"
94
95 logger "removing $network ($ifname) from firewall zone $zone"
96 $IPTABLES -D input -i "$ifname" -j zone_$zone
97 $IPTABLES -D zone_${zone}_MSSFIX -o "$ifname" -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
98 $IPTABLES -D zone_${zone}_ACCEPT -o "$ifname" -j ACCEPT
99 $IPTABLES -D zone_${zone}_DROP -o "$ifname" -j DROP
100 $IPTABLES -D zone_${zone}_REJECT -o "$ifname" -j reject
101 $IPTABLES -D zone_${zone}_ACCEPT -i "$ifname" -j ACCEPT
102 $IPTABLES -D zone_${zone}_DROP -i "$ifname" -j DROP
103 $IPTABLES -D zone_${zone}_REJECT -i "$ifname" -j reject
104 $IPTABLES -D zone_${zone}_nat -t nat -o "$ifname" -j MASQUERADE
105 $IPTABLES -D PREROUTING -t nat -i "$ifname" -j zone_${zone}_prerouting
106 $IPTABLES -D forward -i "$ifname" -j zone_${zone}_forward
107 uci_revert_state firewall core "${network}_ifname"
108 uci_revert_state firewall core "${network}_zone"
109 ACTION=remove ZONE="$zone" INTERFACE="$network" DEVICE="$ifname" /sbin/hotplug-call firewall
110 }
111
112 load_synflood() {
113 local rate=${1:-25}
114 local burst=${2:-50}
115 echo "Loading synflood protection"
116 $IPTABLES -N syn_flood
117 $IPTABLES -A syn_flood -p tcp --syn -m limit --limit $rate/second --limit-burst $burst -j RETURN
118 $IPTABLES -A syn_flood -j DROP
119 $IPTABLES -A INPUT -p tcp --syn -j syn_flood
120 }
121
122 fw_set_chain_policy() {
123 local chain=$1
124 local target=$2
125 [ "$target" == "REJECT" ] && {
126 $IPTABLES -A $chain -j reject
127 target=DROP
128 }
129 $IPTABLES -P $chain $target
130 }
131
132 fw_clear() {
133 $IPTABLES -F
134 $IPTABLES -t nat -F
135 $IPTABLES -t nat -X
136 $IPTABLES -X
137 }
138
139 fw_defaults() {
140 [ -n "$DEFAULTS_APPLIED" ] && {
141 echo "Error: multiple defaults sections detected"
142 return;
143 }
144 DEFAULTS_APPLIED=1
145
146 load_policy "$1"
147
148 echo 1 > /proc/sys/net/ipv4/tcp_syncookies
149 for f in /proc/sys/net/ipv4/conf/*/accept_redirects
150 do
151 echo 0 > $f
152 done
153 for f in /proc/sys/net/ipv4/conf/*/accept_source_route
154 do
155 echo 0 > $f
156 done
157
158 uci_revert_state firewall core
159 uci_set_state firewall core "" firewall_state
160
161 $IPTABLES -P INPUT DROP
162 $IPTABLES -P OUTPUT DROP
163 $IPTABLES -P FORWARD DROP
164
165 fw_clear
166
167 config_get_bool drop_invalid $1 drop_invalid 1
168
169 [ "$drop_invalid" -gt 0 ] && {
170 $IPTABLES -A INPUT -m state --state INVALID -j DROP
171 $IPTABLES -A OUTPUT -m state --state INVALID -j DROP
172 $IPTABLES -A FORWARD -m state --state INVALID -j DROP
173 }
174
175 $IPTABLES -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
176 $IPTABLES -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
177 $IPTABLES -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
178
179 $IPTABLES -A INPUT -i lo -j ACCEPT
180 $IPTABLES -A OUTPUT -o lo -j ACCEPT
181
182 config_get syn_flood $1 syn_flood
183 config_get syn_rate $1 syn_rate
184 config_get syn_burst $1 syn_burst
185 [ "$syn_flood" == "1" ] && load_synflood $syn_rate $syn_burst
186
187 echo "Adding custom chains"
188 fw_custom_chains
189
190 $IPTABLES -N input
191 $IPTABLES -N output
192 $IPTABLES -N forward
193
194 $IPTABLES -A INPUT -j input
195 $IPTABLES -A OUTPUT -j output
196 $IPTABLES -A FORWARD -j forward
197
198 $IPTABLES -N reject
199 $IPTABLES -A reject -p tcp -j REJECT --reject-with tcp-reset
200 $IPTABLES -A reject -j REJECT --reject-with icmp-port-unreachable
201
202 fw_set_chain_policy INPUT "$DEF_INPUT"
203 fw_set_chain_policy OUTPUT "$DEF_OUTPUT"
204 fw_set_chain_policy FORWARD "$DEF_FORWARD"
205 }
206
207 fw_zone() {
208 local name
209 local network
210 local masq
211
212 config_get name $1 name
213 config_get network $1 network
214 config_get masq $1 masq
215 load_policy $1
216
217 [ -z "$network" ] && network=$name
218 create_zone "$name" "$network" "$input" "$output" "$forward" "$masq"
219 fw_custom_chains_zone "$name"
220 }
221
222 fw_rule() {
223 local src
224 local src_ip
225 local src_mac
226 local src_port
227 local src_mac
228 local dest
229 local dest_ip
230 local dest_port
231 local proto
232 local target
233 local ruleset
234
235 config_get src $1 src
236 config_get src_ip $1 src_ip
237 config_get src_mac $1 src_mac
238 config_get src_port $1 src_port
239 config_get dest $1 dest
240 config_get dest_ip $1 dest_ip
241 config_get dest_port $1 dest_port
242 config_get proto $1 proto
243 config_get target $1 target
244 config_get ruleset $1 ruleset
245
246 src_port_first=${src_port%-*}
247 src_port_last=${src_port#*-}
248 [ "$src_port_first" -ne "$src_port_last" ] && { \
249 src_port="$src_port_first:$src_port_last"; }
250
251 dest_port_first=${dest_port%-*}
252 dest_port_last=${dest_port#*-}
253 [ "$dest_port_first" -ne "$dest_port_last" ] && { \
254 dest_port="$dest_port_first:$dest_port_last"; }
255
256 ZONE=input
257 TARGET=$target
258 [ -z "$target" ] && target=DROP
259 [ -n "$src" -a -z "$dest" ] && ZONE=zone_$src
260 [ -n "$src" -a -n "$dest" ] && ZONE=zone_${src}_forward
261 [ -n "$dest" ] && TARGET=zone_${dest}_$target
262 add_rule() {
263 $IPTABLES -I $ZONE 1 \
264 ${proto:+-p $proto} \
265 ${src_ip:+-s $src_ip} \
266 ${src_port:+--sport $src_port} \
267 ${src_mac:+-m mac --mac-source $src_mac} \
268 ${dest_ip:+-d $dest_ip} \
269 ${dest_port:+--dport $dest_port} \
270 -j $TARGET
271 }
272 [ "$proto" == "tcpudp" -o -z "$proto" ] && {
273 proto=tcp
274 add_rule
275 proto=udp
276 add_rule
277 return
278 }
279 add_rule
280 }
281
282 fw_forwarding() {
283 local src
284 local dest
285 local masq
286
287 config_get src $1 src
288 config_get dest $1 dest
289 config_get_bool mtu_fix $1 mtu_fix 0
290 [ -n "$src" ] && z_src=zone_${src}_forward || z_src=forward
291 [ -n "$dest" ] && z_dest=zone_${dest}_ACCEPT || z_dest=ACCEPT
292 $IPTABLES -I $z_src 1 -j $z_dest
293 [ "$mtu_fix" -gt 0 -a -n "$dest" ] && $IPTABLES -I $z_src 1 -j zone_${dest}_MSSFIX
294 }
295
296 fw_redirect() {
297 local src
298 local src_ip
299 local src_port
300 local src_dport
301 local src_mac
302 local dest_ip
303 local dest_port dest_port2
304 local proto
305
306 config_get src $1 src
307 config_get src_ip $1 src_ip
308 config_get src_port $1 src_port
309 config_get src_dport $1 src_dport
310 config_get src_mac $1 src_mac
311 config_get dest_ip $1 dest_ip
312 config_get dest_port $1 dest_port
313 config_get proto $1 proto
314 [ -z "$src" -o -z "$dest_ip" ] && { \
315 echo "redirect needs src and dest_ip"; return ; }
316
317 src_port_first=${src_port%-*}
318 src_port_last=${src_port#*-}
319 [ "$src_port_first" -ne "$src_port_last" ] && { \
320 src_port="$src_port_first:$src_port_last"; }
321
322 src_dport_first=${src_dport%-*}
323 src_dport_last=${src_dport#*-}
324 [ "$src_dport_first" -ne "$src_dport_last" ] && { \
325 src_dport="$src_dport_first:$src_dport_last"; }
326
327 dest_port2=$dest_port
328 dest_port_first=${dest_port2%-*}
329 dest_port_last=${dest_port2#*-}
330 [ "$dest_port_first" -ne "$dest_port_last" ] && { \
331 dest_port2="$dest_port_first:$dest_port_last"; }
332
333 add_rule() {
334 $IPTABLES -A zone_${src}_prerouting -t nat \
335 ${proto:+-p $proto} \
336 ${src_ip:+-s $src_ip} \
337 ${src_port:+--sport $src_port} \
338 ${src_dport:+--dport $src_dport} \
339 ${src_mac:+-m mac --mac-source $src_mac} \
340 -j DNAT --to-destination $dest_ip${dest_port:+:$dest_port}
341
342 $IPTABLES -I zone_${src}_forward 1 \
343 ${proto:+-p $proto} \
344 -d $dest_ip \
345 ${src_ip:+-s $src_ip} \
346 ${src_port:+--sport $src_port} \
347 ${dest_port2:+--dport $dest_port2} \
348 ${src_mac:+-m mac --mac-source $src_mac} \
349 -j ACCEPT
350 }
351 [ "$proto" == "tcpudp" -o -z "$proto" ] && {
352 proto=tcp
353 add_rule
354 proto=udp
355 add_rule
356 return
357 }
358 add_rule
359 }
360
361 fw_include() {
362 local path
363 config_get path $1 path
364 [ -e $path ] && . $path
365 }
366
367 fw_addif() {
368 local up
369 local ifname
370 config_get up $1 up
371 config_get ifname $1 ifname
372 [ -n "$up" ] || return 0
373 (ACTION="ifup" INTERFACE="$1" . /etc/hotplug.d/iface/20-firewall)
374 }
375
376 fw_custom_chains() {
377 [ -n "$CUSTOM_CHAINS" ] || return 0
378 $IPTABLES -N input_rule
379 $IPTABLES -N output_rule
380 $IPTABLES -N forwarding_rule
381 $IPTABLES -N prerouting_rule -t nat
382 $IPTABLES -N postrouting_rule -t nat
383
384 $IPTABLES -A INPUT -j input_rule
385 $IPTABLES -A OUTPUT -j output_rule
386 $IPTABLES -A FORWARD -j forwarding_rule
387 $IPTABLES -A PREROUTING -t nat -j prerouting_rule
388 $IPTABLES -A POSTROUTING -t nat -j postrouting_rule
389 }
390
391 fw_custom_chains_zone() {
392 local zone="$1"
393
394 [ -n "$CUSTOM_CHAINS" ] || return 0
395 $IPTABLES -N input_${zone}
396 $IPTABLES -N forwarding_${zone}
397 $IPTABLES -N prerouting_${zone} -t nat
398 $IPTABLES -I zone_${zone} 1 -j input_${zone}
399 $IPTABLES -I zone_${zone}_forward 1 -j forwarding_${zone}
400 $IPTABLES -I zone_${zone}_prerouting 1 -t nat -j prerouting_${zone}
401 }
402
403 fw_init() {
404 DEFAULTS_APPLIED=
405
406 echo "Loading defaults"
407 config_foreach fw_defaults defaults
408 echo "Loading zones"
409 config_foreach fw_zone zone
410 echo "Loading forwarding"
411 config_foreach fw_forwarding forwarding
412 echo "Loading redirects"
413 config_foreach fw_redirect redirect
414 echo "Loading rules"
415 config_foreach fw_rule rule
416 echo "Loading includes"
417 config_foreach fw_include include
418 uci_set_state firewall core loaded 1
419 unset CONFIG_APPEND
420 config_load network
421 config_foreach fw_addif interface
422 }
423
424 fw_stop() {
425 fw_clear
426 $IPTABLES -P INPUT ACCEPT
427 $IPTABLES -P OUTPUT ACCEPT
428 $IPTABLES -P FORWARD ACCEPT
429 uci_revert_state firewall core
430 }