diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 2f9f8df80..f4ee61d77 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -154,7 +154,6 @@ our %EXPORT_TAGS = ( get_interface_mac have_global_variables set_global_variables - compile_stop_firewall create_netfilter_load create_chainlist_reload $section diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm index 5d2e1ae00..a382cf0c3 100644 --- a/Shorewall/Perl/Shorewall/Rules.pm +++ b/Shorewall/Perl/Shorewall/Rules.pm @@ -44,6 +44,7 @@ our @EXPORT = qw( process_tos process_rules generate_matrix setup_mss + compile_stop_firewall ); our @EXPORT_OK = qw( process_rule process_rule1 initialize ); our $VERSION = '4.3_7'; @@ -2113,4 +2114,350 @@ sub setup_mss( ) { add_rule $chainref , "-p tcp --tcp-flags SYN,RST SYN ${match}-j TCPMSS $option" if $clampmss; } +# +# Compile the stop_firewall() function +# +sub compile_stop_firewall() { + + emit <<'EOF'; +# +# Stop/restore the firewall after an error or because of a 'stop' or 'clear' command +# +stop_firewall() { +EOF + + if ( $family == F_IPV4 ) { + emit( ' deletechain() {', + ' qt $IPTABLES -L $1 -n && qt $IPTABLES -F $1 && qt $IPTABLES -X $1' ); + } else { + emit( ' deletechain() {', + ' qt $IP6TABLES -L $1 -n && qt $IP6TABLES -F $1 && qt $IP6TABLES -X $1' ); + } + + emit <<'EOF'; + } + + deleteallchains() { + do_iptables -F + do_iptables -X + } + + delete_nat() { + do_iptables -t nat -F + do_iptables -t nat -X + + if [ -f ${VARDIR}/nat ]; then + while read external interface; do + del_ip_addr $external $interface + done < ${VARDIR}/nat + + rm -f ${VARDIR}/nat + fi + } + + case $COMMAND in + stop|clear|restore) + ;; + *) + set +x + + case $COMMAND in + start) + logger -p kern.err "ERROR:$PRODUCT start failed" + ;; + restart) + logger -p kern.err "ERROR:$PRODUCT restart failed" + ;; + restore) + logger -p kern.err "ERROR:$PRODUCT restore failed" + ;; + esac + + if [ "$RESTOREFILE" = NONE ]; then + COMMAND=clear + clear_firewall + echo "$PRODUCT Cleared" + + kill $$ + exit 2 + else + RESTOREPATH=${VARDIR}/$RESTOREFILE + + if [ -x $RESTOREPATH ]; then + echo Restoring ${PRODUCT:=Shorewall}... + + if $RESTOREPATH restore; then + echo "$PRODUCT restored from $RESTOREPATH" + set_state "Started" + else + set_state "Unknown" + fi + + kill $$ + exit 2 + fi + fi + ;; + esac + + set_state "Stopping" + + STOPPING="Yes" + + TERMINATOR= + + deletechain shorewall + + run_stop_exit +EOF + + if ( $capabilities{MANGLE_ENABLED} && $config{MANGLE_ENABLED} ) { + emit <<'EOF'; + run_iptables -t mangle -F + run_iptables -t mangle -X + for chain in PREROUTING INPUT FORWARD POSTROUTING; do + qt1 $IPTABLES -t mangle -P $chain ACCEPT + done +EOF + } + + if ( $capabilities{RAW_TABLE} ) { + if ( $family == F_IPV4 ) { + emit <<'EOF'; + run_iptables -t raw -F + run_iptables -t raw -X + for chain in PREROUTING OUTPUT; do + qt1 $IPTABLES -t raw -P $chain ACCEPT + done +EOF + } else { + emit <<'EOF'; + run_iptables -t raw -F + run_iptables -t raw -X + for chain in PREROUTING OUTPUT; do + qt1 $IP6TABLES -t raw -P $chain ACCEPT + done +EOF + } + } + + if ( $capabilities{NAT_ENABLED} ) { + emit <<'EOF'; + delete_nat + for chain in PREROUTING POSTROUTING OUTPUT; do + qt1 $IPTABLES -t nat -P $chain ACCEPT + done +EOF + } + + if ( $family == F_IPV4 ) { + emit <<'EOF'; + if [ -f ${VARDIR}/proxyarp ]; then + while read address interface external haveroute; do + qt arp -i $external -d $address pub + [ -z "${haveroute}${NOROUTES}" ] && qt ip route del $address dev $interface + f=/proc/sys/net/ipv4/conf/$interface/proxy_arp + [ -f $f ] && echo 0 > $f + done < ${VARDIR}/proxyarp + fi + + rm -f ${VARDIR}/proxyarp +EOF + } + + push_indent; + + emit 'delete_tc1' if $config{CLEAR_TC}; + + emit( 'undo_routing', + 'restore_default_route' + ); + + my $criticalhosts = process_criticalhosts; + + if ( @$criticalhosts ) { + if ( $config{ADMINISABSENTMINDED} ) { + emit ( 'for chain in INPUT OUTPUT; do', + ' setpolicy $chain ACCEPT', + 'done', + '', + 'setpolicy FORWARD DROP', + '', + 'deleteallchains', + '' + ); + + for my $hosts ( @$criticalhosts ) { + my ( $interface, $host, $seq ) = ( split /\|/, $hosts ); + my $source = match_source_net $host; + my $dest = match_dest_net $host; + + emit( "do_iptables -A INPUT -i $interface $source -j ACCEPT", + "do_iptables -A OUTPUT -o $interface $dest -j ACCEPT" + ); + } + + emit( '', + 'for chain in INPUT OUTPUT; do', + ' setpolicy $chain DROP', + "done\n" + ); + } else { + emit( '', + 'for chain in INPUT OUTPUT; do', + ' setpolicy $chain ACCEPT', + 'done', + '', + 'setpolicy FORWARD DROP', + '', + "deleteallchains\n" + ); + + for my $hosts ( @$criticalhosts ) { + my ( $interface, $host , $seq ) = ( split /|/, $hosts ); + my $source = match_source_net $host; + my $dest = match_dest_net $host; + + emit( "do_iptables -A INPUT -i $interface $source -j ACCEPT", + "do_iptables -A OUTPUT -o $interface $dest -j ACCEPT" + ); + } + + emit( "\nsetpolicy INPUT DROP", + '', + 'for chain in INPUT FORWARD; do', + ' setcontinue $chain', + "done\n" + ); + } + } elsif ( $config{ADMINISABSENTMINDED} ) { + emit( 'for chain in INPUT FORWARD; do', + ' setpolicy $chain DROP', + 'done', + '', + 'setpolicy OUTPUT ACCEPT', + '', + 'deleteallchains', + '', + 'for chain in INPUT FORWARD; do', + ' setcontinue $chain', + "done\n", + ); + } else { + emit( 'for chain in INPUT OUTPUT FORWARD; do', + ' setpolicy $chain DROP', + 'done', + '', + "deleteallchains\n" + ); + } + + if ( $family == F_IPV6 ) { + emit <<'EOF'; + # + # Enable link local and multi-cast + # + run_iptables -A INPUT -s ff80::/10 -j ACCEPT + run_iptables -A INPUT -d ff80::/10 -j ACCEPT + run_iptables -A INPUT -d ff00::/10 -j ACCEPT +EOF + + emit <<'EOF' unless $config{ADMINISABSENTMINDED}; + run_iptables -A OUTPUT -d ff80::/10 -j ACCEPT + run_iptables -A OUTPUT -d ff00::/10 -j ACCEPT + +EOF + } + + process_routestopped; + + emit( 'do_iptables -A INPUT -i lo -j ACCEPT', + 'do_iptables -A OUTPUT -o lo -j ACCEPT' + ); + + emit 'do_iptables -A OUTPUT -o lo -j ACCEPT' unless $config{ADMINISABSENTMINDED}; + + my $interfaces = find_interfaces_by_option 'dhcp'; + + if ( @$interfaces ) { + my $ports = $family == F_IPV4 ? '67:68' : '546:547'; + + for my $interface ( @$interfaces ) { + emit "do_iptables -A INPUT -p udp -i $interface --dport $ports -j ACCEPT"; + emit "do_iptables -A OUTPUT -p udp -o $interface --dport $ports -j ACCEPT" unless $config{ADMINISABSENTMINDED}; + # + # This might be a bridge + # + emit "do_iptables -A FORWARD -p udp -i $interface -o $interface --dport $ports -j ACCEPT"; + } + } + + emit ''; + + if ( $family == F_IPV4 ) { + if ( $config{IP_FORWARDING} eq 'on' ) { + emit( 'echo 1 > /proc/sys/net/ipv4/ip_forward', + 'progress_message2 IPv4 Forwarding Enabled' ); + } elsif ( $config{IP_FORWARDING} eq 'off' ) { + emit( 'echo 0 > /proc/sys/net/ipv4/ip_forward', + 'progress_message2 IPv4 Forwarding Disabled!' + ); + } + } else { + for my $interface ( all_bridges ) { + emit "do_iptables -A FORWARD -p 58 -i $interface -o $interface -j ACCEPT"; + } + + if ( $config{IP_FORWARDING} eq 'on' ) { + emit( 'echo 1 > /proc/sys/net/ipv6/conf/all/forwarding', + 'progress_message2 IPv6 Forwarding Enabled' ); + } elsif ( $config{IP_FORWARDING} eq 'off' ) { + emit( 'echo 0 > /proc/sys/net/ipv6/conf/all/forwarding', + 'progress_message2 IPv6 Forwarding Disabled!' + ); + } + } + + pop_indent; + + emit ' + run_stopped_exit'; + + my @ipsets = all_ipsets; + + if ( @ipsets ) { + emit <<'EOF' + + if [ -n "$(mywhich ipset)" ]; then + if ipset -S > ${VARDIR}/ipsets.tmp; then + # + # Don't save an 'empty' file + # + grep -q '^-N' ${VARDIR}/ipsets.tmp && mv -f ${VARDIR}/ipsets.tmp ${VARDIR}/ipsets.save + fi + fi +EOF + } + + emit ' + set_state "Stopped" + + logger -p kern.info "$PRODUCT Stopped" + + case $COMMAND in + stop|clear) + ;; + *) + # + # The firewall is being stopped when we were trying to do something + # else. Kill the shell in case we\'re running in a subshell + # + kill $$ + ;; + esac +} +'; + +} + 1;