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
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
#

View File

@ -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;
}
}
#

View File

@ -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{<zone1> => {type = > <zone 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;