From 0628dd8593f1aa27b5a9e8d7d3515311b79bd5bc Mon Sep 17 00:00:00 2001 From: teastep Date: Thu, 15 Mar 2007 23:18:58 +0000 Subject: [PATCH] ***INCOMPLETE*** Partial implementation of stop handling git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@5550 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb --- New/Shorewall/Rules.pm | 150 ++++++++++++++++++++++++- New/compiler | 6 +- New/compiler.pl | 175 ++++++++++++++++++++++++++++- New/prog.functions | 245 ----------------------------------------- 4 files changed, 324 insertions(+), 252 deletions(-) diff --git a/New/Shorewall/Rules.pm b/New/Shorewall/Rules.pm index 8c9258b35..4622390a1 100644 --- a/New/Shorewall/Rules.pm +++ b/New/Shorewall/Rules.pm @@ -36,7 +36,7 @@ use Shorewall::Policy; use strict; our @ISA = qw(Exporter); -our @EXPORT = qw( add_common_rules setup_mac_lists process_rules generate_matrix ); +our @EXPORT = qw( add_common_rules setup_mac_lists process_criticalhosts process_routestopped process_rules generate_matrix ); our @EXPORT_OK = qw( process_rule process_rule1 ); our @VERSION = 1.00; @@ -205,6 +205,154 @@ sub setup_blacklist() { } } +sub process_criticalhosts() { + + my $fn = find_file 'routestopped'; + my @critical; + + @critical = (); + + open RS, "$ENV{TMP_DIR}/routestopped" or fatal_error "Unable to open stripped routestopped file: $!"; + + while ( $line = ) { + + my $routeback = 0; + + chomp $line; + $line =~ s/\s+/ /g; + + + my ($interface, $hosts, $options, $extra) = split /\s+/, $line; + + fatal_error "Invalid routestopped file entry: \"$line\"" if $extra; + + $hosts = ALLIPv4 unless $hosts && $hosts ne '-'; + + my @hosts; + + for my $host ( split /,/, $hosts ) { + push @hosts, "$interface:$hosts"; + } + + $options = '-' unless $options; + + unless ( $options eq '-' ) { + for my $option (split /,/, $options ) { + unless ( $option eq 'routeback' || $option eq 'source' || $option eq 'dest' ) { + if ( $option eq 'critical' ) { + push @critical, @hosts; + } else { + warning_message "Unknown routestopped option ( $option ) ignored in routestopped entry \"$line\""; + } + } + } + } + } + + close RS; + + \@critical; +} + +sub process_routestopped() { + + my $fn = find_file 'routestopped'; + my ( @allhosts, %source, %dest ); + + @critical = (); + + progress_message2 "$doing $fn..."; + + open RS, "$ENV{TMP_DIR}/routestopped" or fatal_error "Unable to open stripped routestopped file: $!"; + + while ( $line = ) { + + my $routeback = 0; + + chomp $line; + $line =~ s/\s+/ /g; + + + my ($interface, $hosts, $options, $extra) = split /\s+/, $line; + + fatal_error "Invalid routestopped file entry: \"$line\"" if $extra; + + $hosts = ALLIPv4 unless $hosts && $hosts ne '-'; + + my @hosts; + + for my $host ( split /,/, $hosts ) { + push @hosts, "$interface:$hosts"; + } + + $options = '-' unless $options; + + unless ( $options eq '-' ) { + for my $option (split /,/, $options ) { + if ( $option eq 'routeback' ) { + if ( $routeback ) { + warning_message "Duplicate 'routeback' option ignored in routestopped entry \"$line\""; + } else { + $routeback = 1; + + for my $host ( split /,/, $hosts ) { + my $source = match_source_net $host; + my $dest = match_dest_net $host; + + emit "run_iptables -A FORWARD -i $interface -o $interface $source $dest -j ACCEPT"; + } + } + } elsif ( $option eq 'source' ) { + for my $host ( split /,/, $hosts ) { + $source{"$interface:$host"} = 1; + } + } elsif ( $option eq 'dest' ) { + for my $host ( split /,/, $hosts ) { + $dest{"$interface:$host"} = 1; + } + } else { + warning_message "Unknown routestopped option ( $option ) ignored in routestopped entry \"$line\"" $option eq 'critical'; + } + } + } + + push @allhosts, @hosts; + } + + close RS; + + for my $host ( @allhosts ) { + my ( $interface, $h ) = split /,/, $host; + my $source = match_source_net $h; + my $dest = match_dest_net $h; + + emit "\$IPTABLES INPUT -i $interface $source ACCEPT"; + emit "\$IPTABLES OUTPUT -o $interface $dest ACCEPT" if $config{ADMINISABSENTMINDED}; + + my $matched = 0; + + if ( $source{$host} ) { + emit "\$IPTABLES FORWARD -i $interface $source ACCEPT"; + $matched = 1; + } + + if ( $dest{$host} ) { + emit "\$IPTABLES FORWARD -o $interface $dest ACCEPT"; + $matched = 1; + } + + unless ( $matched ) { + for my $host1 ( @allhosts ) { + unless ( $host eq $host1 ) { + my ( $interface1, $h1 ) = split /,/, $host1; + my $dest1 = match_dest_net $h1; + emit "\$IPTABLES -A FORWARD -i $interface -o $interface1 $source $dest1 -j ACCEPT"; + } + } + } + } +} + sub setup_forwarding() { if ( "\L$config{IP_FORWARDING}" eq 'on' ) { emit 'echo 1 > /proc/sys/net/ipv4/ip_forward'; diff --git a/New/compiler b/New/compiler index cacb361da..f351967d0 100755 --- a/New/compiler +++ b/New/compiler @@ -1,6 +1,6 @@ #!/bin/sh # -# The Shoreline Firewall (Shorewall) Packet Filtering Firewall Compiler - V3.4 +# The Shoreline Firewall (Shorewall) Packet Filtering Firewall Compiler wrapper - V3.9 # # This program is under GPL [http://www.gnu.org/copyleft/gpl.htm] # @@ -21,9 +21,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA # -# If an error occurs while starting or restarting the firewall, the -# firewall is automatically stopped. -# # Commands are: # # compile check Verify the configuration files. @@ -34,6 +31,7 @@ # EXPORT=Yes -e option specified to /sbin/shorewall # SHOREWALL_DIR A directory name was passed to /sbin/shorewall # VERBOSE Standard Shorewall verbosity control. +# # # Fatal error -- stops the compiler after issuing the error message diff --git a/New/compiler.pl b/New/compiler.pl index baf2c8f9a..690cda824 100755 --- a/New/compiler.pl +++ b/New/compiler.pl @@ -150,12 +150,183 @@ sub generate_script_1 { pop_indent; emit "}\n"; + + +} + +sub compile_stop_firewall() { + + emit "#\n# Stop/restore the firewall after an error or because of a 'stop' or 'clear' command\n#"; + emit "stop_firewall() {\n"; + + emit << "EOF"; +# +# Stop/restore the firewall after an error or because of a "stop" or "clear" command +# +stop_firewall() { + + deletechain() { + qt \$IPTABLES -L \$1 -n && qt \$IPTABLES -F \$1 && qt \$IPTABLES -X \$1 + } + + deleteallchains() { + \$IPTABLES -F + \$IPTABLES -X + } + + setcontinue() { + \$IPTABLES -A \$1 -m state --state ESTABLISHED,RELATED -j ACCEPT + } + + delete_nat() { + \$IPTABLES -t nat -F + \$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) + ;; + *) + 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 + + if [ -x \${RESTOREPATH}-ipsets ]; then + progress_message2 Restoring Ipsets... + # + # We must purge iptables to be sure that there are no + # references to ipsets + # + for table in mangle nat filter; do + \$IPTABLES -t \$table -F + \$IPTABLES -t \$table -X + done + + \${RESTOREPATH}-ipsets + fi + + 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 + + determine_capabilities + + run_stop_exit; + if [ -n "\$MANGLE_ENABLED" ]; then + run_iptables -t mangle -F + run_iptables -t mangle -X + for chain in PREROUTING INPUT FORWARD POSTROUTING; do + qt \$IPTABLES -t mangle -P \$chain ACCEPT + done + fi + + if [ -n "\$RAW_TABLE" ]; then + run_iptables -t raw -F + run_iptables -t raw -X + for chain in PREROUTING OUTPUT; do + qt \$IPTABLES -t raw -P \$chain ACCEPT + done + fi + + if [ -n "\$NAT_ENABLED" ]; then + delete_nat + for chain in PREROUTING POSTROUTING OUTPUT; do + qt \$IPTABLES -t nat -P \$chain ACCEPT + done + fi + + 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 + done < \${VARDIR}/proxyarp + + for f in /proc/sys/net/ipv4/conf/*; do + [ -f \$f/proxy_arp ] && echo 0 > \$f/proxy_arp + done + fi + + rm -f \${VARDIR}/proxyarp +EOF + + emit 'delete_tc1' if $config{CLEAR_TC}; + emit 'undo_routing'; + emit 'restore_default_route'; - copy find_file 'prog.functions'; - + my @criticalhosts = process_criticalhosts; + + if ( @criticalhosts ) { + if ( $config{ADMINISABSENTMINDED} ) { + emit 'for chain in INPUT OUTPUT; do'; + emit ' setpolicy \$chain ACCEPT'; + emit "done\n"; + + emit "setpolicy FORWARD DROP\n"; + + emit "deleteallchains\n"; + + for my $hosts ( @criticalhosts ) { + my ( $interface, $host ) = ( split /,/, $hosts ); + + + + } sub generate_script_2 () { + + copy find_file 'prog.functions'; + emit '#'; emit '# Setup Routing and Traffic Shaping'; emit '#'; diff --git a/New/prog.functions b/New/prog.functions index cb3ac7b02..6ff357b2e 100644 --- a/New/prog.functions +++ b/New/prog.functions @@ -16,251 +16,6 @@ delete_proxyarp() { rm -f ${VARDIR}/proxyarp } -# -# Stop/restore the firewall after an error or because of a "stop" or "clear" command -# -stop_firewall() { - - deletechain() { - qt $IPTABLES -L $1 -n && qt $IPTABLES -F $1 && qt $IPTABLES -X $1 - } - - deleteallchains() { - $IPTABLES -F - $IPTABLES -X - } - - setcontinue() { - $IPTABLES -A $1 -m state --state ESTABLISHED,RELATED -j ACCEPT - } - - delete_nat() { - $IPTABLES -t nat -F - $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) - ;; - *) - 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 - - if [ -x ${RESTOREPATH}-ipsets ]; then - progress_message2 Restoring Ipsets... - # - # We must purge iptables to be sure that there are no - # references to ipsets - # - for table in mangle nat filter; do - $IPTABLES -t $table -F - $IPTABLES -t $table -X - done - - ${RESTOREPATH}-ipsets - fi - - 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 - - determine_capabilities - - run_stop_exit - - if [ -n "$MANGLE_ENABLED" ]; then - run_iptables -t mangle -F - run_iptables -t mangle -X - for chain in PREROUTING INPUT FORWARD POSTROUTING; do - qt $IPTABLES -t mangle -P $chain ACCEPT - done - fi - - if [ -n "$RAW_TABLE" ]; then - run_iptables -t raw -F - run_iptables -t raw -X - for chain in PREROUTING OUTPUT; do - qt $IPTABLES -t raw -P $chain ACCEPT - done - fi - - if [ -n "$NAT_ENABLED" ]; then - delete_nat - for chain in PREROUTING POSTROUTING OUTPUT; do - qt $IPTABLES -t nat -P $chain ACCEPT - done - fi - - delete_proxyarp - - [ -n "$CLEAR_TC" ] && delete_tc1 - - [ -n "$DISABLE_IPV6" ] && disable_ipv6 - - undo_routing - - restore_default_route - # - # Fixme -- CRITICALHOSTS handling broken - # - if [ -n "$CRITICALHOSTS" ]; then - if [ -z "$ADMINISABSENTMINDED" ]; then - - for chain in INPUT OUTPUT; do - setpolicy $chain ACCEPT - done - - setpolicy FORWARD DROP - - deleteallchains - - for host in $CRITICALHOSTS; do - interface=${host%:*} - networks=${host#*:} - $IPTABLES -A INPUT -i $interface $(source_ip_range $networks) -j ACCEPT - $IPTABLES -A OUTPUT -o $interface $(dest_ip_range $networks) -j ACCEPT - done - - for chain in INPUT OUTPUT; do - setpolicy $chain DROP - done - else - for chain in INPUT OUTPUT; do - setpolicy $chain ACCEPT - done - - setpolicy FORWARD DROP - - deleteallchains - - for host in $CRITICALHOSTS; do - interface=${host%:*} - networks=${host#*:} - $IPTABLES -A INPUT -i $interface $(source_ip_range $networks) -j ACCEPT - $IPTABLES -A OUTPUT -o $interface $(dest_ip_range $networks) -j ACCEPT - done - - setpolicy INPUT DROP - - for chain in INPUT FORWARD; do - setcontinue $chain - done - fi - elif [ -z "$ADMINISABSENTMINDED" ]; then - for chain in INPUT OUTPUT FORWARD; do - setpolicy $chain DROP - done - - deleteallchains - else - for chain in INPUT FORWARD; do - setpolicy $chain DROP - done - - setpolicy OUTPUT ACCEPT - - deleteallchains - - for chain in INPUT FORWARD; do - setcontinue $chain - done - fi - - $IPTABLES -A INPUT -i lo -j ACCEPT - - [ -z "$ADMINISABSENTMINDED" ] && $IPTABLES -A OUTPUT -o lo -j ACCEPT - - for interface in $DHCP_INTERFACES; do - $IPTABLES -A INPUT -p udp -i $interface --dport 67:68 -j ACCEPT - [ -z "$ADMINISABSENTMINDED" ] && $IPTABLES -A OUTPUT -p udp -o $interface --dport 67:68 -j ACCEPT - # - # This might be a bridge - # - $IPTABLES -A FORWARD -p udp -i $interface -o $interface --dport 67:68 -j ACCEPT - done - - case "$IP_FORWARDING" in - On|on|ON) - echo 1 > /proc/sys/net/ipv4/ip_forward - progress_message2 IP Forwarding Enabled - ;; - Off|off|OFF) - echo 0 > /proc/sys/net/ipv4/ip_forward - progress_message2 IP Forwarding Disabled! - ;; - esac - - run_stopped_exit - - 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. Remove the lock file and Kill the shell in case we're in a - # subshell - # - kill $$ - ;; - esac -} - # # Set policy of chain $1 to $2 #