ipt_recent_rcheck should be local too
[opensuse:susefirewall2.git] / SuSEfirewall2
1 #!/bin/bash
2 #
3 # SuSEfirewall2 - stateful packetfilter rules generator
4 # Copyright (C) 2000-2002 Marc Heuse <marc@suse.de>
5 # Copyright (C) 2003,2004 SUSE Linux AG
6 # Copyright (C) 2005 SUSE LINUX Products GmbH
7 #
8 # Author:     Marc Heuse
9 # Maintainer: Ludwig Nussel
10
11 # Please send feedback via http://www.suse.de/feedback
12 #
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
15 # version 2 as published by the Free Software Foundation.
16
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
26 #
27 # For all those fellow experts out there: yes I know that this is NOT a 
28 # firewall setup but a simple (no, not simple, it tries actually to be
29 # clever) packet filter. But if we would call this "SuSEpacketfilter",
30 # only a few user would install it, hence general security would be bad.
31 #
32 ###########################################################################
33 #                                                                         #
34 # The configuration file for this firewall script is                      #
35 # /etc/sysconfig/SuSEfirewall2                                            #
36 #                                                                         #
37 # Please make only modifications to this script if you know what you      #
38 # are doing! A small explanation of the setup can be found in             #
39 # /usr/share/doc/packages/SuSEfirewall2/README                            #
40 #                                                                         #
41 # For new-user help concerning configuring this firewall, take a look at  #
42 # the configuration file /etc/sysconfig/SuSEfirewall2 - it tells          #
43 # you all                                                                 #
44 # (if not: sorry, but configuring a packet filter/screening router is NOT #
45 # trivial - you must know what you are doing and what it actually does!)  #
46 #                                                                         #
47 ###########################################################################
48
49 help() {
50 cat <<EOF
51 SuSEfirewall2 3.4, Copyright (C) 2005  SUSE LINUX Products GmbH
52
53 stateful packet filter rules generator for iptables.
54
55 $0 start|test|debug [file FILENAME]
56 $0 basic|stop|close|status|help
57 $0 open ZONE TYPE services...
58 $0 on|off
59
60 Options:
61   start   generate and load the firewall filter rules from 
62           /etc/sysconfig/SuSEfirewall2
63   stop    unload all filter rules
64   close   no incoming network traffic except bootp+ping (for boot security)
65   basic   set basic filter rules that drop all incoming access
66   test    generate and load the filter rules but do not drop any packet but log
67           to syslog anything which *would* be denied
68   status  print the output of "iptables -nvL"
69   debug   print the iptables command to stdout instead of executing them
70   log     show SuSEfirewall2 related syslog messages in a better readable format
71   help    this output
72   open    open the specified services in the specified zone. You need to
73           restart SuSEfirewall2 for changes to take effect.
74   on      add SuSEfirwall2 initscripts to boot process and start
75   off     remove SuSEfirwall2 initscripts from boot process and stop
76
77   file FILENAME  same as "start" but load alternate config file FILENAME
78
79 Calling $0 without any option is the same as the "start" option.
80 The "file FILENAME" option may be used with the start, test and debug options.
81 EOF
82     exit 0
83 }
84
85 removefiles=()
86 declare -a  removefiles
87 removeonexit()
88 {
89     removefiles[${#removefiles[@]}]="$1"
90 }
91
92 cleanup()
93 {
94     local file
95     for file in "${removefiles[@]}"; do
96             rm -f "$file"
97     done
98 }
99 trap cleanup EXIT
100
101 quiet=''
102 syslog()
103 {
104     local pri="-p auth.err"
105     local dashs='-s'
106     if [ "$1" = '0' ]; then
107         pri="-p auth.info"
108         if [ -n "$quiet" ]; then
109             dashs=''
110         fi
111     elif [ "$1" = '-1' ]; then
112         pri="-p auth.warn"
113     fi
114     shift
115     /bin/logger $dashs $pri -t SuSEfirewall2 "$*"
116 }
117
118 message()
119 {
120     syslog 0 "$*"
121 }
122
123 warning()
124 {
125     syslog -1 "Warning:" "$*"
126 }
127
128 deprecated()
129 {
130     warning "$@ is deprecated and will likely be removed in the future."
131     warning "If you think it should be kept please report your use case at"
132     warning "http://forge.novell.com/modules/xfmod/project/?susefirewall2"
133 }
134
135 error()
136 {
137     syslog -2 "Error:" "$*"
138 }
139
140 die()
141 {
142     local ret=1
143     trap EXIT
144     cleanup
145     case "$1" in
146         [0-9]) ret="$1"; shift ;;
147     esac
148     [ -n "$*" ] && syslog "$ret" "$*"
149     exit $ret
150 }
151
152 need()
153 {
154     . "$SCRIPTSDIR/SuSEfirewall2-$1"
155 }
156
157 CONFIGURATIONSDIR="/usr/share/SuSEfirewall2/services"
158 SCRIPTSDIR="/etc/sysconfig/scripts"
159 FWCONFIG="/etc/sysconfig/SuSEfirewall2"
160 LOCKFILE="/var/lock/SuSEfirewall2.pid"
161 BOOTLOCKFILE="/var/lock/SuSEfirewall2.booting"
162 FW_CUSTOMRULES=""
163
164 USE_IPTABLES_BATCH=''
165
166 # whether ip6tables supports state matching
167 IP6TABLES_HAVE_STATE=1
168
169 # whether ip6tables support REJECT
170 IP6TABLES_HAVE_REJECT=1
171
172 ACTION="start"
173 MODE="standard"
174 INITSCRIPTS="" # on|off
175 needconfig=
176 needlock=1
177 create_bootlock=0
178
179 # prevent double log entries when called from ip-up
180 if test -x /usr/bin/tty && ! /usr/bin/tty -s; then
181     quiet=1
182 fi
183
184 getopttmp=`/usr/bin/getopt -o hq --long help,scriptsdir:,batch,nobatch,file:,debug,test,bootlock,quiet \
185      -n 'SuSEfirewall2' -- "$@"`
186
187 [ $? != 0 ] && die 1 "getopt error"
188
189 eval set -- "$getopttmp"
190
191 while true ; do
192         case "$1" in
193                 --file) FWCONFIG="$2"; shift 2 ;;
194                 --batch) USE_IPTABLES_BATCH='yes'; shift ;;
195                 --nobatch) USE_IPTABLES_BATCH='no'; shift ;;
196                 --scriptsdir) SCRIPTSDIR="$2" ; shift 2 ;;
197                 --test) MODE="test" ; shift ;;
198                 --debug) MODE="debug"; needlock=0 ; shift ;;
199                 --bootlock) create_bootlock=1 ; shift ;;
200                 -h|--help) help ; shift ;;
201                 -q|--quiet) quiet=1 ; shift ;;
202                 --) shift ; break ;;
203                 *) die 1 "getopt error"; ;;
204         esac
205 done
206
207 case "$1" in
208     start|"") needconfig=1 ;;
209     test) MODE="test" ;;
210     debug) MODE="debug"; needlock=0 ;;
211     easy|novice|basic) ACTION="basic" ;;
212     stop|halt|down|shutdown) ACTION="stop"; needconfig=1 ;;
213     close) ACTION="close" ;;
214     status) ACTION="status"; USE_IPTABLES_BATCH='no'; needlock=0 ;;
215     open) ACTION="open"; needlock=0 ;;
216     log) ACTION="showlog" ;;
217     help) help ;;
218     off) ACTION="stop"; needconfig=1; INITSCRIPTS="off" ;;
219     on) ACTION="start"; needconfig=1; INITSCRIPTS="on" ;;
220     *) help ;;
221 esac
222 shift
223
224 case "$ACTION" in
225     start|stop)
226         while [ $# -gt 0 ]; do
227             case "$1" in
228                 file) FWCONFIG="$2"; shift 2 ;;
229                 force|batch) shift ;;  # unused, for compatability
230                 *) echo "invalid option: $1"; exit 1 ;;
231             esac
232         done
233         ;;
234 esac
235
236 test -e /etc/sysconfig/network/config && . /etc/sysconfig/network/config
237
238 if [ -r "$FWCONFIG" ]; then
239     . "$FWCONFIG"
240 elif [ -n "$needconfig" ]; then
241     die 6 " Can not read $FWCONFIG"
242 fi
243
244 if [ -z "$USE_IPTABLES_BATCH" ]; then
245     case "$FW_USE_IPTABLES_BATCH" in
246         no) USE_IPTABLES_BATCH='' ;;
247         yes) USE_IPTABLES_BATCH='yes' ;;
248         ''|auto) USE_IPTABLES_BATCH='auto' ;;
249     esac
250 fi
251
252 if [ -n "$USE_IPTABLES_BATCH" -a "$USE_IPTABLES_BATCH" != 'no' ]; then
253     need batch
254     check_iptables_batch
255 fi
256
257 [ "$USE_IPTABLES_BATCH" = 'no' ] && USE_IPTABLES_BATCH=''
258
259 ### Definitions - fixed
260 unset ${!LC_*} ${!RC_LC_*} LANGUAGE RC_LANG
261 export LANG=en_US
262
263 export PATH="/sbin:/bin:/usr/sbin:/usr/bin"
264
265 modinfo="/sbin/modinfo"
266 TC="/usr/sbin/tc"
267 IPTABLES_BIN="/usr/sbin/iptables"
268 IP6TABLES_BIN="/usr/sbin/ip6tables"
269 if [ "$MODE" = debug ]; then
270     IPTABLES="iptables"
271     iptables()
272     {
273         echo iptables "$@"
274     }
275     IP6TABLES="ip6tables"
276     ip6tables()
277     {
278         echo ip6tables "$@"
279     }
280     TC="tc"
281     tc()
282     {
283         echo tc "$@"
284     }
285     modprobe()
286     {
287         echo modprobe "$@"
288     }
289 else
290     IPTABLES="$IPTABLES_BIN"
291     IP6TABLES="$IP6TABLES_BIN"
292
293     ### ipv6 checks
294     case "$FW_IPv6" in
295             drop|reject) IP6TABLES_HAVE_STATE=0 ;;
296             no) IP6TABLES=":" ;;
297             *) FW_IPv6="" ;;
298     esac
299
300
301     if [ "$IP6TABLES" != ':' ]; then
302         # Do we have a kernel with IPv6 enabled?
303         $IP6TABLES -nvL >/dev/null 2>&1 || IP6TABLES=:
304         if ! [ -e /proc/net/stat/nf_conntrack ] || ! $IP6TABLES -m state --help >/dev/null 2>&1 || \
305         ( ! $modinfo ip6t_state >/dev/null 2>&1 && ! $modinfo xt_state >/dev/null 2>&1); then
306             warning "ip6tables does not support state matching. Extended IPv6 support disabled."
307             IP6TABLES_HAVE_STATE=0
308             # reject incoming packets if not specified otherwise
309             [ "$FW_IPv6" != 'no' -a "$FW_IPv6" != 'drop' ] && FW_IPv6='reject'
310         fi
311
312         $modinfo ip6t_REJECT >/dev/null 2>&1 || IP6TABLES_HAVE_REJECT=0
313
314         if [ \( "$FW_REJECT" = "yes" -o "$FW_IPv6" = "reject" \) \
315                 -a "$IP6TABLES_HAVE_REJECT" != 1 ]; then
316                 warning "Kernel lacks support for IPv6 REJECT target! Using DROP for IPv6 instead."
317         fi
318     fi
319     ####
320
321     if [ -n "$USE_IPTABLES_BATCH" ]; then
322         IPTABLES=iptables
323         [ "$IP6TABLES" != ":" ] && IP6TABLES=ip6tables
324     fi
325 fi
326 AWK="/bin/awk"
327 SED="/bin/sed"
328 IFCONFIG="/sbin/ifconfig"
329 NETSTAT="/bin/netstat"
330 SORT="/bin/sort"
331 GREP="/bin/grep"
332 PERL="/usr/bin/perl"
333
334 for i in "$GREP" "$AWK" "$SED" "$IFCONFIG" "$NETSTAT" "$SORT"; do
335     if [ ! -x "$i" ]; then
336         die 1 "$i is required for SuSEfirewall2 but it is not an executable"
337     fi
338 done
339
340 ### jump targets
341 ACCEPT="ACCEPT"
342 DROP="DROP"
343 REJECT="reject_func"
344 [ "$FW_REJECT" = yes ] && DROP="reject_func"
345
346 # fwmarks
347
348 mark_redir=1
349
350 # ipsec
351
352 ipsec_chain=""
353 IPSEC_INPUT_MATCH="-m policy --dir in --pol ipsec --proto esp"
354 IPSEC_OUTPUT_MATCH="-m policy --dir out --pol ipsec --proto esp"
355
356 ### zones
357
358 all_zones="int ext dmz"
359 forward_zones=
360 input_zones=
361
362 #### constants
363
364 safe_icmp_replies="echo-reply destination-unreachable time-exceeded parameter-problem timestamp-reply address-mask-reply protocol-unreachable redirect"
365 safe_icmpv6_replies="echo-reply destination-unreachable packet-too-big time-exceeded parameter-problem"
366 stateless_icmpv6_types="router-solicitation router-advertisement neighbour-solicitation neighbour-advertisement redirect"
367
368 ###############
369
370 parse_logging()
371 {
372     if [ -z "$FW_LOG_LIMIT" ]; then
373         FW_LOG_LIMIT="-m limit --limit 3/minute"
374     elif [ "$FW_LOG_LIMIT" = 'no' ]; then
375         FW_LOG_LIMIT=''
376     else
377         FW_LOG_LIMIT="-m limit --limit $FW_LOG_LIMIT"
378     fi
379
380     ### logging setup
381     if [ -z "$FW_LOG" ]; then
382         LOG='--log-level warning --log-tcp-options --log-ip-options --log-prefix SFW2'
383     else
384         LOG="$FW_LOG"
385     fi
386
387     case "$LOG" in
388         -j\ *) ;;
389         *) LOG="-j LOG $LOG" ;;
390     esac
391
392     LDC=''  # log drop critical
393     LDA=''  # log drop all
394     LDAC='' # log drop all or critical
395     LAC=''  # log accept critical
396     LAA=''  # log accept all
397     LAAC='' # log accept all or critical
398
399     # 'critical' will be unset if 'all' is set since 'critical' might be a special case of 'all'.
400     if [ "$FW_LOG_DROP_ALL" != yes ]; then
401         LDA=":"
402         if [ "$FW_LOG_DROP_CRIT" = no ]; then
403             LDC=":"
404             LDAC=":"
405         fi
406     else
407         LDC=':'
408     fi
409
410     if [ "$FW_LOG_ACCEPT_ALL" != yes ]; then
411         LAA=":"
412         if [ "$FW_LOG_ACCEPT_CRIT" = no ]; then
413             LAC=":"
414             LAAC=":"
415         fi
416     else 
417         LAC=':'
418     fi
419
420     [ "$LAA" = ':' ] && LOG="$FW_LOG_LIMIT $LOG"
421 }
422
423 ### Functions
424 function setproc()
425 {
426     [ -z "$2" -o ! -w "$2" ] && return
427     if [ "$MODE" != "debug" ]; then
428         echo "$1" > "$2"
429     else
430         echo "echo \"$1\" > \"$2\""
431     fi
432 }
433
434 # parameters: protocol port variable
435 # check whether $1 and $2/$3 are a valid protocol/port combination and sets global
436 # variables $proto, $port ($rport) and $sport ($rsport) in iptables syntax
437 # $4 is used for logging
438 # returns 1 on error, the content of $proto and $port is undefined then
439 check_proto_port()
440 {
441     proto="$1"
442     port="$2"
443     sport="$3"
444     local var="$4"
445     case "$proto" in
446         '')   error "proto must not be empty in ${var}"; return 1; ;;
447         _rpc_) # cannot check ports here
448             ;;
449         tcp|udp)
450             if [ -n "$port" ]; then
451                 rport="--sport $port"
452                 port="--dport $port"
453             else
454                 port=''
455                 rport=''
456             fi
457             if [ -n "$sport" ]; then
458                 rsport="--dport $sport"
459                 sport="--sport $sport"
460             else
461                 sport=''
462                 rsport=''
463             fi
464
465             ;;
466         icmp)
467             if [ -n "$port" ]; then
468                 port="--icmp-type $port"
469                 rport="$port"
470             else
471                 port=''
472                 rport=''
473             fi
474             if [ -n "$sport" ]; then
475                 sport="--icmp-type $sport"
476                 rsport="$sport"
477             else
478                 sport=''
479                 rsport=''
480             fi
481         ;;
482         *)
483             if [ -n "$port" ]; then
484                 error "port is only valid with tcp, udp or icmp in ${var}"
485                 return 1
486             fi
487         ;;
488     esac
489     proto="-p $proto"
490     return 0
491 }
492
493 function reset_rules_silent() {
494     if [ "$FW_STOP_KEEP_ROUTING_STATE" != "yes" ]; then
495         setproc 0 /proc/sys/net/ipv4/ip_forward
496     fi
497     $IPTABLES -F INPUT
498     $IPTABLES -F OUTPUT
499     $IPTABLES -F FORWARD
500     $IPTABLES -P INPUT ACCEPT
501     $IPTABLES -P OUTPUT ACCEPT
502     $IPTABLES -P FORWARD ACCEPT
503     $IPTABLES -F
504     $IPTABLES -X
505     $IPTABLES -t nat -F
506     $IPTABLES -t nat -X
507     $IPTABLES -t mangle -F
508     $IPTABLES -t mangle -X
509
510     $IP6TABLES -F INPUT
511     $IP6TABLES -F OUTPUT
512     $IP6TABLES -F FORWARD
513     $IP6TABLES -P INPUT ACCEPT
514     $IP6TABLES -P OUTPUT ACCEPT
515     $IP6TABLES -P FORWARD ACCEPT
516     $IP6TABLES -F
517     $IP6TABLES -X
518     $IP6TABLES -t mangle -F
519     $IP6TABLES -t mangle -X
520 }
521
522 clear_qdisc_settings() {
523     local data
524     local dev
525     local bandwidth
526     for data in $FW_HTB_TUNE_DEV; do
527         IFS="," read dev bandwidth < <(echo "$data")
528         $TC qdisc del dev $dev root 2> /dev/null
529     done
530 }
531
532 function reset_rules() {
533         reset_rules_silent
534         clear_qdisc_settings
535 }
536
537 function load_modules()
538 {
539     local i
540     for i in "$@"; do
541         modprobe "$i"
542     done
543 }
544
545 function rulelog()
546 {
547     rule=$1
548     case $rule in
549         input_*)
550                 echo IN${rule#input_}
551                 ;;
552         forward_*)
553                 echo FWD${rule#forward_}
554                 ;;
555     esac        
556 }
557
558
559 function allow_basic_related()
560 {
561     # needed for dhcp and dns replies
562     local iptables
563     for iptables in "$IPTABLES" "$IP6TABLES"; do
564             $LAA $iptables -A INPUT ${LOG}"-IN-ACC-RELATED " -m state --state ESTABLISHED,RELATED
565             $iptables -A INPUT -j "$ACCEPT" -m state --state ESTABLISHED,RELATED
566
567             # if two hosts have a tcp connection on fixed ports and
568             # one of the hosts crashes it will send a SYN to the
569             # peer if it comes back up. The peer sends back ACK as
570             # it thinks there is already a connection established.
571             # This ACK is INVALID and must be answered with RST
572             # otherwise long timeouts may occur (#46818).
573 #           $LDA $iptables -A INPUT ${LOG}"-IN-REJECT-ACK " -m state --state INVALID -p tcp --tcp-flags SYN,RST,ACK ACK
574 #           $iptables -A INPUT -j "$REJECT" -m state --state INVALID -p tcp --tcp-flags SYN,RST,ACK ACK
575     done
576 }
577
578 xen_forward_hack()
579 {
580     local dev iptables
581     for iptables in "$IPTABLES" "$IP6TABLES"; do
582         for dev in $FW_FORWARD_ALWAYS_INOUT_DEV; do
583             $iptables -A FORWARD -i $dev -o $dev -j ACCEPT
584         done
585     done
586 }
587
588 function set_basic_rules()
589 {
590     load_modules ip_tables ip_conntrack $FW_LOAD_MODULES
591
592     if [ "$FW_IPv6" != no ]; then
593         load_modules ip6table_filter ip6table_mangle
594     fi
595     
596     # determine policy
597     local DROP_JUMP
598     if [ "$DROP" = "ACCEPT" ]; then
599         DROP_JUMP="ACCEPT"
600     else
601         DROP_JUMP="DROP"
602     fi
603     $IPTABLES -F INPUT
604     $IPTABLES -F OUTPUT
605     $IPTABLES -F FORWARD
606     $IPTABLES -P INPUT "$DROP_JUMP"
607     $IPTABLES -P OUTPUT ACCEPT
608     $IPTABLES -P FORWARD "$DROP_JUMP"
609     $IPTABLES -F
610     $IPTABLES -X
611     # Special REJECT function #
612     $IPTABLES -t nat -F
613     $IPTABLES -t nat -X
614     $IPTABLES -t mangle -F
615     $IPTABLES -t mangle -X
616     $IPTABLES -N reject_func
617     $IPTABLES -A reject_func -p tcp -j REJECT --reject-with tcp-reset
618     $IPTABLES -A reject_func -p udp -j REJECT --reject-with icmp-port-unreachable
619     $IPTABLES -A reject_func        -j REJECT --reject-with icmp-proto-unreachable
620
621     # loopback is always allowed
622     $IPTABLES -A INPUT  -j "$ACCEPT" -i lo
623     $IPTABLES -A OUTPUT -j "$ACCEPT" -o lo
624
625     $IP6TABLES -F INPUT
626     $IP6TABLES -F OUTPUT
627     $IP6TABLES -F FORWARD
628     $IP6TABLES -P INPUT "$DROP_JUMP"
629     $IP6TABLES -P OUTPUT ACCEPT
630     $IP6TABLES -P FORWARD "$DROP_JUMP"
631     $IP6TABLES -F
632     $IP6TABLES -X
633     # Special REJECT function #
634     $IP6TABLES -t mangle -F
635     $IP6TABLES -t mangle -X
636     $IP6TABLES -N reject_func
637     if [ "$IP6TABLES_HAVE_REJECT" = 1 ]; then
638         $IP6TABLES -A reject_func -p tcp -j REJECT --reject-with tcp-reset
639         $IP6TABLES -A reject_func -p udp -j REJECT --reject-with port-unreach
640         $IP6TABLES -A reject_func        -j REJECT --reject-with addr-unreach # know anything better?
641     fi
642     # sometimes the above lines do not work despite prior checks, so add drop
643     # always to be on the safe side
644     $IP6TABLES -A reject_func -j DROP
645
646     # loopback is always allowed
647     $IP6TABLES -A INPUT  -j "$ACCEPT" -i lo
648     $IP6TABLES -A OUTPUT -j "$ACCEPT" -o lo
649
650     xen_forward_hack
651
652     # workaround for ip6tables without state matching
653     if [ "$IP6TABLES_HAVE_STATE" != 1 ]; then
654         for itype in $stateless_icmpv6_types $safe_icmpv6_replies; do
655             $LAA $IP6TABLES -A INPUT ${LOG}"-IN-ACC-ICMP " -p icmpv6 --icmpv6-type $itype
656             $IP6TABLES -A INPUT -j "$ACCEPT" -p icmpv6 --icmpv6-type $itype
657         done
658         if [ "$FW_ALLOW_PING_FW" = yes ]; then
659             $LAA $IP6TABLES -A INPUT ${LOG}"-`rulelog $chain`-ACC-PING "  -p icmpv6 --icmpv6-type echo-request
660             $IP6TABLES -A INPUT -j "$ACCEPT" -p icmpv6 --icmpv6-type echo-request
661         fi
662         $LAA $IP6TABLES -A INPUT -p tcp --tcp-flags ACK ACK ${LOG}"-IN-ACC-TCP "
663         $IP6TABLES -A INPUT -p tcp --tcp-flags ACK ACK -j "$ACCEPT"
664         # Drop all until IPv6 is really supported
665         $LDA $IP6TABLES -A INPUT ${LOG}"-IN-IPv6_PROHIB "
666         if [ "$FW_IPv6" = "drop" -o "$IP6TABLES_HAVE_REJECT" != 1 ]; then
667             $IP6TABLES -A INPUT -j "$DROP"
668         else
669             $IP6TABLES -A INPUT -j "$REJECT"
670         fi
671         $IP6TABLES -A OUTPUT -p icmpv6 -j "$ACCEPT"
672         $IP6TABLES -A OUTPUT -p tcp -j "$ACCEPT"
673         if [ "$IP6TABLES_HAVE_REJECT" != 1 -o "$FW_IPv6_REJECT_OUTGOING" = "no" ]; then
674             $IP6TABLES -A OUTPUT -j "$DROP"
675         else
676             $IP6TABLES -A OUTPUT -j "$REJECT"
677         fi
678         IP6TABLES=":" # disable further rules
679     fi
680
681     allow_basic_related
682
683     # make sure basic rules get committed even if there are errors later
684     [ -n "$USE_IPTABLES_BATCH" ] && iptables_batch_commitpoint
685 }
686
687 handle_initscripts()
688 {
689     local i
690     case "$INITSCRIPTS" in
691         on)
692             for i in SuSEfirewall2_init SuSEfirewall2_setup; do
693                 /sbin/insserv -f $i
694             done
695             ;;
696         off)
697             for i in SuSEfirewall2_setup SuSEfirewall2_init; do
698                 /sbin/insserv -r -f $i
699             done
700             ;;
701     esac
702 }
703
704 # set $ip and $net to list of ips and ip/prefix separated by space. set $dev to actual name of device
705 getdevinfo()
706 {
707     local dev=`getcfg-interface "$1"`
708
709     if [ "$?" -ne 0 -o -z "$dev" \
710         -o  \( ! -e /proc/sys/net/ipv4/conf/"$dev" \
711         -a ! -e /proc/sys/net/ipv6/conf/"$dev" \)  ]; then
712         return 1
713     fi
714
715     echo "$dev"
716     return 0
717 }
718
719 # find interface name for hardware description
720 function getcfg-interface()
721 {
722     if [ -x /sbin/getcfg-interface ]; then
723         /sbin/getcfg-interface "$1" || echo "$1"
724     else
725         echo "$1"
726     fi
727 }
728
729
730 auto_detect_done=0
731 auto_detect_interfaces()
732 {
733     [ "$auto_detect_done" = 1 ] && return
734     local zone
735     while read line; do
736         set -- $line
737         zone="$1"
738         shift
739         case "$zone" in
740             External:)
741                 FW_DEV_EXT_AUTO="$*"
742             ;;
743             Internal:)
744                 FW_DEV_INT_AUTO="$*"
745             ;;
746         esac
747     done < <(/bin/bash $SCRIPTSDIR/SuSEfirewall2-autointerface.sh)
748     auto_detect_done=1
749 }
750
751 # auto interface detection
752 auto_detect_all_interfaces()
753 {
754     if [ "$FW_DEV_EXT" = "auto" ]; then
755         auto_detect_interfaces
756         FW_DEV_EXT="$FW_DEV_EXT_AUTO"
757     fi
758
759     if [ "$FW_DEV_INT" = "auto" ]; then
760         auto_detect_interfaces
761         FW_DEV_INT="$FW_DEV_INT_AUTO"
762     fi
763
764     if [ "$FW_MASQ_DEV" = "auto" ]; then
765         FW_MASQ_DEV="$FW_DEV_EXT"
766     fi
767 }
768
769 setlock()
770 {
771     ### Locking mechanism
772     if [ "$needlock" -ne 0 ]; then
773         if [ -e "$BOOTLOCKFILE" ]; then
774             die 0 "$BOOTLOCKFILE exists which means system boot in progress, exit." 
775         fi
776         if [ -e "$LOCKFILE" ]; then
777             read PID < $LOCKFILE
778             message "Another SuSEfirewall2 with PID $PID found, waiting ..."
779             i=0
780             while [ -e "$LOCKFILE" -a "$i" -lt 15 ]; do
781                 sleep 2
782                 i=$(( i + 1 ))
783             done
784             if [ -e "$LOCKFILE" ]; then
785                 message "Lockfile is still there, ignoring it ..."
786                 kill -TERM $PID
787                 sleep 2
788                 kill -KILL $PID
789                 rm -f "$LOCKFILE"
790             fi
791         fi
792         removeonexit "$LOCKFILE"
793         set -o noclobber
794         echo "$$" > $LOCKFILE || exit 1
795         if [ "$create_bootlock" -eq 1 ]; then
796             touch "$BOOTLOCKFILE"
797         fi
798         set +o noclobber
799     fi
800 }
801
802 ##
803 ## function definitions for full featured mode
804 ##
805
806 # Provide empty functions for transparent hook support for customised rules
807 fw_custom_before_antispoofing() { true; }
808 fw_custom_after_antispoofing() { true; }
809 fw_custom_before_port_handling() { true; }
810 fw_custom_before_masq() { true; }
811 fw_custom_before_denyall() { true; }
812
813 evaluateinterfaces()
814 {
815     local devs=""
816     local dev_any=""
817     local dev
818     for dev in "$@" ; do
819         if [ "$dev" = 'any' ]; then
820             dev_any='any'
821             continue
822         fi
823         dev=`getdevinfo "$dev"` || continue
824         case "$dev" in *:*) continue; ;; esac
825
826         devs="$devs $dev"
827     done
828     echo $dev_any $devs
829 }
830
831 parse_interfaces()
832 {
833     local zone devs var
834
835     for zone in $all_zones; do
836         eval devs="\$FW_DEV_`cibiz $zone`"
837         set -- `evaluateinterfaces $devs`
838         if [ "$1" = 'any' ]; then
839             eval DEV_${zone}_ANY="yes"
840             shift
841         fi
842         eval FW_DEV_$zone="\"$*\""
843     done
844
845     set -- `evaluateinterfaces $FW_MASQ_DEV`
846     [ "$1" = 'any' ] && shift
847     FW_MASQ_DEV="$*"
848
849 }
850
851 load_customrules()
852 {
853     ### Load custom rules
854     if [ -n "$FW_CUSTOMRULES" ]; then
855         if [ ! -r "$FW_CUSTOMRULES" ]; then
856             die 1 "Firewall customary rules file can not be read from $FW_CUSTOMRULES"
857         fi
858         . "$FW_CUSTOMRULES"
859         message "Firewall customary rules loaded from $FW_CUSTOMRULES"
860     fi
861 }
862
863 check_interfaces()
864 {
865     local v
866     for zone in $all_zones; do
867         eval v="\$FW_DEV_$zone"
868         [ -n "$v" ] && return
869     done
870     warning 'no interface active'
871 }
872
873 verify_parameters()
874 {
875     if [ "$FW_ROUTE" = no ]; then
876         if [ "$FW_MASQUERADE" = yes ]; then
877             warning 'FW_ROUTE needs to be set to yes for masquerading to work!'
878         fi
879         if [ "$FW_ALLOW_CLASS_ROUTING" = yes ]; then
880             warning 'FW_ROUTE needs to be set to yes for FW_ALLOW_CLASS_ROUTING to work!'
881         fi
882         if [ "$FW_ALLOW_PING_DMZ" = yes -o "$FW_ALLOW_PING_EXT" = yes ]; then
883             warning 'FW_ROUTE needs to be set to yes for FW_ALLOW_PING_EXT and/or FW_ALLOW_PING_DMZ to work!'
884         fi
885     fi
886
887     if [ "$FW_MASQUERADE" = no ]; then
888         [ -n "$FW_MASQ_NETS" -a "$FW_MASQ_NETS" != "0/0" ] && warning 'FW_MASQ_NETS needs FW_MASQUERADE set to yes to work!'
889         [ -n "$FW_FORWARD_MASQ" ] && warning 'FW_FORWARD_MASQ needs FW_MASQUERADE set to yes to work!'
890     fi
891 }
892
893 # Turn ip forwarding on if configured
894 switch_on_ip_forwarding()
895 {
896     if [ "$FW_ROUTE" = yes ]; then
897         setproc 1 /proc/sys/net/ipv4/ip_forward
898     else
899         setproc 0 /proc/sys/net/ipv4/ip_forward
900     fi
901 }
902
903 # warn user if device to masquerade is  from a non private network
904 # 0/0 has to be skipped here, otherwise the spoof rules would block
905 # anything
906 verify_masq_nets()
907 {
908     local nets net1
909     for nets in $FW_MASQ_NETS ; do
910         IFS=, eval set -- \$nets
911         net1="$1"
912
913         # skip 0/0
914         test "$net1" = "0/0" && continue
915
916         IFS=/ eval set -- \$net1
917
918         [ -z "$2" ] && continue
919
920         case "$1" in
921             10.*|172.1[6789].*|172.2[0-9].*|172.3[01].*|192.168.*) ;;
922             *) warning "The network $net1 you want to masquerade is not from a private network " \
923                     'like 10.0.0.0/8, 172.16.0.0/12 or 192.168.0.0/16'
924         esac
925     done
926 }
927
928 #################################
929 # Configuring more kernel stuff #
930 #################################
931 set_proc_stuff()
932 {
933     if [ "$FW_KERNEL_SECURITY" != no ]; then
934         setproc 1 /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts 
935 # test "$FW_ALLOW_PING_FW" = yes || setproc 1 /proc/sys/net/ipv4/icmp_echo_ignore_all  # XXX
936         setproc 1 /proc/sys/net/ipv4/ip_always_defrag  # XXX not there?
937         setproc 1 /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses 
938         setproc 5 /proc/sys/net/ipv4/icmp_echoreply_rate 
939         setproc 5 /proc/sys/net/ipv4/icmp_destunreach_rate 
940         setproc 5 /proc/sys/net/ipv4/icmp_paramprob_rate 
941         setproc 6 /proc/sys/net/ipv4/icmp_timeexceed_rate 
942         setproc 20 /proc/sys/net/ipv4/ipfrag_time 
943         setproc "1024 29999" /proc/sys/net/ipv4/ip_local_port_range 
944         for i in /proc/sys/net/ipv4/conf/*; do
945             setproc 1 $i/log_martians 
946             setproc 0 $i/bootp_relay 
947             [ "$FW_ROUTE" != yes ] && setproc 0 $i/forwarding
948             setproc 0 $i/proxy_arp 
949             setproc 1 $i/secure_redirects 
950             #setproc 0 $i/accept_redirects # let kernel decide this
951             setproc 0 $i/accept_source_route 
952             setproc 1 $i/rp_filter 
953         done
954         setproc 1 /proc/sys/net/ipv4/route/flush
955     fi
956 }
957
958 # Make input/forward chains
959 create_chains()
960 {
961     local iptables
962     for iptables in "$IPTABLES" "$IP6TABLES"; do
963         for TARGET in input forward; do
964             for CHAIN in $all_zones; do
965                 $iptables -N ${TARGET}_${CHAIN}
966             done
967         done
968     done
969 }
970
971 ### configurations ###
972
973 parse_configurations()
974 {
975     local var zone configurations config
976
977     for zone in $input_zones; do
978         var="FW_CONFIGURATIONS_`cibiz $zone`"
979         eval configurations="\"\$$var\""
980
981         for config in $configurations; do
982             local TCP=''
983             local UDP=''
984             local RPC=''
985             local IP=''
986             local BROADCAST=''
987
988             # XXX: could use a sub shell in order to enforce use of known variables only
989             if ! . $CONFIGURATIONSDIR/$config; then
990                 warning "config '$config' not available"
991                 continue
992             fi
993
994             for var in TCP UDP RPC IP; do
995                 eval [ -n \"\$$var\" ] \&\& FW_SERVICES_`cibiz $zone`_$var="\"\$FW_SERVICES_`cibiz $zone`_$var \$$var\""
996             done
997
998             if [ -n "$BROADCAST" ]; then
999                 var=FW_ALLOW_FW_BROADCAST_`cibiz $zone`
1000                 eval allow="\"\$$var\""
1001                 if [ "$allow" != 'yes' ]; then
1002                     # 'no' is ignored later anyways
1003                     eval $var="\"\$$var \$BROADCAST\""
1004                 fi
1005             fi
1006         done
1007     done
1008 }
1009
1010 ### handling of broadcasts ###
1011
1012 check_convert_old_broadcast()
1013 {
1014     if [ -n "$FW_ALLOW_FW_BROADCAST" -o -n "$FW_IGNORE_FW_BROADCAST" ]; then
1015         need oldbroadcast
1016         convert_old_broadcast
1017     fi
1018 }
1019
1020 drop_broadcast()
1021 {
1022     local allow ignore port zone
1023
1024     for zone in $input_zones; do
1025         eval allow="\$FW_ALLOW_FW_BROADCAST_`cibiz $zone`"
1026         eval ignore="\$FW_IGNORE_FW_BROADCAST_`cibiz $zone`"
1027
1028         [ "$allow" = yes ] && continue
1029         
1030         local match="-A input_$zone -m pkttype --pkt-type broadcast"
1031
1032         for port in $allow; do
1033             [ $port = no ] && continue
1034             $LAA $IPTABLES $match -p udp --dport $port ${LOG}"-ACC-BCAST${zone:0:1} "
1035             $IPTABLES $match -p udp --dport $port -j "$ACCEPT"
1036         done
1037
1038         if [ "$ignore" != yes ]; then
1039             for port in $ignore; do
1040                 [ $port = no ] && continue
1041                 $IPTABLES $match -p udp --dport $port -j DROP
1042             done
1043
1044             $LDA $IPTABLES $match ${LOG}"-DROP-BCAST${zone:0:1} "
1045         fi
1046
1047         $IPTABLES $match -j DROP # no need to send icmp for broadcasts
1048     done
1049 }
1050
1051 ### zones ###
1052
1053 parse_zones()
1054 {
1055     local zone
1056     for zone in $FW_ZONES; do
1057         case $zone in
1058             [Ii][Nn][Tt]|[Ee][Xx][Tt]|[Dd][Mm][Zz])
1059                 error "FW_ZONES=$zone ignored" ;;
1060             *) all_zones="$all_zones $zone" ;;
1061         esac
1062     done
1063 }
1064
1065 remove_unused_zones()
1066 {
1067     local zone zones devs any
1068     for zone in $all_zones; do
1069         eval devs="\$FW_DEV_$zone"
1070         eval any="\$DEV_${zone}_ANY"
1071         if [ -n "$devs" -o "$ipsec_chain" = $zone -o "$any" = 'yes' ]; then
1072             if [ -z "$zones" ]; then
1073                 zones=$zone
1074             else
1075                 zones="$zones $zone"
1076             fi
1077         fi
1078     done
1079
1080     [ "$all_zones" != "$zones" ] && all_zones="$zones"
1081 }
1082
1083 create_zones_hash()
1084 {
1085     local zone
1086     need bashhash
1087     for zone in $all_zones; do
1088         hashadd zones $zone 1
1089     done
1090 }
1091
1092 # convert if built in zone, eg ext -> EXT
1093 cibiz()
1094 {
1095     case $1 in
1096         int) echo INT ;;
1097         ext) echo EXT ;;
1098         dmz) echo DMZ ;;
1099         *)   echo "$1" ;;
1100     esac
1101 }
1102
1103 ### IPsec ###
1104
1105 parse_ipsec()
1106 {
1107     if [ "$FW_IPSEC_TRUST" = yes ]; then
1108         ipsec_chain="int"
1109     elif [ "$FW_IPSEC_TRUST" = no ]; then
1110         :
1111     elif [ -n "$FW_IPSEC_TRUST" ]; then
1112         for zone in $all_zones; do
1113             if [ "$FW_IPSEC_TRUST" = "$zone" ]; then
1114                 ipsec_chain="$zone"
1115                 break;
1116             fi
1117         done
1118         if [ -z "$ipsec_chain" ]; then
1119             warning "FW_IPSEC_TRUST: $FW_IPSEC_TRUST is no valid zone"
1120         fi
1121     fi
1122 }
1123
1124 allow_ipsec()
1125 {
1126     if [ -n "$ipsec_chain" ]; then
1127         $IPTABLES -A INPUT -j "input_$ipsec_chain" $IPSEC_INPUT_MATCH
1128         $IPTABLES -A FORWARD -j "forward_$ipsec_chain" $IPSEC_INPUT_MATCH
1129         $IPTABLES -A FORWARD -j "forward_$ipsec_chain" $IPSEC_OUTPUT_MATCH
1130     fi
1131 }
1132
1133 #####################################
1134 # Rule split up - forking to chains #
1135 #####################################
1136 # ipv4 and ipv6
1137 fork_to_chains()
1138 {
1139     local iptables
1140     local zone
1141     local dev
1142     local devs
1143     local any
1144     local anyzone=''
1145
1146     for iptables in "$IPTABLES" "$IP6TABLES"; do
1147         for zone in $saved_input_zones; do
1148             eval devs="\$FW_DEV_$zone"
1149             for dev in $devs; do
1150                 $iptables -A INPUT -j input_$zone -i $dev
1151             done
1152             eval any="\$DEV_${zone}_ANY"
1153             if [ "$any" = 'yes' ]; then
1154                 if [ -n "$anyzone" ]; then
1155                     [ "$iptables" != ':' ] && warning "interface 'any' already in zone '$anyzone', ignoring '$zone'"
1156                 else
1157                     anyzone=$zone
1158                 fi
1159             fi
1160         done
1161         if [ -n "$anyzone" ]; then
1162             $iptables -A INPUT -j input_$anyzone
1163             anyzone=''
1164         fi
1165         if [ "$FW_ROUTE" = yes ]; then
1166             for zone in $forward_zones; do
1167                 eval devs="\$FW_DEV_$zone"
1168                 for dev in $devs; do
1169                     $iptables -A FORWARD -j forward_$zone -i $dev
1170                 done
1171             done
1172         fi
1173     done
1174 }
1175
1176 # ipv4 and ipv6
1177 finish_chains()
1178 {
1179     local iptables
1180     for iptables in "$IPTABLES" "$IP6TABLES"; do
1181         # anything which is now not in the input_* chains is evil
1182         $LDAC $iptables -A INPUT ${LOG}"-IN-ILL-TARGET " 
1183         $iptables -A INPUT -j "$DROP"
1184
1185         $LDAC $iptables -A FORWARD ${LOG}"-FWD-ILL-ROUTING "
1186         if [ "$FW_ROUTE" = yes ]; then
1187             $iptables -A FORWARD -j "$DROP" # this is an unneeded rule, but looks nice :)
1188         fi
1189
1190         $iptables -A OUTPUT -j ACCEPT -m state --state NEW,ESTABLISHED,RELATED
1191         $iptables -A OUTPUT ${LOG}"-OUT-ERROR " 
1192         # we want to let locally generated packets out since our task is not
1193         # to protect the world from us, but protect us from the world ;)
1194         # policy is ACCEPT $iptables -A OUTPUT -j ACCEPT
1195     done
1196
1197     # MSS stuff needs this?
1198     if [ "$FW_ROUTE" = yes ]; then
1199         $IPTABLES -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
1200     fi
1201 }
1202
1203 # Protect the firewall from the internal network? #
1204 protect_from_internal()
1205 {
1206     local iptables chain newzones
1207     for chain in $input_zones; do
1208
1209         if [ "$chain" = "int" -a "$FW_PROTECT_FROM_INTERNAL" = "no" ]; then
1210             val="no"
1211             warning "FW_PROTECT_FROM_INTERNAL is deprecated, use FW_PROTECT_FROM_INT instead"
1212         else
1213             var="FW_PROTECT_FROM_`cibiz $chain`"
1214             eval val="\"\$$var\""
1215         fi
1216
1217         if [ -z "$val" -o "$val" != no ]; then
1218             if [ -z "$newzones" ]; then
1219                 newzones="$chain"
1220             else
1221                 newzones="$newzones $chain"
1222             fi
1223         else
1224             eval devs="\$FW_DEV_$zone"
1225             chain=input_$chain
1226             for iptables in "$IPTABLES" "$IP6TABLES"; do
1227                 $LAA $iptables -A $chain ${LOG}"-`rulelog $chain`-ACC-ALL " 
1228                 $iptables -A $chain -j "$ACCEPT"
1229             done
1230         fi
1231     done
1232
1233     if [ "$input_zones" != "$newzones" ]; then 
1234         saved_input_zones="$input_zones" # need that for fork_to_chains
1235         input_zones="$newzones"
1236     fi
1237 }
1238
1239 # ICMP stuff
1240 allow_icmp()
1241 {
1242     local chain dev itype zone devs
1243     # INPUT ICMP rules
1244     if [ "$FW_ALLOW_FW_SOURCEQUENCH" != "no" ]; then
1245         for chain in $input_zones; do
1246             chain=input_$chain
1247             $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-SOURCEQUENCH "  -p icmp --icmp-type source-quench
1248             $IPTABLES -A $chain -j "$ACCEPT" -p icmp --icmp-type source-quench
1249         done
1250     fi
1251
1252     if [ "$FW_ALLOW_PING_FW" = yes ]; then
1253         for chain in $input_zones; do
1254             chain=input_$chain
1255             $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-PING "  -p icmp --icmp-type echo-request
1256             $IPTABLES -A $chain -j "$ACCEPT" -p icmp --icmp-type echo-request
1257
1258             $LAA $IP6TABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-PING "  -p icmpv6 --icmpv6-type echo-request
1259             $IP6TABLES -A $chain -j "$ACCEPT" -p icmpv6 --icmpv6-type echo-request
1260         done
1261     fi
1262     local icmp_types="$safe_icmp_replies"
1263     for itype in $icmp_types; do
1264         for chain in $input_zones; do
1265             chain=input_$chain
1266             $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-ICMP "  -m state --state ESTABLISHED,RELATED -p icmp --icmp-type $itype
1267             $IPTABLES -A $chain -j "$ACCEPT" -m state --state ESTABLISHED,RELATED -p icmp --icmp-type $itype
1268         done
1269     done
1270     icmp_types="$safe_icmpv6_replies"
1271     for itype in $icmp_types; do
1272         for chain in $input_zones; do
1273             chain=input_$chain
1274             $LAA $IP6TABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-ICMP " -m state --state ESTABLISHED,RELATED  -p icmpv6 --icmpv6-type $itype
1275             $IP6TABLES -A $chain -j "$ACCEPT" -m state --state ESTABLISHED,RELATED -p icmpv6 --icmpv6-type $itype
1276         done
1277     done
1278     # DROP rules for input ICMP are after trusted handling (see below)
1279     
1280     # state matching for these does not work
1281     icmp_types="$stateless_icmpv6_types"
1282     for itype in $icmp_types; do
1283         for chain in $input_zones; do
1284             chain=input_$chain
1285             $LAA $IP6TABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-ICMP " -p icmpv6 --icmpv6-type $itype
1286             $IP6TABLES -A $chain -j "$ACCEPT" -p icmpv6 --icmpv6-type $itype
1287         done
1288     done
1289 }
1290
1291 allow_forward_icmp_echo()
1292 {
1293     [ "$FW_ROUTE" != "yes" ] && return
1294
1295     local zone chain var val
1296
1297     # FORWARD ICMP rules
1298     for zone in $forward_zones; do
1299         var="FW_ALLOW_PING_`cibiz $zone`"
1300         eval val="\"\$$var\""
1301
1302         [ "$val" != yes ] && continue
1303
1304         eval devs="\$FW_DEV_$zone"
1305
1306         for dev in $devs; do
1307             for chain in $forward_zones; do
1308                 [ "$chain" = "$zone" ] && continue
1309
1310                 chain=forward_$chain
1311                 $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-PING "  -p icmp --icmp-type echo-request -o $dev
1312                 $IPTABLES -A $chain -j "$ACCEPT" -m state --state NEW -p icmp --icmp-type echo-request -o $dev
1313                 $LAA $IP6TABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-PING "  -p icmpv6 --icmpv6-type echo-request -o $dev
1314                 $IP6TABLES -A $chain -j "$ACCEPT" -m state --state NEW -p icmpv6 --icmpv6-type echo-request -o $dev
1315             done
1316         done
1317         chain=forward_$zone
1318         $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-PING "  -p icmp --icmp-type echo-reply
1319         $IPTABLES -A $chain -j "$ACCEPT"  -m state --state ESTABLISHED -p icmp --icmp-type echo-reply
1320         $LAA $IP6TABLES -A $chan ${LOG}"-`rulelog $chain`-ACC-PING "  -p icmpv6 --icmpv6-type echo-reply
1321         $IP6TABLES -A $chain -j "$ACCEPT"  -m state --state ESTABLISHED -p icmpv6 --icmpv6-type echo-reply
1322     done
1323     # drop rule for forwarding chains are at the end of the forwarding rules
1324 }
1325
1326 #############################
1327 # Trusted Networks Handling #
1328 #############################
1329 process_trusted_nets()
1330 {
1331     local nets net chain
1332     for nets in $FW_TRUSTED_NETS; do
1333         IFS=, eval set -- \$nets
1334         net="$1"
1335         proto="$2"
1336         port="$3"
1337         if [ -n "$4" ]; then
1338             error "Too many arguments in FW_TRUSTED_NETS -> $nets"
1339         elif [ -z "$net" ]; then
1340             error "network parameter of FW_TRUSTED_NETS is empty -> $nets"
1341         elif [ -z "$proto" -a -n "$port" ]; then
1342             error "need to specify protocol for port $port in FW_TRUSTED_NETS"
1343         elif [ -z "$proto" ] || check_proto_port "$proto" "$port" "" 'FW_TRUSTED_NETS'; then
1344             for chain in $input_zones; do # trusted networks can be on any interface ...
1345                 chain=input_$chain
1346                 $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-TRUST " -m state --state NEW -s $net $proto $port
1347                 $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-TRUST " -s $net $proto $port
1348                 $IPTABLES -A $chain -j "$ACCEPT"  -m state --state NEW,ESTABLISHED,RELATED -s $net $proto $port
1349             done
1350         fi
1351     done
1352 }
1353
1354 # determine port numbers of rpc services and generate a suitable iptables
1355 # parameter fragment
1356 #
1357 # parameters: names of rpc services, e.g. ypbind mountd
1358 rpcservicerules()
1359 {
1360     $PERL "$SCRIPTSDIR/SuSEfirewall2-rpcinfo" "$@" 2>/dev/null
1361 }
1362
1363 # parameters: REJECT|DROP
1364 reject_or_drop_services()
1365 {
1366     local action="$1"
1367     local var
1368     local services target service proto net port
1369     local iptables zone chain
1370
1371     eval target=\$$action
1372
1373     for zone in $input_zones; do
1374         chain=input_$zone
1375         var="FW_SERVICES_${action}_`cibiz $zone`"
1376         eval services="\"\$$var\""
1377
1378         for service in $services; do
1379             IFS=, eval set -- \$service
1380             if [ "$#" -lt 2 ]; then
1381                 error "too few parameters in $var -> $service"
1382                 continue
1383             fi
1384
1385             net="${1:-0/0}"
1386             proto="$2"
1387             port="$3"
1388             sport="$4"
1389             shift 4
1390
1391             iptables="$IPTABLES $IP6TABLES"
1392             case "$net" in
1393                 *:*) iptables="$IP6TABLES" ;;
1394                 [0-9]*.*.*.*) iptables="$IPTABLES" ;;
1395             esac
1396
1397             if [ "$proto" = "_rpc_" ]; then
1398                 rpcservicerules $service | while read ARG; do
1399                     $LDC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-$action " -m state --state NEW $ARG
1400                     $IPTABLES -A $chain -j "$target" $ARG
1401                 done
1402             elif check_proto_port "$proto" "$port" "$sport" "$var"; then
1403                 for iptables in $iptables; do
1404                     $LDA $iptables -A $chain -s $net $proto $port $sport -m state --state NEW ${LOG}"-`rulelog $chain`-$action "
1405                     $iptables -A $chain -s $net $proto $port $sport -m state --state NEW -j "$target"
1406                 done
1407             fi
1408         done
1409     done
1410 }
1411
1412 accept_services()
1413 {
1414     local var
1415     local services target service proto net
1416     local iptables zone chain
1417     local ipt_recent_update ipt_recent_set ipt_recent_rcheck
1418
1419     for zone in $input_zones; do
1420         chain=input_$zone
1421         var="FW_SERVICES_ACCEPT_`cibiz $zone`"
1422         eval services="\"\$$var\""
1423
1424         for service in $services; do
1425             ipt_recent_update=''
1426             ipt_recent_set=''
1427             ipt_recent_rcheck=''
1428             IFS=, eval set -- \$service
1429             if [ "$#" -lt 3 ]; then
1430                 error "too few parameters in $var -> $service"
1431                 continue
1432             fi
1433             
1434             net="${1:-0/0}"
1435             proto="$2"
1436             port="$3"
1437             shift 3
1438             sport="$1"
1439             [ "$#" -gt 0 ] && shift
1440
1441             while [ "$#" -gt 0 ]; do
1442                 case "$1" in
1443                     hitcount=*) ipt_recent_update="$ipt_recent_update --hitcount ${1#*=}"; shift ;;
1444                     blockseconds=*) ipt_recent_update="$ipt_recent_update --seconds ${1#*=}"; shift ;;
1445                     recentname=*)
1446                         ipt_recent_update="$ipt_recent_update --name ${1#*=}"
1447                         ipt_recent_set="$ipt_recent_set --name ${1#*=}"
1448                         shift
1449                         ;;
1450                     *) error "unknown parameter $1 in $var -> $service"; continue 2 ;;
1451                 esac
1452             done
1453
1454             if [ -n "$ipt_recent_update" ]; then
1455                 ipt_recent_rcheck="-m recent --rcheck$ipt_recent_update"
1456                 ipt_recent_update="-m recent --update$ipt_recent_update --rttl"
1457                 ipt_recent_set="-m recent --set$ipt_recent_set"
1458             fi
1459
1460             iptables="$IPTABLES $IP6TABLES"
1461             case "$net" in
1462                 *:*) iptables="$IP6TABLES" ;;
1463                 [0-9]*.*.*.*) iptables="$IPTABLES" ;;
1464             esac
1465
1466             if [ "$proto" = "_rpc_" ]; then
1467                 rpcservicerules $service | while read ARG; do
1468                     if [ -n "$ipt_recent_set" ]; then
1469                         $LDC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-DROPr " $ARG -m state --state NEW $ipt_recent_rcheck
1470                         $IPTABLES -A $chain -j "$DROP" $ARG -m state --state NEW $ipt_recent_update
1471                     fi
1472                     $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC " -m state --state NEW $ARG
1473                     $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC " $ARG
1474                     [ -n "$ipt_recent_set" ] && $IPTABLES -A $chain -j ACCEPT $ARG -m state --state NEW $ipt_recent_set
1475                     $IPTABLES -A $chain -j ACCEPT $ARG
1476                 done
1477             elif check_proto_port "$proto" "$port" "$sport" "$var"; then
1478                 for iptables in $iptables; do
1479                     if [ -n "$ipt_recent_set" ]; then
1480                         $LDC $iptables -A $chain ${LOG}"-`rulelog $chain`-DROPr " -s $net $proto $port $sport -m state --state NEW $ipt_recent_rcheck
1481                         $iptables -A $chain -j "$DROP" -s $net $proto $port $sport -m state --state NEW $ipt_recent_update
1482                     fi
1483                     $LAC $iptables -A $chain -s $net $proto $port $sport -m state --state NEW ${LOG}"-`rulelog $chain`-ACC "
1484                     $LAA $iptables -A $chain -s $net $proto $port $sport ${LOG}"-`rulelog $chain`-ACC "
1485                     [ -n "$ipt_recent_set" ] && $iptables -A $chain -s $net $proto $port $sport -j ACCEPT -m state --state NEW $ipt_recent_set
1486                     $iptables -A $chain -s $net $proto $port $sport -j ACCEPT
1487                 done
1488             fi
1489         done
1490     done
1491 }
1492
1493 allow_tcp_highports()
1494 {
1495     local j chain
1496     for j in $FW_ALLOW_INCOMING_HIGHPORTS_TCP; do
1497         case "$j" in
1498         [Dd][Nn][Ss]) warning "FW_ALLOW_INCOMING_HIGHPORTS_TCP=DNS is no longer supported" ;;
1499         no) ;;
1500         yes)
1501             deprecated 'FW_ALLOW_INCOMING_HIGHPORTS_TCP'
1502             for chain in $input_zones; do
1503                 chain=input_$chain
1504                 $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-HiTCP " -p tcp --dport 1024: --syn
1505                 $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-HiTCP " -p tcp --dport 1024:
1506                 $IPTABLES -A $chain -j "$ACCEPT" -p tcp --dport 1024:
1507             done
1508             break;
1509             ;;
1510         *)
1511             deprecated 'FW_ALLOW_INCOMING_HIGHPORTS_TCP'
1512             for chain in $input_zones; do
1513                 chain=input_$chain
1514                 $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-HIGH " -p tcp --sport $j --dport 1024: --syn
1515                 $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-HIGH " -p tcp --sport $j --dport 1024:
1516                 $IPTABLES -A $chain -j "$ACCEPT" -p tcp --sport $j --dport 1024:
1517             done
1518             ;;
1519         esac
1520     done
1521 }
1522
1523 allow_rpc_services()
1524 {
1525     local zone chain ports
1526     for zone in $input_zones; do
1527         chain=input_$zone
1528         eval ports="\$FW_SERVICES_`cibiz $zone`_RPC"
1529         rpcservicerules $ports | while read ARG; do
1530             $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-RPC " -m state --state NEW $ARG
1531             $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-RPC " $ARG
1532             $IPTABLES -A $chain -j "$ACCEPT" $ARG
1533         done
1534     done
1535 }
1536
1537 allow_ip_services()
1538 {
1539     local proto zone iptables protos
1540
1541     for zone in $input_zones; do
1542         chain=input_$zone
1543         eval protos="\$FW_SERVICES_`cibiz $zone`_IP"
1544         for iptables in "$IPTABLES" "$IP6TABLES"; do
1545             for proto in $protos; do
1546                 $LAA $iptables -A $chain ${LOG}"-`rulelog $chain`-ACC-IP " -p $proto
1547                 $iptables -A $chain -j "$ACCEPT" -p $proto
1548             done
1549         done
1550     done
1551 }
1552
1553 allow_tcp_services()
1554 {
1555     local port zone iptables ports
1556
1557     for zone in $input_zones; do
1558         chain=input_$zone
1559         eval ports="\$FW_SERVICES_`cibiz $zone`_TCP"
1560         for iptables in "$IPTABLES" "$IP6TABLES"; do
1561             for port in $ports; do
1562                 $LAC $iptables -A $chain ${LOG}"-`rulelog $chain`-ACC-TCP " -p tcp --dport $port --syn
1563                 $LAA $iptables -A $chain ${LOG}"-`rulelog $chain`-ACC-TCP " -p tcp --dport $port
1564                 $iptables -A $chain -j "$ACCEPT" -p tcp --dport $port
1565             done
1566         done
1567     done
1568 }
1569
1570 # UDP Stuff
1571 allow_udp_services()
1572 {
1573     local port zone iptables ports
1574
1575     for zone in $input_zones; do
1576         chain=input_$zone
1577         eval ports="\$FW_SERVICES_`cibiz $zone`_UDP"
1578         for iptables in "$IPTABLES" "$IP6TABLES"; do
1579             for port in $ports; do
1580                 $LAA $iptables -A $chain ${LOG}"-`rulelog $chain`-ACC-UDP " -p udp --dport $port
1581                 $iptables -A $chain -j "$ACCEPT" -p udp --dport $port
1582             done
1583         done
1584     done
1585 }
1586
1587 allow_highports_udp()
1588 {
1589     local j chain
1590     # checking "yes" in the loop allows you to log individual services plus
1591     # allowing all
1592     for j in $FW_ALLOW_INCOMING_HIGHPORTS_UDP; do
1593         case "$j" in
1594             [Dd][Nn][Ss])
1595                     warning "FW_ALLOW_INCOMING_HIGHPORTS_UDP=DNS is no longer supported"
1596                     ;;
1597             no) ;;
1598             yes)
1599                 deprecated 'FW_ALLOW_INCOMING_HIGHPORTS_UDP'
1600                 for chain in $input_zones; do
1601                     chain=input_$chain
1602                     $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-HiUDP " -m state --state NEW -p udp --dport 1024:
1603                     $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-HiUDP " -p udp --dport 1024:
1604                     $IPTABLES -A $chain -j "$ACCEPT" -m state --state NEW -p udp --dport 1024:
1605                 done
1606                 break;
1607                 ;;
1608             *)
1609                 deprecated 'FW_ALLOW_INCOMING_HIGHPORTS_UDP'
1610                 for chain in $input_zones; do
1611                     chain=input_$chain
1612                     $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-HiUDP " -m state --state NEW -p udp --sport $j --dport 1024:
1613                     $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-HiUDP " -p udp --sport $j --dport 1024:
1614                     $IPTABLES -A $chain -j "$ACCEPT" -m state --state NEW -p udp --sport $j --dport 1024:
1615                 done
1616                 ;;
1617         esac
1618     done
1619 }
1620
1621 # redirect packets from one port to another, opens ports in input_*
1622 redirect_rules()
1623 {
1624     local chain nets net1 net2 proto port1 port2
1625     local redirectinstalled
1626     for nets in $FW_REDIRECT; do
1627         IFS=, eval set -- \$nets
1628
1629         net1="$1"
1630         net2="$2"
1631         proto="$3"
1632         port1="$4"
1633         port2="$5"
1634         
1635         if [ -n "$6" ]; then
1636             error "Too many arguments in FW_REDIRECT -> $nets"
1637         elif [ -z "$net1" -o -z "$net2" -o -z "$proto" -o -z "$port1" -o -z "$port2" ]; then
1638             error "Missing parameter in FW_REDIRECT -> $nets"
1639         elif [ "$proto" != tcp -a "$proto" != udp ]; then
1640             error "FW_REDIRECT supports only tcp and udp -> $nets"
1641         else
1642             net1=${net1/\!/\! }
1643             net2=${net2/\!/\! }
1644             $IPTABLES -A PREROUTING -t mangle -j MARK  -p $proto -s $net1 -d $net2 --dport $port1 --set-mark $mark_redir
1645             $IPTABLES -A PREROUTING -t nat -j REDIRECT -p $proto -s $net1 -d $net2 --dport $port1 --to-ports $port2
1646             redirectinstalled=1
1647         fi
1648     done
1649
1650     if [ -n "$redirectinstalled" ]; then
1651         for chain in $input_zones; do
1652             chain=input_$chain
1653             $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-REDIR " -m mark --mark $mark_redir -m state --state NEW
1654             $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-REDIR " -m mark --mark $mark_redir -m state --state NEW,ESTABLISHED,RELATED
1655             $IPTABLES -A $chain -j "$ACCEPT" -m state --state NEW,ESTABLISHED,RELATED -m mark --mark $mark_redir
1656         done
1657     fi
1658
1659 }
1660
1661 # parameters: zone interfaces
1662 # assuming that only traffic from $zone interface enter the forward_$zone chain
1663 # anyways, we don't need the -i parameter
1664 allow_class_routing()
1665 {
1666     [ "$FW_ALLOW_CLASS_ROUTING" != yes ] && return
1667
1668     local chain iface devs zone
1669     for zone in $forward_zones; do
1670         eval devs="\$FW_DEV_$zone"
1671         chain=forward_$zone
1672         for iface in $devs; do
1673             $LAA $IPTABLES -A $chain $LOG"-`rulelog $chain`-ACC-CLASS "  -o $iface
1674             $IPTABLES -A $chain -j "$ACCEPT" -o $iface
1675         done
1676     done
1677 }
1678
1679 allow_related_forward_icmp()
1680 {
1681     local chain itype
1682
1683     for chain in $forward_zones; do
1684         chain=forward_$chain
1685         for itype in $safe_icmp_replies; do
1686             $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-FWD-RELA"  -m state --state ESTABLISHED,RELATED -p icmp --icmp-type $itype
1687             $IPTABLES -A $chain -j "$ACCEPT" -m state --state ESTABLISHED,RELATED -p icmp --icmp-type $itype
1688         done
1689         for itype in $safe_icmpv6_replies; do
1690             $LAA $IP6TABLES -A $chain ${LOG}"-`rulelog $chain`-FWD-RELA " -m state --state ESTABLISHED,RELATED  -p icmpv6 --icmpv6-type $itype
1691             $IP6TABLES -A $chain -j "$ACCEPT" -m state --state ESTABLISHED,RELATED -p icmpv6 --icmpv6-type $itype
1692         done
1693     done
1694 }
1695
1696 # <source network>,<destination network>[,protocol[,port[,flags]]]
1697 forwarding_rules()
1698 {
1699     local nets net1 net2 flags more_args_in more_args_out chain
1700     for nets in $FW_FORWARD; do
1701         IFS=, eval set -- \$nets
1702
1703         net1="$1"
1704         net2="$2"
1705         proto="$3"
1706         port="$4"
1707         flags="$5"
1708         rport=""
1709         more_args_in=
1710         more_args_out=
1711
1712         case "$flags" in
1713             "") ;;
1714             ipsec)
1715                 more_args_in="$IPSEC_INPUT_MATCH"
1716                 more_args_out="$IPSEC_OUTPUT_MATCH"
1717                 ;;
1718             *)
1719                 echo "Error: unsupported flag in FW_FORWARD: $flags"
1720                 net1=""
1721                 ;;
1722         esac
1723
1724         if [ -n "$proto" ] && ! check_proto_port "$proto" "$port" '' "FW_FORWARD"; then
1725             continue
1726         fi
1727
1728         if [ -n "$net1" -a -n "$net2" ]; then
1729             for chain in $forward_zones; do
1730                 chain=forward_$chain
1731                 $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-FORW "  -s $net1 -d $net2 $proto $port -m state --state NEW $more_args_in
1732                 $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-FORW "  -s $net1 -d $net2 $proto $port $more_args_in
1733                 $IPTABLES -A $chain -j "$ACCEPT" -m state --state NEW,ESTABLISHED,RELATED -s $net1 -d $net2 $proto $port $more_args_in
1734                 $IPTABLES -A $chain -j "$ACCEPT" -m state --state ESTABLISHED,RELATED -s $net2 -d $net1 $proto $rport $more_args_in
1735                 if [ -n "$more_args_out" ]; then
1736                     $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-FORW "  -s $net1 -d $net2 $proto $port -m state --state NEW $more_args_out
1737                     $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-FORW "  -s $net1 -d $net2 $proto $port $more_args_out
1738                     $IPTABLES -A $chain -j "$ACCEPT" -m state --state NEW,ESTABLISHED,RELATED -s $net1 -d $net2 $proto $port $more_args_out
1739                     $IPTABLES -A $chain -j "$ACCEPT" -m state --state ESTABLISHED,RELATED -s $net2 -d $net1 $proto $rport $more_args_out
1740                 fi
1741             done
1742         else
1743             error "too few parameters in FW_FORWARD -> $nets"
1744         fi
1745      done
1746 }
1747
1748 masquerading_rules()
1749 {
1750     local nets net1 net2 proto port dev chain snet2 sport
1751     for nets in $FW_MASQ_NETS; do
1752         IFS=, eval set -- \$nets
1753
1754         net1="$1"
1755         net2="$2"
1756         proto="$3"
1757         port="$4"
1758         rport=""
1759
1760         if [ -n "$5" ]; then
1761             error "Too many arguments in FW_MASQ_NETS -> $nets"
1762         elif [ -z "$net1" ]; then
1763             error "source network must not be empty in FW_MASQ_NETS -> $nets"
1764         elif [ -z "$proto" -a -z "$port" ] || check_proto_port "$proto" "$port" '' 'FW_MASQ_NETS'; then
1765             net1=${net1/\!/\! }
1766             net2=${net2/\!/\! }
1767             snet2=""
1768             if [ -n "$net2" ]; then
1769                 snet2="-s $net2"
1770                 net2="-d $net2"
1771             fi
1772
1773             for dev in $FW_MASQ_DEV; do
1774                 for chain in $forward_zones; do
1775                     chain=forward_$chain
1776                     $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-MASQ "  -s $net1 $net2 $proto $port -o $dev
1777                     $IPTABLES -A $chain -j "$ACCEPT" -m state --state NEW,ESTABLISHED,RELATED -s $net1 $net2 $proto $port -o $dev
1778                     # we need to allow the replies as well
1779                     $LAA $IPTABLES -A $chain -d $net1 $snet2 $proto $rport -i $dev ${LOG}"-`rulelog $CHAIN`-ACC-MASQ " -m state --state ESTABLISHED,RELATED
1780                     $IPTABLES -A $chain -d $net1 $snet2 $proto $rport -i $dev -j "$ACCEPT" -m state --state ESTABLISHED,RELATED
1781                 done
1782                 $IPTABLES -A POSTROUTING -j MASQUERADE -t nat -s $net1 $net2 $proto $port -o $dev
1783             done
1784         fi
1785     done
1786 }
1787
1788 # <source network>,<ip to forward to>,<protocol>,<port>[,redirect port,[destination ip]]
1789 forward_masquerading_rules()
1790 {
1791     local nets net1 net2 proto port1 port2 lip
1792     for nets in $FW_FORWARD_MASQ; do
1793         IFS=, eval set -- \$nets
1794
1795         net1="$1"
1796         net2="$2"
1797         proto="$3"
1798         port1="$4"
1799         port2="$5"
1800         lip="$6"
1801
1802         case "$net2" in
1803             */*|'')
1804                 error "target must be a single host in FW_FORWARD_MASQ -> $nets"
1805                 continue
1806                 ;;
1807         esac
1808
1809         if [ -n "$7" ]; then
1810             error "too many arguments in FW_FORWARD_MASQ -> $nets"
1811         elif [ -z "$net1" ]; then
1812             error "source network must not be empty in FW_FORWARD_MASQ -> $nets"
1813         elif [ "$proto" != tcp -a "$proto" != udp ]; then
1814             error "The protocol with FW_FORWARD_MASQ must be tcp or udp -> $nets"
1815         elif [ -z "$port1" ]; then
1816             error "Port missing in FW_FORWARD_MASQ -> $nets"
1817         else
1818             proto="-p $proto"
1819             test -z "$port2" && port2="$port1"
1820             port1="--dport $port1"
1821             dport2="--dport $port2"
1822             port2=":${port2/:/-}"
1823             test -n "$lip" && lip="-d $lip"
1824             for dev in $FW_MASQ_DEV; do
1825                 $IPTABLES -A PREROUTING -j DNAT -t nat $proto -s $net1 $lip $port1 --to-destination ${net2}${port2} -i $dev
1826                 # to install minimal rule set we'd need to check if
1827                 # $net1 is covered by $FW_MASQ_NETS. Not feasible in
1828                 # bash code so just check for 0/0
1829                 if [ "$FW_MASQ_NETS" != "0/0" ]; then
1830                     $IPTABLES -A POSTROUTING -j MASQUERADE -t nat -s $net1 -d $net2 $proto $dport2 -o $dev
1831                 fi
1832             done
1833             for chain in $forward_zones; do
1834                 chain=forward_$chain
1835                 $LAC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-REVMASQ " $proto -s $net1 -d $net2 $dport2 -m state --state NEW
1836                 $LAA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-ACC-REVMASQ " $proto -s $net1 -d $net2 $dport2
1837                 $IPTABLES -A $chain -j "$ACCEPT" $proto -s $net1 -d $net2 $dport2
1838                 $IPTABLES -A $chain -j "$ACCEPT" $proto -d $net1 -s $net2 -m state --state ESTABLISHED,RELATED
1839             done
1840         fi
1841     done
1842 }
1843
1844 # Special Logging + Deny #
1845 drop_all()
1846 {
1847     local chain
1848     local itype
1849     local chains
1850
1851     for chain in $input_zones; do
1852         chains="$chains input_$chain"
1853     done
1854
1855     if [ "$FW_ROUTE" = yes ]; then
1856         for chain in $forward_zones; do
1857             chains="$chains forward_$chain"
1858         done
1859     fi
1860     
1861     for chain in $chains; do
1862         # log and drop multicast packets separately to not flood
1863         # other log targets (#155326)
1864         $LDC $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-DROP-DEFLT " -m pkttype --pkt-type multicast
1865         $IPTABLES -A $chain -j "$DROP" -m pkttype --pkt-type multicast
1866         # some packet types are considered critical
1867         if [ -z "$LDC" ]; then
1868             local log=${LOG}"-`rulelog $chain`-DROP-DEFLT"
1869             $IPTABLES  -A $chain $log" " -p tcp --syn
1870             $IP6TABLES -A $chain $log" " -p tcp --syn
1871             $IPTABLES  -A $chain $log" " -p icmp
1872             $IP6TABLES -A $chain $log" " -p icmpv6
1873             $IPTABLES  -A $chain $log" " -p udp
1874             $IP6TABLES -A $chain $log" " -p udp
1875             $IPTABLES  -A $chain ${LOG}"-`rulelog $chain`-DROP-DEFLT-INV " -m state --state INVALID
1876             $IP6TABLES -A $chain ${LOG}"-`rulelog $chain`-DROP-DEFLT-INV " -m state --state INVALID
1877         fi
1878         # log anything else
1879         $LDA $IPTABLES -A $chain ${LOG}"-`rulelog $chain`-DROP-DEFLT "
1880         $IPTABLES -A $chain -j "$DROP"
1881         $LDA $IP6TABLES -A $chain ${LOG}"-`rulelog $chain`-DROP-DEFLT "
1882         $IP6TABLES -A $chain -j "$DROP"
1883     done
1884 }
1885
1886 ############################################
1887 #                                          #
1888 # Now we begin to set the filter rules ... #
1889 #                                          #
1890 ############################################
1891
1892 if [ "$ACTION" = "showlog" ]; then
1893     exec $PERL "$SCRIPTSDIR/SuSEfirewall2-showlog" "$@"
1894     die 1 "failed to execute $SCRIPTSDIR/SuSEfirewall2-showlog"
1895 fi
1896
1897 ###############
1898
1899 parse_logging
1900
1901 setlock
1902
1903 if [ "$ACTION" = "basic" ]; then
1904     # Reset the filter rules
1905     set_basic_rules
1906
1907     $IPTABLES -A INPUT -j "$ACCEPT" -p icmp --icmp-type echo-request
1908
1909     # log incoming tcp connection requests. also logging udp etc would just flood the log
1910     $IPTABLES -A INPUT -p tcp -m state --state NEW $LOG"-IN-DROP-NEW-CONNECT "
1911
1912     # reject anything else
1913     $IPTABLES -A INPUT -j "$DROP"
1914
1915     [ -n "$USE_IPTABLES_BATCH" ] && commit_iptables_batch
1916
1917     die 0 "Firewall rules successfully set in simple mode"
1918 fi
1919
1920 if [ "$MODE" = "test" ]; then
1921     DROP="ACCEPT"
1922     REJECT="ACCEPT"
1923     FW_LOG_DROP_ALL=yes
1924     FW_LOG_DROP_CRIT=yes
1925     FW_LOG_ACCEPT_ALL=no
1926     FW_LOG_ACCEPT_CRIT=no
1927     warning "SuSEfirewall2 is running in TEST MODE, no packet filtering is done!"
1928 fi
1929         
1930 if [ "$ACTION" = "stop" ]; then
1931     reset_rules
1932     handle_initscripts
1933     [ -n "$USE_IPTABLES_BATCH" ] && commit_iptables_batch
1934     die 0 "Firewall rules unloaded."
1935 fi
1936
1937 if [ "$ACTION" = "close" ]; then
1938     set_basic_rules
1939     setproc 0 /proc/sys/net/ipv4/ip_forward
1940     [ -n "$USE_IPTABLES_BATCH" ] && commit_iptables_batch
1941     die 0 "Firewall rules set to CLOSE."
1942 fi
1943
1944 if [ "$ACTION" = "status" ]; then
1945     if [ "$UID" != 0 ]; then
1946         die 2 "You need to be root to check the status"
1947     fi
1948     if ! $IPTABLES -nL reject_func >/dev/null 2>&1; then
1949         die 1 "SuSEfirewall2 not active"
1950     fi
1951     # yes we need cat here, while read ... does no work :-(
1952     for i in `sort < /proc/net/ip_tables_names`; do
1953         echo "### iptables $i ###"
1954         $IPTABLES -t $i -vnL
1955         echo ""
1956     done
1957     if [ "$IP6TABLES" != ":" ]; then
1958         for i in `sort /proc/net/ip6_tables_names`; do
1959             echo "### ip6tables $i ###"
1960             $IP6TABLES -t $i -vnL
1961             echo ""
1962         done
1963     fi
1964     die 0
1965 fi
1966
1967 if [ "$ACTION" = "open" ]; then
1968     OPENHELPER="$SCRIPTSDIR/SuSEfirewall2-open"
1969     exec $PERL -w $OPENHELPER "$@"
1970     die 1 "failed to execute $OPENHELPER"
1971 fi
1972
1973 ### main mode ###
1974
1975 message "Setting up rules from $FWCONFIG ..."
1976
1977 parse_zones
1978
1979 auto_detect_all_interfaces
1980
1981 parse_interfaces
1982 load_customrules
1983
1984 check_interfaces
1985
1986 verify_parameters
1987 #verify_masq_nets
1988
1989 parse_ipsec
1990
1991 remove_unused_zones
1992 [ "$FW_ROUTE" = 'yes' ] && forward_zones="$all_zones"
1993 input_zones="$all_zones"
1994 saved_input_zones="$input_zones" # need that for fork_to_chains
1995
1996 #create_zones_hash
1997
1998 parse_configurations
1999
2000 # Set default rules + flush
2001 set_basic_rules
2002
2003 switch_on_ip_forwarding
2004
2005 set_proc_stuff
2006
2007 create_chains
2008
2009 # HOOK
2010 fw_custom_before_antispoofing
2011
2012 # HOOK
2013 fw_custom_after_antispoofing
2014
2015 protect_from_internal
2016
2017 check_convert_old_broadcast
2018
2019 drop_broadcast
2020
2021 allow_ipsec
2022
2023 allow_icmp
2024
2025 allow_forward_icmp_echo
2026
2027 # HOOK
2028 fw_custom_before_port_handling
2029
2030 process_trusted_nets
2031
2032 allow_ip_services
2033
2034 allow_tcp_services
2035
2036 allow_udp_services
2037
2038 allow_rpc_services
2039
2040 accept_services
2041
2042 reject_or_drop_services DROP
2043
2044 reject_or_drop_services REJECT
2045
2046 allow_tcp_highports
2047
2048 allow_highports_udp
2049
2050 # HOOK
2051 fw_custom_before_masq
2052
2053 redirect_rules
2054
2055 if [ "$FW_ROUTE" = yes ]; then
2056
2057     allow_related_forward_icmp
2058
2059     allow_class_routing
2060
2061     forwarding_rules
2062
2063     if [ "$FW_MASQUERADE" = yes ]; then
2064         masquerading_rules
2065         forward_masquerading_rules
2066     fi
2067 fi
2068
2069 # HOOK
2070 fw_custom_before_denyall
2071
2072 drop_all
2073
2074 fork_to_chains
2075
2076 finish_chains
2077
2078 # HTB settings
2079 if [ -n "$FW_HTB_TUNE_DEV" ]; then
2080     need qdisc
2081     do_qdisc_settings
2082 fi
2083
2084 [ -n "$USE_IPTABLES_BATCH" ] && commit_iptables_batch
2085
2086 handle_initscripts
2087
2088 # END #
2089 die 0 "Firewall rules successfully set"
2090
2091 # vim: sw=4