source: trunk/package/firewall/files/uci_firewall.sh @ 18028

Last change on this file since 18028 was 18028, checked in by nbd, 7 years ago

firewall: fix zone defaults

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