Ruleset optimization -- phase I

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@8100 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2008-01-24 16:22:03 +00:00
parent 459812507a
commit 65df4d9f73
3 changed files with 52 additions and 92 deletions

View File

@ -75,8 +75,11 @@ our %EXPORT_TAGS = (
decr_cmd_level decr_cmd_level
chain_base chain_base
forward_chain forward_chain
zone_forward_chain
input_chain input_chain
zone_input_chain
output_chain output_chain
zone_output_chain
masq_chain masq_chain
syn_flood_chain syn_flood_chain
mac_chain mac_chain
@ -510,6 +513,13 @@ sub forward_chain($)
chain_base_cond($_[0]) . '_fwd'; chain_base_cond($_[0]) . '_fwd';
} }
#
# Forward Chain for a zone
#
sub zone_forward_chain($) {
chain_base($_[0]) . '_frwd';
}
# #
# Input Chain for an interface # Input Chain for an interface
# #
@ -518,6 +528,13 @@ sub input_chain($)
chain_base_cond($_[0]) . '_in'; chain_base_cond($_[0]) . '_in';
} }
#
# Input Chain for a zone
#
sub zone_input_chain($) {
chain_base($_[0]) . '_input';
}
# #
# Output Chain for an interface # Output Chain for an interface
# #
@ -526,6 +543,13 @@ sub output_chain($)
chain_base_cond($_[0]) . '_out'; chain_base_cond($_[0]) . '_out';
} }
#
# Output Chain for a zone
#
sub zone_output_chain($) {
chain_base($_[0]) . '_output';
}
# #
# Masquerade Chain for an interface # Masquerade Chain for an interface
# #

View File

