From 65df4d9f73e14e1edcb5c190f04c9c895152ff26 Mon Sep 17 00:00:00 2001 From: teastep Date: Thu, 24 Jan 2008 16:22:03 +0000 Subject: [PATCH] Ruleset optimization -- phase I git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@8100 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb --- Shorewall-perl/Shorewall/Chains.pm | 24 +++++++ Shorewall-perl/Shorewall/Rules.pm | 107 ++++++++--------------------- Shorewall-perl/Shorewall/Zones.pm | 13 +--- 3 files changed, 52 insertions(+), 92 deletions(-) diff --git a/Shorewall-perl/Shorewall/Chains.pm b/Shorewall-perl/Shorewall/Chains.pm index 35145b2d4..816560c05 100644 --- a/Shorewall-perl/Shorewall/Chains.pm +++ b/Shorewall-perl/Shorewall/Chains.pm @@ -75,8 +75,11 @@ our %EXPORT_TAGS = ( decr_cmd_level chain_base forward_chain + zone_forward_chain input_chain + zone_input_chain output_chain + zone_output_chain masq_chain syn_flood_chain mac_chain @@ -510,6 +513,13 @@ sub forward_chain($) chain_base_cond($_[0]) . '_fwd'; } +# +# Forward Chain for a zone +# +sub zone_forward_chain($) { + chain_base($_[0]) . '_frwd'; +} + # # Input Chain for an interface # @@ -518,6 +528,13 @@ sub input_chain($) chain_base_cond($_[0]) . '_in'; } +# +# Input Chain for a zone +# +sub zone_input_chain($) { + chain_base($_[0]) . '_input'; +} + # # Output Chain for an interface # @@ -526,6 +543,13 @@ sub output_chain($) chain_base_cond($_[0]) . '_out'; } +# +# Output Chain for a zone +# +sub zone_output_chain($) { + chain_base($_[0]) . '_output'; +} + # # Masquerade Chain for an interface # diff --git a/Shorewall-perl/Shorewall/Rules.pm b/Shorewall-perl/Shorewall/Rules.pm index cb54a3790..af9d9806d 100644 --- a/Shorewall-perl/Shorewall/Rules.pm +++ b/Shorewall-perl/Shorewall/Rules.pm @@ -1498,16 +1498,16 @@ sub generate_matrix() { my $preroutingref = ensure_chain 'nat', 'dnat'; my $fw = firewall_zone; # - # Special processing for complex zones + # Set up forwarding chain for each zone # - for my $zone ( complex_zones ) { - my $frwd_ref = new_standard_chain "${zone}_frwd"; + for my $zone ( non_firewall_zones ) { + my $frwd_ref = new_standard_chain zone_forward_chain( $zone ); my $zoneref = find_zone( $zone ); my $exclusions = $zoneref->{exclusions}; if ( @$exclusions ) { - my $in_ref = new_standard_chain "${zone}_input"; - my $out_ref = new_standard_chain "${zone}_output"; + my $in_ref = new_standard_chain zone_input_chain $zone; + my $out_ref = new_standard_chain zone_output_chain $zone; add_rule ensure_filter_chain( "${zone}2${zone}", 1 ) , '-j ACCEPT' if rules_target( $zone, $zone ) eq 'ACCEPT'; @@ -1552,20 +1552,15 @@ sub generate_matrix() { my $chain1 = rules_target firewall_zone , $zone; my $chain2 = rules_target $zone, firewall_zone; my $chain3 = rules_target $zone, $zone; - my $complex = $zoneref->{options}{complex} || 0; my $type = $zoneref->{type}; my $exclusions = $zoneref->{exclusions}; - my $frwd_ref = 0; + my $frwd_ref = $filter_table->{ zone_forward_chain $zone }; my $chain = 0; - my $dnatref = $nat_table->{dnat_chain $zone} || {}; + my $dnatref = ensure_chain 'nat' , dnat_chain( $zone ); my $nested = $zoneref->{options}{nested}; - if ( $complex ) { - $frwd_ref = $filter_table->{"${zone}_frwd"}; - $dnatref = ensure_chain 'nat' , dnat_chain( $zone ); - if ( @$exclusions ) { - insert_exclusions $dnatref, $exclusions if $dnatref->{referenced}; - } + if ( @$exclusions ) { + insert_exclusions $dnatref, $exclusions if $dnatref->{referenced}; } if ( $config{DYNAMIC_ZONES} ) { @@ -1625,9 +1620,10 @@ sub generate_matrix() { my $outputref = $filter_table->{output_chain $interface}; if ( @$exclusions ) { - add_rule $outputref , join( '', $dest, $ipsec_out_match, "-j ${zone}_output" ); - add_rule $filter_table->{"${zone}_output"} , "-j $chain1"; - $nextchain = "${zone}_output"; + my $output = zone_output_chain $zone; + add_rule $outputref , join( '', $dest, $ipsec_out_match, "-j $output" ); + add_rule $filter_table->{$output} , "-j $chain1"; + $nextchain = $output; } else { add_rule $outputref , join( '', $dest, $ipsec_out_match, "-j $chain1" ); $nextchain = $chain1; @@ -1656,15 +1652,16 @@ sub generate_matrix() { if ( $chain2 ) { if ( @$exclusions ) { - add_rule $filter_table->{input_chain $interface}, join( '', $source, $ipsec_in_match, "-j ${zone}_input" ); - add_rule $filter_table->{"${zone}_input"} , "-j $chain2"; + my $input = zone_input_chain $zone; + add_rule $filter_table->{input_chain $interface}, join( '', $source, $ipsec_in_match, "-j $input" ); + add_rule $filter_table->{ $input } , "-j $chain2"; } else { add_rule $filter_table->{input_chain $interface}, join( '', $source, $ipsec_in_match, "-j $chain2" ); } } add_rule $filter_table->{forward_chain $interface} , join( '', $source, $ipsec_in_match. "-j $frwd_ref->{name}" ) - if $complex && $hostref->{ipsec} ne 'ipsec'; + if $hostref->{ipsec} ne 'ipsec'; } } } @@ -1781,49 +1778,15 @@ sub generate_matrix() { } } - if ( $complex ) { - for my $typeref ( values %$dest_hosts_ref ) { - for my $interface ( keys %$typeref ) { - my $arrayref = $typeref->{$interface}; - for my $hostref ( @$arrayref ) { - next if $hostref->{options}{sourceonly}; - if ( $zone ne $zone1 || $num_ifaces > 1 || $hostref->{options}{routeback} ) { - my $ipsec_out_match = match_ipsec_out $zone1 , $hostref; - for my $net ( @{$hostref->{hosts}} ) { - add_rule $frwd_ref, join( '', match_dest_dev( $interface) , match_dest_net($net), $ipsec_out_match, "-j $chain" ); - } - } - } - } - } - } else { - for my $typeref ( values %$source_hosts_ref ) { - for my $interface ( keys %$typeref ) { - my $arrayref = $typeref->{$interface}; - my $chain3ref = $filter_table->{forward_chain $interface}; - for my $hostref ( @$arrayref ) { - next if $hostref->{options}{destonly}; + for my $typeref ( values %$dest_hosts_ref ) { + for my $interface ( keys %$typeref ) { + my $arrayref = $typeref->{$interface}; + for my $hostref ( @$arrayref ) { + next if $hostref->{options}{sourceonly}; + if ( $zone ne $zone1 || $num_ifaces > 1 || $hostref->{options}{routeback} ) { + my $ipsec_out_match = match_ipsec_out $zone1 , $hostref; for my $net ( @{$hostref->{hosts}} ) { - for my $type1ref ( values %$dest_hosts_ref ) { - for my $interface1 ( keys %$type1ref ) { - my $array1ref = $type1ref->{$interface1}; - for my $host1ref ( @$array1ref ) { - next if $host1ref->{options}{sourceonly}; - my $ipsec_out_match = match_ipsec_out $zone1 , $host1ref; - for my $net1 ( @{$host1ref->{hosts}} ) { - unless ( $interface eq $interface1 && $net eq $net1 && ! $host1ref->{options}{routeback} ) { - # - # We defer evaluation of the source net match to accomodate systems without $capabilities{KLUDEFREE}; - # - add_rule( - $chain3ref , - join( '', match_dest_dev($interface1), match_source_net($net), match_dest_net($net1), $ipsec_out_match, "-j $chain" ) - ); - } - } - } - } - } + add_rule $frwd_ref, join( '', match_dest_dev( $interface) , match_dest_net($net), $ipsec_out_match, "-j $chain" ); } } } @@ -1832,25 +1795,9 @@ sub generate_matrix() { # # E N D F O R W A R D I N G # - # Now add (an) unconditional jump(s) to the last unique policy-only chain determined above, if any + # Now add an unconditional jump to the last unique policy-only chain determined above, if any # - if ( $last_chain ) { - if ( $complex ) { - add_rule $frwd_ref , "-j $last_chain"; - } else { - for my $typeref ( values %$source_hosts_ref ) { - for my $interface ( keys %$typeref ) { - my $arrayref = $typeref->{$interface}; - my $chain2ref = $filter_table->{forward_chain $interface}; - for my $hostref ( @$arrayref ) { - for my $net ( @{$hostref->{hosts}} ) { - add_rule $chain2ref, match_source_net($net) . "-j $last_chain"; - } - } - } - } - } - } + add_rule $frwd_ref , "-j $last_chain" if $last_chain; } } # diff --git a/Shorewall-perl/Shorewall/Zones.pm b/Shorewall-perl/Shorewall/Zones.pm index 8fbeab0fc..b213b67a1 100644 --- a/Shorewall-perl/Shorewall/Zones.pm +++ b/Shorewall-perl/Shorewall/Zones.pm @@ -45,7 +45,6 @@ our @EXPORT = qw( NOTHING defined_zone zone_type all_zones - complex_zones non_firewall_zones single_interface validate_interfaces_file @@ -82,8 +81,7 @@ use constant { NOTHING => 'NOTHING', # @zones contains the ordered list of zones with sub-zones appearing before their parents. # # %zones{ => {type = > 'firewall', 'ipv4', 'ipsec4', 'bport4'; -# options => { complex => 0|1 -# nested => 0|1 +# options => { nested => 0|1 # in_out => < policy match string > # in => < policy match string > # out => < policy match string > @@ -299,7 +297,6 @@ sub determine_zones() options => { in_out => parse_zone_option_list( $options || '', $type ) , in => parse_zone_option_list( $in_options || '', $type ) , out => parse_zone_option_list( $out_options || '', $type ) , - complex => ($type eq 'ipsec4' || $options || $in_options || $out_options ? 1 : 0) , nested => @parents > 0 } , interfaces => {} , children => [] , @@ -495,8 +492,6 @@ sub add_group_to_zone($$$$$) $interfaceref = ( $typeref->{$type} || ( $interfaceref = $typeref->{$type} = {} ) ); $arrayref = ( $interfaceref->{$interface} || ( $interfaceref->{$interface} = [] ) ); - $zoneref->{options}{complex} = 1 if @$arrayref || ( @newnetworks > 1 ) || ( @exclusions ); - push @{$zoneref->{exclusions}}, @exclusions; push @{$arrayref}, { options => $options, @@ -534,10 +529,6 @@ sub non_firewall_zones() { grep ( $zones{$_}{type} ne 'firewall' , @zones ); } -sub complex_zones() { - grep( $zones{$_}{options}{complex} , @zones ); -} - sub firewall_zone() { $firewall_zone; } @@ -923,7 +914,6 @@ sub validate_hosts_file() if ( $hosts =~ /^([\w.@%-]+\+?):(.*)$/ ) { $interface = $1; $hosts = $2; - $zoneref->{options}{complex} = 1 if $hosts =~ /^\+/; fatal_error "Unknown interface ($interface)" unless $interfaces{$interface}{root}; } else { fatal_error "Invalid HOST(S) column contents: $hosts"; @@ -948,7 +938,6 @@ sub validate_hosts_file() { if ( $option eq 'ipsec' ) { $type = 'ipsec4'; - $zoneref->{options}{complex} = 1; $ipsec = 1; } elsif ( $validoptions{$option}) { $options{$option} = 1;