diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 832a7330f..1cde3678f 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -225,6 +225,7 @@ our %EXPORT_TAGS = ( handle_network_list expand_rule addnatjump + mysplit set_chain_variables mark_firewall_not_started mark_firewall6_not_started diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index 16005639c..e2cdfed18 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -919,6 +919,7 @@ sub compiler { # call that function during normal 'check', we must validate routestopped here. # process_routestopped; + process_stoppedrules; } if ( $family == F_IPV4 ) { diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index f44eb3b11..61c00766b 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -430,6 +430,7 @@ our %config_files = ( #accounting => 1, started => 1, stop => 1, stopped => 1, + stoppedrules => 1, tcclasses => 1, tcclear => 1, tcdevices => 1, diff --git a/Shorewall/Perl/Shorewall/Misc.pm b/Shorewall/Perl/Shorewall/Misc.pm index 5cc4ed8f4..e7974da63 100644 --- a/Shorewall/Perl/Shorewall/Misc.pm +++ b/Shorewall/Perl/Shorewall/Misc.pm @@ -41,6 +41,7 @@ our @EXPORT = qw( process_tos add_common_rules setup_mac_lists process_routestopped + process_stoppedrules compile_stop_firewall generate_matrix ); @@ -548,9 +549,9 @@ EOF sub process_routestopped() { if ( my $fn = open_file 'routestopped' ) { - my ( @allhosts, %source, %dest , %notrack, @rule ); + my ( @allhosts, %source, %dest , %destonly, %notrack, @rule ); - my $seq = 0; + my $seq = 0; first_entry "$doing $fn..."; @@ -573,12 +574,7 @@ sub process_routestopped() { my $rule = do_proto( $proto, $ports, $sports, 0 ); - for my $host ( split /,/, $hosts ) { - imatch_source_net( $host ); - push @hosts, "$interface|$host|$seq"; - push @rule, $rule; - } - + my $verified; unless ( $options eq '-' ) { for my $option (split /,/, $options ) { @@ -589,13 +585,23 @@ sub process_routestopped() { $routeback = 1; } } elsif ( $option eq 'source' ) { - for my $host ( split /,/, $hosts ) { + $verified = 1; + for my $host ( mysplit $hosts ) { + imatch_source_net( $host ); $source{"$interface|$host|$seq"} = 1; } } elsif ( $option eq 'dest' ) { - for my $host ( split /,/, $hosts ) { + $verified = 1; + for my $host ( mysplit $hosts ) { + imatch_dest_net( $host ); $dest{"$interface|$host|$seq"} = 1; } + } elsif ( $option eq 'destonly' ) { + $verified = 1; + for my $host ( mysplit $hosts ) { + imatch_dest_net( $host ); + $destonly{"$interface|$host|$seq"} = 1; + } } elsif ( $option eq 'notrack' ) { for my $host ( split /,/, $hosts ) { $notrack{"$interface|$host|$seq"} = 1; @@ -610,7 +616,7 @@ sub process_routestopped() { if ( $routeback || $interfaceref->{options}{routeback} ) { my $chainref = $filter_table->{FORWARD}; - for my $host ( split /,/, $hosts ) { + for my $host ( mysplit $hosts ) { add_ijump( $chainref , j => 'ACCEPT', imatch_source_dev( $interface ) , @@ -619,9 +625,21 @@ sub process_routestopped() { imatch_dest_net( $host ) ); clearrule; } + $verified = 1; + } + + for my $host ( mysplit $hosts ) { + unless ( $verified ) { + imatch_source_net( $host ); + imatch_dest_net( $host ); + } + + push @hosts, "$interface|$host|$seq"; + push @rule, $rule; } push @allhosts, @hosts; + } for my $host ( @allhosts ) { @@ -632,7 +650,7 @@ sub process_routestopped() { my $desti = match_dest_dev $interface; my $rule = shift @rule; - add_rule $filter_table->{INPUT}, "$sourcei $source $rule -j ACCEPT", 1; + add_rule $filter_table->{INPUT}, "$sourcei $source $rule -j ACCEPT", 1 unless $destonly{$host}; my $matched = 0; @@ -641,15 +659,20 @@ sub process_routestopped() { $matched = 1; } - if ( $dest{$host} ) { + if ( $dest{$host} || $destonly{$host} ) { add_rule $filter_table->{OUTPUT}, "$desti $dest $rule -j ACCEPT", 1 unless $config{ADMINISABSENTMINDED}; add_rule $filter_table->{FORWARD}, "$desti $dest $rule -j ACCEPT", 1; $matched = 1; } if ( $notrack{$host} ) { - add_rule $raw_table->{PREROUTING}, "$sourcei $source $rule -j NOTRACK", 1; - add_rule $raw_table->{OUTPUT}, "$desti $dest $rule -j NOTRACK", 1; + if ( have_capability 'CT_TARGET' ) { + add_rule $raw_table->{PREROUTING}, "$sourcei $source $rule -j CT --notrack", 1; + add_rule $raw_table->{OUTPUT}, "$desti $dest $rule -j CT --notrack", 1; + } else { + add_rule $raw_table->{PREROUTING}, "$sourcei $source $rule -j NOTRACK", 1; + add_rule $raw_table->{OUTPUT}, "$desti $dest $rule -j NOTRACK", 1; + } } unless ( $matched ) { @@ -667,6 +690,86 @@ sub process_routestopped() { } } +# +# Process the stoppedrules file +# +sub process_stoppedrules() { + my $fw = firewall_zone; + + if ( my $fn = open_file 'stoppedrules' ) { + first_entry "$doing $fn..."; + + while ( read_a_line( NORMAL_READ ) ) { + + my ( $target, $source, $dest, $proto, $ports, $sports ) = + split_line1 'stoppedrules file', { target => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5 }, { COMMENT => 0, FORMAT => 2 }; + + fatal_error( "Invalid TARGET ($target)" ) unless $target =~ /^(?:ACCEPT|NOTRACK)$/; + + my $tableref; + + my $chainref; + my $restriction = NO_RESTRICT; + + if ( $target eq 'NOTRACK' ) { + $tableref = $raw_table; + require_capability 'RAW_TABLE', 'NOTRACK', 's'; + $chainref = $raw_table->{PREROUTING}; + $restriction = PREROUTE_RESTRICT | DESTIFACE_DISALLOW; + } else { + $tableref = $filter_table; + } + + if ( $source eq $fw ) { + $chainref = $tableref->{OUTPUT}; + $source = ''; + $restriction = OUTPUT_RESTRICT; + } + + if ( $source =~ s/^($fw):// ) { + $chainref = $filter_table->{OUTPUT}; + $restriction = OUTPUT_RESTRICT; + } + + if ( $dest eq $fw ) { + fatal_error "\$FW may not be specified as the destination of a NOTRACK rule" if $target eq 'NOTRACK'; + $chainref = $filter_table->{INPUT}; + $dest = ''; + $restriction = INPUT_RESTRICT; + } + + if ( $dest =~ s/^($fw):// ) { + fatal_error "\$FW may not be specified as the destination of a NOTRACK rule" if $target eq 'NOTRACK'; + $chainref = $filter_table->{INPUT}; + $restriction = INPUT_RESTRICT; + } + + $chainref = $tableref->{FORWARD} unless $chainref; + + my $disposition = $target; + + $target = 'CT --notrack' if $target eq 'NOTRACK' and have_capability( 'CT_TARGET' ); + + unless ( $restriction == OUTPUT_RESTRICT + && $target eq 'ACCEPT' + && $config{ADMINISABSENTMINDED} ) { + expand_rule( $chainref , + $restriction , + do_proto( $proto, $ports, $sports ) , + $source , + $dest , + '' , + $target, + '', + $disposition, + do_proto( $proto, '-', '-' ) ); + } + } + } + + clear_comment; +} + sub setup_mss(); sub add_common_rules ( $ ) { @@ -2415,6 +2518,7 @@ EOF } process_routestopped; + process_stoppedrules; add_ijump $input, j => 'ACCEPT', i => 'lo'; add_ijump $output, j => 'ACCEPT', o => 'lo' unless $config{ADMINISABSENTMINDED}; diff --git a/Shorewall/configfiles/routestopped b/Shorewall/configfiles/routestopped index 73b94076d..0586fab0b 100644 --- a/Shorewall/configfiles/routestopped +++ b/Shorewall/configfiles/routestopped @@ -1,6 +1,8 @@ # # Shorewall version 4 - Routestopped File # +# This file is deprecated in favor of the stoppedrules file +# # For information about entries in this file, type "man shorewall-routestopped" # # The manpage is also online at diff --git a/Shorewall/configfiles/stoppedrules b/Shorewall/configfiles/stoppedrules new file mode 100644 index 000000000..65dc3555b --- /dev/null +++ b/Shorewall/configfiles/stoppedrules @@ -0,0 +1,15 @@ +# +# Shorewall version 4 - Stopped Rules File +# +# For information about entries in this file, type "man shorewall-stoppedrules" +# +# The manpage is also online at +# http://www.shorewall.net/manpages/shorewall-stoppedrules.html +# +# See http://shorewall.net/starting_and_stopping_shorewall.htm for additional +# information. +# +FORMAT 2 +############################################################################### +#TARGET SOURCE DEST PROTO DEST SOURCE +# PORT(S) PORT(S) diff --git a/Shorewall6/configfiles/routestopped b/Shorewall6/configfiles/routestopped index d81110bcc..d7dd252fa 100644 --- a/Shorewall6/configfiles/routestopped +++ b/Shorewall6/configfiles/routestopped @@ -1,6 +1,8 @@ # # Shorewall6 version 4 - Routestopped File # +# This file is deprecated in favor of the stoppedrules file. +# # For information about entries in this file, type "man shorewall6-routestopped" # # The manpage is also online at diff --git a/Shorewall6/configfiles/stoppedrules b/Shorewall6/configfiles/stoppedrules new file mode 100644 index 000000000..501000d32 --- /dev/null +++ b/Shorewall6/configfiles/stoppedrules @@ -0,0 +1,15 @@ +# +# Shorewall6 version 4 - Stopped Rules File +# +# For information about entries in this file, type "man shorewall6-stoppedrules" +# +# The manpage is also online at +# http://www.shorewall.net/manpages/shorewall6-stoppedrules.html +# +# See http://shorewall.net/starting_and_stopping_shorewall.htm for additional +# information. +# +FORMAT 2 +############################################################################### +#TARGET SOURCE DEST PROTO DEST SOURCE +# PORT(S) PORT(S)