@ -1498,16 +1498,16 @@ sub generate_matrix() {
my $preroutingref = ensure_chain 'nat', 'dnat'; my $preroutingref = ensure_chain 'nat', 'dnat';
my $fw = firewall_zone; my $fw = firewall_zone;
# #
# Special processing for complex zones # Set up forwarding chain for each zone
# #
for my $zone ( complex_zones ) { for my $zone ( non_firewall_zones ) {
my $frwd_ref = new_standard_chain "${zone}_frwd"; my $frwd_ref = new_standard_chain zone_forward_chain( $zone );
my $zoneref = find_zone( $zone ); my $zoneref = find_zone( $zone );
my $exclusions = $zoneref->{exclusions}; my $exclusions = $zoneref->{exclusions};
if ( @$exclusions ) { if ( @$exclusions ) {
my $in_ref = new_standard_chain "${zone}_input"; my $in_ref = new_standard_chain zone_input_chain $zone;
my $out_ref = new_standard_chain "${zone}_output"; 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'; 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 $chain1 = rules_target firewall_zone , $zone;
my $chain2 = rules_target $zone, firewall_zone; my $chain2 = rules_target $zone, firewall_zone;
my $chain3 = rules_target $zone, $zone; my $chain3 = rules_target $zone, $zone;
my $complex = $zoneref->{options}{complex} || 0;
my $type = $zoneref->{type}; my $type = $zoneref->{type};
my $exclusions = $zoneref->{exclusions}; my $exclusions = $zoneref->{exclusions};
my $frwd_ref = 0; my $frwd_ref = $filter_table->{ zone_forward_chain $zone };
my $chain = 0; my $chain = 0;
my $dnatref = $nat_table->{dnat_chain $zone} || {}; my $dnatref = ensure_chain 'nat' , dnat_chain( $zone );
my $nested = $zoneref->{options}{nested}; my $nested = $zoneref->{options}{nested};
if ( $complex ) { if ( @$exclusions ) {
$frwd_ref = $filter_table->{"${zone}_frwd"}; insert_exclusions $dnatref, $exclusions if $dnatref->{referenced};
$dnatref = ensure_chain 'nat' , dnat_chain( $zone );
if ( @$exclusions ) {
insert_exclusions $dnatref, $exclusions if $dnatref->{referenced};
}
} }
if ( $config{DYNAMIC_ZONES} ) { if ( $config{DYNAMIC_ZONES} ) {
@ -1625,9 +1620,10 @@ sub generate_matrix() {
my $outputref = $filter_table->{output_chain $interface}; my $outputref = $filter_table->{output_chain $interface};
if ( @$exclusions ) { if ( @$exclusions ) {
add_rule $outputref , join( '', $dest, $ipsec_out_match, "-j ${zone}_output" ); my $output = zone_output_chain $zone;
add_rule $filter_table->{"${zone}_output"} , "-j $chain1"; add_rule $outputref , join( '', $dest, $ipsec_out_match, "-j $output" );
$nextchain = "${zone}_output"; add_rule $filter_table->{$output} , "-j $chain1";
$nextchain = $output;
} else { } else {
add_rule $outputref , join( '', $dest, $ipsec_out_match, "-j $chain1" ); add_rule $outputref , join( '', $dest, $ipsec_out_match, "-j $chain1" );
$nextchain = $chain1; $nextchain = $chain1;
@ -1656,15 +1652,16 @@ sub generate_matrix() {
if ( $chain2 ) { if ( $chain2 ) {
if ( @$exclusions ) { if ( @$exclusions ) {
add_rule $filter_table->{input_chain $interface}, join( '', $source, $ipsec_in_match, "-j ${zone}_input" ); my $input = zone_input_chain $zone;
add_rule $filter_table->{"${zone}_input"} , "-j $chain2"; add_rule $filter_table->{input_chain $interface}, join( '', $source, $ipsec_in_match, "-j $input" );
add_rule $filter_table->{ $input } , "-j $chain2";
} else { } else {
add_rule $filter_table->{input_chain $interface}, join( '', $source, $ipsec_in_match, "-j $chain2" ); 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}" ) 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 $typeref ( values %$dest_hosts_ref ) { for my $interface ( keys %$typeref ) {
for my $interface ( keys %$typeref ) { my $arrayref = $typeref->{$interface};
my $arrayref = $typeref->{$interface}; for my $hostref ( @$arrayref ) {
for my $hostref ( @$arrayref ) { next if $hostref->{options}{sourceonly};
next if $hostref->{options}{sourceonly}; if ( $zone ne $zone1 || $num_ifaces > 1 || $hostref->{options}{routeback} ) {
if ( $zone ne $zone1 || $num_ifaces > 1 || $hostref->{options}{routeback} ) { my $ipsec_out_match = match_ipsec_out $zone1 , $hostref;
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 $net ( @{$hostref->{hosts}} ) { for my $net ( @{$hostref->{hosts}} ) {
for my $type1ref ( values %$dest_hosts_ref ) { add_rule $frwd_ref, join( '', match_dest_dev( $interface) , match_dest_net($net), $ipsec_out_match, "-j $chain" );
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" )
);
}
}
}
}
}
} }
} }
} }
@ -1832,25 +1795,9 @@ sub generate_matrix() {
# #
# E N D F O R W A R D I N G # 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 ) { add_rule $frwd_ref , "-j $last_chain" 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";
}
}
}
}
}
}
} }
} }
# #

View File

@ -45,7 +45,6 @@ our @EXPORT = qw( NOTHING
defined_zone defined_zone
zone_type zone_type
all_zones all_zones
complex_zones
non_firewall_zones non_firewall_zones
single_interface single_interface
validate_interfaces_file 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 contains the ordered list of zones with sub-zones appearing before their parents.
# #
# %zones{<zone1> => {type = > <zone type> 'firewall', 'ipv4', 'ipsec4', 'bport4'; # %zones{<zone1> => {type = > <zone type> 'firewall', 'ipv4', 'ipsec4', 'bport4';
# options => { complex => 0|1 # options => { nested => 0|1
# nested => 0|1
# in_out => < policy match string > # in_out => < policy match string >
# in => < policy match string > # in => < policy match string >
# out => < policy match string > # out => < policy match string >
@ -299,7 +297,6 @@ sub determine_zones()
options => { in_out => parse_zone_option_list( $options || '', $type ) , options => { in_out => parse_zone_option_list( $options || '', $type ) ,
in => parse_zone_option_list( $in_options || '', $type ) , in => parse_zone_option_list( $in_options || '', $type ) ,
out => parse_zone_option_list( $out_options || '', $type ) , out => parse_zone_option_list( $out_options || '', $type ) ,
complex => ($type eq 'ipsec4' || $options || $in_options || $out_options ? 1 : 0) ,
nested => @parents > 0 } , nested => @parents > 0 } ,
interfaces => {} , interfaces => {} ,
children => [] , children => [] ,
@ -495,8 +492,6 @@ sub add_group_to_zone($$$$$)
$interfaceref = ( $typeref->{$type} || ( $interfaceref = $typeref->{$type} = {} ) ); $interfaceref = ( $typeref->{$type} || ( $interfaceref = $typeref->{$type} = {} ) );
$arrayref = ( $interfaceref->{$interface} || ( $interfaceref->{$interface} = [] ) ); $arrayref = ( $interfaceref->{$interface} || ( $interfaceref->{$interface} = [] ) );
$zoneref->{options}{complex} = 1 if @$arrayref || ( @newnetworks > 1 ) || ( @exclusions );
push @{$zoneref->{exclusions}}, @exclusions; push @{$zoneref->{exclusions}}, @exclusions;
push @{$arrayref}, { options => $options, push @{$arrayref}, { options => $options,
@ -534,10 +529,6 @@ sub non_firewall_zones() {
grep ( $zones{$_}{type} ne 'firewall' , @zones ); grep ( $zones{$_}{type} ne 'firewall' , @zones );
} }
sub complex_zones() {
grep( $zones{$_}{options}{complex} , @zones );
}
sub firewall_zone() { sub firewall_zone() {
$firewall_zone; $firewall_zone;
} }
@ -923,7 +914,6 @@ sub validate_hosts_file()
if ( $hosts =~ /^([\w.@%-]+\+?):(.*)$/ ) { if ( $hosts =~ /^([\w.@%-]+\+?):(.*)$/ ) {
$interface = $1; $interface = $1;
$hosts = $2; $hosts = $2;
$zoneref->{options}{complex} = 1 if $hosts =~ /^\+/;
fatal_error "Unknown interface ($interface)" unless $interfaces{$interface}{root}; fatal_error "Unknown interface ($interface)" unless $interfaces{$interface}{root};
} else { } else {
fatal_error "Invalid HOST(S) column contents: $hosts"; fatal_error "Invalid HOST(S) column contents: $hosts";
@ -948,7 +938,6 @@ sub validate_hosts_file()
{ {
if ( $option eq 'ipsec' ) { if ( $option eq 'ipsec' ) {
$type = 'ipsec4'; $type = 'ipsec4';
$zoneref->{options}{complex} = 1;
$ipsec = 1; $ipsec = 1;
} elsif ( $validoptions{$option}) { } elsif ( $validoptions{$option}) {
$options{$option} = 1; $options{$option} = 1;