source: branches/backfire/package/firewall/files/uci_firewall.sh @ 22902

Last change on this file since 22902 was 22902, checked in by jow, 6 years ago

[backfire] remove leftover debugging

  • Property svn:executable set to *
File size: 14.8 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        local masq_src="$4"
73        local masq_dest="$5"
74
75        local n_if n_zone
76        config_get n_if core "${network}_ifname"
77        config_get n_zone core "${network}_zone"
78        [ -n "$n_zone" ] && {
79                if [ "$n_zone" != "$zone" ]; then
80                        local n_masq_src n_masq_dest
81                        config_get n_masq_src core "${n_zone}_masq_src"
82                        config_get n_masq_dest core "${n_zone}_masq_dest"
83                        delif "$network" "$n_if" "$n_zone" "$n_masq_src" "$n_masq_dest"
84                else
85                        return
86                fi
87        }
88
89        logger "adding $network ($ifname) to firewall zone $zone"
90        $IPTABLES -A input -i "$ifname" -j zone_${zone}
91        $IPTABLES -I zone_${zone}_MSSFIX 1 -o "$ifname" -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
92        $IPTABLES -I zone_${zone}_ACCEPT 1 -o "$ifname" -j ACCEPT
93        $IPTABLES -I zone_${zone}_DROP 1 -o "$ifname" -j DROP
94        $IPTABLES -I zone_${zone}_REJECT 1 -o "$ifname" -j reject
95        $IPTABLES -I zone_${zone}_ACCEPT 1 -i "$ifname" -j ACCEPT
96        $IPTABLES -I zone_${zone}_DROP 1 -i "$ifname" -j DROP
97        $IPTABLES -I zone_${zone}_REJECT 1 -i "$ifname" -j reject
98
99        local msrc mdst
100        for msrc in ${masq_src:-0.0.0.0/0}; do
101                [ "${msrc#!}" != "$msrc" ] && msrc="! -s ${msrc#!}" || msrc="-s $msrc"
102                for mdst in ${masq_dest:-0.0.0.0/0}; do
103                        [ "${mdst#!}" != "$mdst" ] && mdst="! -d ${mdst#!}" || mdst="-d $mdst"
104                        $IPTABLES -I zone_${zone}_nat 1 -t nat -o "$ifname" $msrc $mdst -j MASQUERADE
105                done
106        done
107
108        $IPTABLES -I PREROUTING 1 -t nat -i "$ifname" -j zone_${zone}_prerouting
109        $IPTABLES -A forward -i "$ifname" -j zone_${zone}_forward
110        $IPTABLES -t raw -I PREROUTING 1 -i "$ifname" -j zone_${zone}_notrack
111        uci_set_state firewall core "${network}_ifname" "$ifname"
112        uci_set_state firewall core "${network}_zone" "$zone"
113        uci_set_state firewall core "${zone}_masq_src" "$masq_src"
114        uci_set_state firewall core "${zone}_masq_dest" "$masq_dest"
115        ACTION=add ZONE="$zone" INTERFACE="$network" DEVICE="$ifname" /sbin/hotplug-call firewall
116}
117
118delif() {
119        local network="$1"
120        local ifname="$2"
121        local zone="$3"
122        local masq_src="$4"
123        local masq_dest="$5"
124
125        logger "removing $network ($ifname) from firewall zone $zone"
126        $IPTABLES -D input -i "$ifname" -j zone_$zone
127        $IPTABLES -D zone_${zone}_MSSFIX -o "$ifname" -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
128        $IPTABLES -D zone_${zone}_ACCEPT -o "$ifname" -j ACCEPT
129        $IPTABLES -D zone_${zone}_DROP -o "$ifname" -j DROP
130        $IPTABLES -D zone_${zone}_REJECT -o "$ifname" -j reject
131        $IPTABLES -D zone_${zone}_ACCEPT -i "$ifname" -j ACCEPT
132        $IPTABLES -D zone_${zone}_DROP -i "$ifname" -j DROP
133        $IPTABLES -D zone_${zone}_REJECT -i "$ifname" -j reject
134
135        local msrc mdst
136        for msrc in ${masq_src:-0.0.0.0/0}; do
137                [ "${msrc#!}" != "$msrc" ] && msrc="! -s ${msrc#!}" || msrc="-s $msrc"
138                for mdst in ${masq_dest:-0.0.0.0/0}; do
139                        [ "${mdst#!}" != "$mdst" ] && mdst="! -d ${mdst#!}" || mdst="-d $mdst"
140                        $IPTABLES -D zone_${zone}_nat -t nat -o "$ifname" $msrc $mdst -j MASQUERADE
141                done
142        done
143
144        $IPTABLES -D PREROUTING -t nat -i "$ifname" -j zone_${zone}_prerouting
145        $IPTABLES -D forward -i "$ifname" -j zone_${zone}_forward
146        uci_revert_state firewall core "${network}_ifname"
147        uci_revert_state firewall core "${network}_zone"
148        uci_revert_state firewall core "${zone}_masq_src"
149        uci_revert_state firewall core "${zone}_masq_dest"
150        ACTION=remove ZONE="$zone" INTERFACE="$network" DEVICE="$ifname" /sbin/hotplug-call firewall
151}
152
153load_synflood() {
154        local rate=${1:-25}
155        local burst=${2:-50}
156        echo "Loading synflood protection"
157        $IPTABLES -N syn_flood
158        $IPTABLES -A syn_flood -p tcp --syn -m limit --limit $rate/second --limit-burst $burst -j RETURN
159        $IPTABLES -A syn_flood -j DROP
160        $IPTABLES -A INPUT -p tcp --syn -j syn_flood
161}
162
163fw_set_chain_policy() {
164        local chain=$1
165        local target=$2
166        [ "$target" == "REJECT" ] && {
167                $IPTABLES -A $chain -j reject
168                target=DROP
169        }
170        $IPTABLES -P $chain $target
171}
172
173fw_clear() {
174        $IPTABLES -F
175        $IPTABLES -t nat -F
176        $IPTABLES -t nat -X
177        $IPTABLES -t raw -F
178        $IPTABLES -t raw -X
179        $IPTABLES -X
180}
181
182fw_defaults() {
183        [ -n "$DEFAULTS_APPLIED" ] && {
184                echo "Error: multiple defaults sections detected"
185                return;
186        }
187        DEFAULTS_APPLIED=1
188
189        load_policy "$1"
190
191        echo 1 > /proc/sys/net/ipv4/tcp_syncookies
192        for f in /proc/sys/net/ipv4/conf/*/accept_redirects
193        do
194                echo 0 > $f
195        done
196        for f in /proc/sys/net/ipv4/conf/*/accept_source_route
197        do
198                echo 0 > $f
199        done
200
201        uci_revert_state firewall core
202        uci_set_state firewall core "" firewall_state
203
204        $IPTABLES -P INPUT DROP
205        $IPTABLES -P OUTPUT DROP
206        $IPTABLES -P FORWARD DROP
207
208        fw_clear
209        config_get_bool drop_invalid $1 drop_invalid 0
210
211        [ "$drop_invalid" -gt 0 ] && {
212                $IPTABLES -A INPUT -m state --state INVALID -j DROP
213                $IPTABLES -A OUTPUT -m state --state INVALID -j DROP
214                $IPTABLES -A FORWARD -m state --state INVALID -j DROP
215                NOTRACK_DISABLED=1
216        }
217
218        $IPTABLES -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
219        $IPTABLES -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
220        $IPTABLES -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
221
222        $IPTABLES -A INPUT -i lo -j ACCEPT
223        $IPTABLES -A OUTPUT -o lo -j ACCEPT
224
225        config_get syn_flood $1 syn_flood
226        config_get syn_rate $1 syn_rate
227        config_get syn_burst $1 syn_burst
228        [ "$syn_flood" == "1" ] && load_synflood $syn_rate $syn_burst
229
230        echo "Adding custom chains"
231        fw_custom_chains
232
233        $IPTABLES -N input
234        $IPTABLES -N output
235        $IPTABLES -N forward
236
237        $IPTABLES -A INPUT -j input
238        $IPTABLES -A OUTPUT -j output
239        $IPTABLES -A FORWARD -j forward
240
241        $IPTABLES -N reject
242        $IPTABLES -A reject -p tcp -j REJECT --reject-with tcp-reset
243        $IPTABLES -A reject -j REJECT --reject-with icmp-port-unreachable
244
245        fw_set_chain_policy INPUT "$DEF_INPUT"
246        fw_set_chain_policy OUTPUT "$DEF_OUTPUT"
247        fw_set_chain_policy FORWARD "$DEF_FORWARD"
248}
249
250fw_zone_defaults() {
251        local name
252        local network
253        local masq
254
255        config_get name $1 name
256        config_get network $1 network
257        config_get_bool masq $1 masq "0"
258        config_get_bool conntrack $1 conntrack "0"
259        config_get_bool mtu_fix $1 mtu_fix 0
260
261        load_policy $1
262        [ "$forward" ] && $IPTABLES -A zone_${name}_forward -j zone_${name}_${forward}
263        [ "$input" ] && $IPTABLES -A zone_${name} -j zone_${name}_${input}
264}
265
266fw_zone() {
267        local name
268        local network
269        local masq
270
271        config_get name $1 name
272        config_get network $1 network
273        config_get_bool masq $1 masq "0"
274        config_get_bool conntrack $1 conntrack "0"
275        config_get_bool mtu_fix $1 mtu_fix 0
276
277        load_policy $1
278        [ "$conntrack" = "1" -o "$masq" = "1" ] && append CONNTRACK_ZONES "$name"
279        [ -z "$network" ] && network=$name
280        create_zone "$name" "$network" "$input" "$output" "$forward" "$masq" "$mtu_fix"
281        fw_custom_chains_zone "$name"
282}
283
284fw_rule() {
285        local src
286        local src_ip
287        local src_mac
288        local src_port
289        local src_mac
290        local dest
291        local dest_ip
292        local dest_port
293        local proto
294        local icmp_type
295        local target
296        local ruleset
297
298        config_get src $1 src
299        config_get src_ip $1 src_ip
300        config_get src_mac $1 src_mac
301        config_get src_port $1 src_port
302        config_get dest $1 dest
303        config_get dest_ip $1 dest_ip
304        config_get dest_port $1 dest_port
305        config_get proto $1 proto
306        config_get icmp_type $1 icmp_type
307        config_get target $1 target
308        config_get ruleset $1 ruleset
309
310        src_port_first=${src_port%-*}
311        src_port_last=${src_port#*-}
312        [ "$src_port_first" -ne "$src_port_last" ] && { \
313                src_port="$src_port_first:$src_port_last"; }
314
315        dest_port_first=${dest_port%-*}
316        dest_port_last=${dest_port#*-}
317        [ "$dest_port_first" -ne "$dest_port_last" ] && { \
318                dest_port="$dest_port_first:$dest_port_last"; }
319
320        ZONE=input
321        TARGET=$target
322        [ -z "$target" ] && target=DROP
323        [ -n "$src" -a -z "$dest" ] && ZONE=zone_$src
324        [ -n "$src" -a -n "$dest" ] && ZONE=zone_${src}_forward
325        [ -n "$dest" ] && TARGET=zone_${dest}_$target
326
327        eval 'RULE_COUNT=$((++RULE_COUNT_'$ZONE'))'
328
329        add_rule() {
330                $IPTABLES -I $ZONE $RULE_COUNT \
331                        ${proto:+-p $proto} \
332                        ${icmp_type:+--icmp-type $icmp_type} \
333                        ${src_ip:+-s $src_ip} \
334                        ${src_port:+--sport $src_port} \
335                        ${src_mac:+-m mac --mac-source $src_mac} \
336                        ${dest_ip:+-d $dest_ip} \
337                        ${dest_port:+--dport $dest_port} \
338                        -j $TARGET
339        }
340        [ "$proto" == "tcpudp" -o -z "$proto" ] && {
341                proto=tcp
342                add_rule
343                proto=udp
344                add_rule
345                return
346        }
347        add_rule
348}
349
350fw_forwarding() {
351        local src
352        local dest
353        local masq
354
355        config_get src $1 src
356        config_get dest $1 dest
357        [ -n "$src" ] && z_src=zone_${src}_forward || z_src=forward
358        [ -n "$dest" ] && z_dest=zone_${dest}_ACCEPT || z_dest=ACCEPT
359        $IPTABLES -I $z_src 1 -j $z_dest
360
361        # propagate masq zone flag
362        find_item "$src" $CONNTRACK_ZONES && append CONNTRACK_ZONES $dest
363        find_item "$dest" $CONNTRACK_ZONES && append CONNTRACK_ZONES $src
364}
365
366fw_redirect() {
367        local src
368        local src_ip
369        local src_port
370        local src_dport
371        local src_mac
372        local dest_ip
373        local dest_port dest_port2
374        local proto
375
376        config_get src $1 src
377        config_get src_ip $1 src_ip
378        config_get src_dip $1 src_dip
379        config_get src_port $1 src_port
380        config_get src_dport $1 src_dport
381        config_get src_mac $1 src_mac
382        config_get dest_ip $1 dest_ip
383        config_get dest_port $1 dest_port
384        config_get proto $1 proto
385        [ -z "$src" -o -z "$dest_ip$dest_port" ] && { \
386                echo "redirect needs src and dest_ip or dest_port"; return ; }
387
388        find_item "$src" $CONNTRACK_ZONES || \
389                append CONNTRACK_ZONES "$src"
390
391        src_port_first=${src_port%-*}
392        src_port_last=${src_port#*-}
393        [ "$src_port_first" != "$src_port_last" ] && { \
394                src_port="$src_port_first:$src_port_last"; }
395
396        src_dport_first=${src_dport%-*}
397        src_dport_last=${src_dport#*-}
398        [ "$src_dport_first" != "$src_dport_last" ] && { \
399                src_dport="$src_dport_first:$src_dport_last"; }
400
401        dest_port2=${dest_port:-$src_dport}
402        dest_port_first=${dest_port2%-*}
403        dest_port_last=${dest_port2#*-}
404        [ "$dest_port_first" != "$dest_port_last" ] && { \
405                dest_port2="$dest_port_first:$dest_port_last"; }
406
407        add_rule() {
408                $IPTABLES -A zone_${src}_prerouting -t nat \
409                        ${proto:+-p $proto} \
410                        ${src_ip:+-s $src_ip} \
411                        ${src_dip:+-d $src_dip} \
412                        ${src_port:+--sport $src_port} \
413                        ${src_dport:+--dport $src_dport} \
414                        ${src_mac:+-m mac --mac-source $src_mac} \
415                        -j DNAT --to-destination $dest_ip${dest_port:+:$dest_port}
416
417                [ -n "$dest_ip" ] && \
418                $IPTABLES -I zone_${src}_forward 1 \
419                        ${proto:+-p $proto} \
420                        -d $dest_ip \
421                        ${src_ip:+-s $src_ip} \
422                        ${src_port:+--sport $src_port} \
423                        ${dest_port2:+--dport $dest_port2} \
424                        ${src_mac:+-m mac --mac-source $src_mac} \
425                        -j ACCEPT
426        }
427
428        [ "$proto" == "tcpudp" -o -z "$proto" ] && {
429                proto=tcp
430                add_rule
431                proto=udp
432                add_rule
433                return
434        }
435        add_rule
436}
437
438fw_include() {
439        local path
440        config_get path $1 path
441        [ -e $path ] && . $path
442}
443
444get_interface_zones() {
445        local interface="$2"
446        local name
447        local network
448        local masq_src
449        local masq_dest
450        config_get name $1 name
451        config_get network $1 network
452        config_get masq_src $1 masq_src
453        config_get masq_dest $1 masq_dest
454        [ -z "$network" ] && network=$name 
455        for n in $network; do
456                [ "$n" = "$interface" ] && {
457                        append add_zone "$name"
458                        append add_masq_src "$masq_src"
459                        append add_masq_dest "$masq_dest"
460                }
461        done
462}
463
464fw_event() {
465        local action="$1"
466        local interface="$2"
467        local ifname="$(sh -c ". /etc/functions.sh; include /lib/network; scan_interfaces; config_get "$interface" ifname")"
468        local add_zone=
469        local add_masq_src=
470        local add_masq_dest=
471        local up
472
473        [ -z "$ifname" ] && return 0
474        config_foreach get_interface_zones zone "$interface"
475        [ -z "$add_zone" ] && return 0
476
477        case "$action" in
478                ifup)
479                        for z in $add_zone; do
480                                local loaded masq_src masq_dest
481                                config_get loaded core loaded
482                                [ -n "$loaded" ] && addif "$interface" "$ifname" "$z" "$add_masq_src" "$add_masq_dest"
483                        done
484                ;;
485                ifdown)
486                        config_get up "$interface" up
487
488                        for z in $ZONE; do
489                                local masq_src masq_dest
490                                config_get masq_src core "${z}_masq_src"
491                                config_get masq_dest core "${z}_masq_dest"
492                                [ "$up" == "1" ] && delif "$interface" "$ifname" "$z" "$masq_src" "$masq_dest"
493                        done
494                ;;
495        esac
496}
497
498fw_addif() {
499        local up
500        local ifname
501        config_get up $1 up
502        [ -n "$up" ] || return 0
503        fw_event ifup "$1"
504}
505
506fw_custom_chains() {
507        [ -n "$CUSTOM_CHAINS" ] || return 0
508        $IPTABLES -N input_rule
509        $IPTABLES -N output_rule
510        $IPTABLES -N forwarding_rule
511        $IPTABLES -N prerouting_rule -t nat
512        $IPTABLES -N postrouting_rule -t nat
513
514        $IPTABLES -A INPUT -j input_rule
515        $IPTABLES -A OUTPUT -j output_rule
516        $IPTABLES -A FORWARD -j forwarding_rule
517        $IPTABLES -A PREROUTING -t nat -j prerouting_rule
518        $IPTABLES -A POSTROUTING -t nat -j postrouting_rule
519}
520
521fw_custom_chains_zone() {
522        local zone="$1"
523
524        [ -n "$CUSTOM_CHAINS" ] || return 0
525        $IPTABLES -N input_${zone}
526        $IPTABLES -N forwarding_${zone}
527        $IPTABLES -N prerouting_${zone} -t nat
528        $IPTABLES -I zone_${zone} 1 -j input_${zone}
529        $IPTABLES -I zone_${zone}_forward 1 -j forwarding_${zone}
530        $IPTABLES -I zone_${zone}_prerouting 1 -t nat -j prerouting_${zone}
531}
532
533fw_check_notrack() {
534        local zone="$1"
535        config_get name "$zone" name
536        [ -n "$NOTRACK_DISABLED" ] || \
537                find_item "$name" $CONNTRACK_ZONES || \
538                $IPTABLES -t raw -A zone_${name}_notrack -j NOTRACK
539}
540
541fw_init() {
542        DEFAULTS_APPLIED=
543
544        echo "Loading defaults"
545        config_foreach fw_defaults defaults
546        echo "Loading zones"
547        config_foreach fw_zone zone
548        echo "Loading forwarding"
549        config_foreach fw_forwarding forwarding
550        echo "Loading redirects"
551        config_foreach fw_redirect redirect
552        echo "Loading rules"
553        config_foreach fw_rule rule
554        echo "Loading includes"
555        config_foreach fw_include include
556        echo "Loading zone defaults"
557        config_foreach fw_zone_defaults zone
558        uci_set_state firewall core loaded 1
559        config_set core loaded 1
560        config_foreach fw_check_notrack zone
561        INTERFACES="$(sh -c '
562                . /etc/functions.sh; config_load network
563                echo_up() { local up; config_get_bool up "$1" up 0; [ $up = 1 ] && echo "$1"; }
564                config_foreach echo_up interface
565        ')"
566        for interface in $INTERFACES; do
567                fw_event ifup "$interface"
568        done
569}
570
571fw_stop() {
572        fw_clear
573        $IPTABLES -P INPUT ACCEPT
574        $IPTABLES -P OUTPUT ACCEPT
575        $IPTABLES -P FORWARD ACCEPT
576        uci_revert_state firewall
577}
Note: See TracBrowser for help on using the repository browser.