forked from extern/shorewall_code
Break up generate_matrix()
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
49050e61de
commit
fe7d0730d5
@ -1443,46 +1443,16 @@ sub add_interface_jumps {
|
|||||||
handle_loopback_traffic;
|
handle_loopback_traffic;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Generate the rules matrix.
|
|
||||||
#
|
#
|
||||||
# Stealing a comment from the Burroughs B6700 MCP Operating System source, "generate_matrix makes a sow's ear out of a silk purse".
|
# Do the initial matrix processing for a complex zone
|
||||||
#
|
#
|
||||||
# The biggest disadvantage of the zone-policy-rule model used by Shorewall is that it doesn't scale well as the number of zones increases (Order N**2 where N = number of zones).
|
sub handle_complex_zone( $$ ) {
|
||||||
# A major goal of the rewrite of the compiler in Perl was to restrict those scaling effects to this function and the rules that it generates.
|
my ( $zone, $zoneref ) = @_;
|
||||||
#
|
|
||||||
# The function traverses the full "source-zone by destination-zone" matrix and generates the rules necessary to direct traffic through the right set of filter-table and
|
|
||||||
# nat-table rules.
|
|
||||||
#
|
|
||||||
sub generate_matrix() {
|
|
||||||
my @interfaces = ( all_interfaces );
|
|
||||||
#
|
|
||||||
# Should this be the real PREROUTING chain?
|
|
||||||
#
|
|
||||||
my $preroutingref = ensure_chain 'nat', 'dnat';
|
|
||||||
|
|
||||||
my $fw = firewall_zone;
|
our %input_jump_added;
|
||||||
my @zones = off_firewall_zones;
|
our %output_jump_added;
|
||||||
my @vservers = vserver_zones;
|
our %forward_jump_added;
|
||||||
|
our %ipsec_jump_added;
|
||||||
my $notrackref = $raw_table->{notrack_chain $fw};
|
|
||||||
my @state = $config{BLACKLISTNEWONLY} ? $globals{UNTRACKED} ? state_imatch 'NEW,INVALID,UNTRACKED' : state_imatch 'NEW,INVALID' : ();
|
|
||||||
my $interface_jumps_added = 0;
|
|
||||||
|
|
||||||
our %input_jump_added = ();
|
|
||||||
our %output_jump_added = ();
|
|
||||||
our %forward_jump_added = ();
|
|
||||||
my %ipsec_jump_added = ();
|
|
||||||
|
|
||||||
progress_message2 'Generating Rule Matrix...';
|
|
||||||
progress_message ' Handling complex zones...';
|
|
||||||
|
|
||||||
#
|
|
||||||
# Special processing for configurations with more than 2 off-firewall zones or with other special considerations like IPSEC.
|
|
||||||
#
|
|
||||||
for my $zone ( @zones ) {
|
|
||||||
my $zoneref = find_zone( $zone );
|
|
||||||
|
|
||||||
next if @zones <= 2 && ! $zoneref->{complex};
|
|
||||||
#
|
#
|
||||||
# Complex zone or we have more than two off-firewall zones -- Shorewall::Rules::classic_blacklist created a zone forwarding chain
|
# Complex zone or we have more than two off-firewall zones -- Shorewall::Rules::classic_blacklist created a zone forwarding chain
|
||||||
#
|
#
|
||||||
@ -1555,41 +1525,24 @@ sub generate_matrix() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# The passed zone is a sub-zone. We need to determine if
|
||||||
|
#
|
||||||
|
# a) A parent zone defines DNAT/REDIRECT or notrack rules; and
|
||||||
|
# b) The current zone has a CONTINUE policy to some other zone.
|
||||||
|
#
|
||||||
|
# If a) but not b), then we must avoid sending packets from this
|
||||||
|
# zone through the DNAT/REDIRECT or notrack chain for the parent.
|
||||||
|
#
|
||||||
|
sub handle_nested_zone( $$ ) {
|
||||||
|
my ( $zone, $zoneref ) = @_;
|
||||||
#
|
#
|
||||||
# NOTRACK from firewall
|
# Function returns this 3-tuple
|
||||||
#
|
#
|
||||||
add_ijump $raw_table->{OUTPUT}, j => $notrackref if $notrackref->{referenced};
|
my ( $nested, $parenthasnat, $parenthasnotrack ) = ( 1, 0, 0 );
|
||||||
#
|
|
||||||
# Main source-zone matrix-generation loop
|
|
||||||
#
|
|
||||||
progress_message ' Entering main matrix-generation loop...';
|
|
||||||
|
|
||||||
for my $zone ( @zones ) {
|
|
||||||
my $zoneref = find_zone( $zone );
|
|
||||||
my $source_hosts_ref = $zoneref->{hosts};
|
|
||||||
my $chain1 = rules_target firewall_zone , $zone;
|
|
||||||
my $chain2 = rules_target $zone, firewall_zone;
|
|
||||||
my $type = $zoneref->{type};
|
|
||||||
my $frwd_ref = $filter_table->{zone_forward_chain $zone};
|
|
||||||
my $chain = 0;
|
|
||||||
my $dnatref = ensure_chain 'nat' , dnat_chain( $zone );
|
|
||||||
my $notrackref = ensure_chain 'raw' , notrack_chain( $zone );
|
|
||||||
my $nested = @{$zoneref->{parents}};
|
|
||||||
my $parenthasnat = 0;
|
|
||||||
my $parenthasnotrack = 0;
|
|
||||||
|
|
||||||
if ( $nested ) {
|
|
||||||
#
|
|
||||||
# This is a sub-zone. We need to determine if
|
|
||||||
#
|
|
||||||
# a) A parent zone defines DNAT/REDIRECT or notrack rules; and
|
|
||||||
# b) The current zone has a CONTINUE policy to some other zone.
|
|
||||||
#
|
|
||||||
# If a) but not b), then we must avoid sending packets from this
|
|
||||||
# zone through the DNAT/REDIRECT or notrack chain for the parent.
|
|
||||||
#
|
|
||||||
for my $parent ( @{$zoneref->{parents}} ) {
|
for my $parent ( @{$zoneref->{parents}} ) {
|
||||||
my $ref1 = $nat_table->{dnat_chain $parent} || {};
|
my $ref1 = $nat_table->{dnat_chain $parent} || {};
|
||||||
my $ref2 = $raw_table->{notrack_chain $parent} || {};
|
my $ref2 = $raw_table->{notrack_chain $parent} || {};
|
||||||
@ -1615,23 +1568,36 @@ sub generate_matrix() {
|
|||||||
#
|
#
|
||||||
$nested = 0;
|
$nested = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#
|
( $nested, $parenthasnat, $parenthasnotrack );
|
||||||
# Take care of PREROUTING, INPUT and OUTPUT jumps
|
}
|
||||||
#
|
|
||||||
for my $typeref ( values %$source_hosts_ref ) {
|
#
|
||||||
for my $interface ( sort { interface_number( $a ) <=> interface_number( $b ) } keys %$typeref ) {
|
# Generate the PREROUTING, INPUT and OUTPUT jumps for the passed ($zone:$typeref:$interface)
|
||||||
|
#
|
||||||
|
sub handle_pio_jumps( $$$$$$$$ ) {
|
||||||
|
my ( $zone,
|
||||||
|
$zoneref,
|
||||||
|
$typeref,
|
||||||
|
$interface,
|
||||||
|
$nested,
|
||||||
|
$parenthasnat,
|
||||||
|
$parenthasnotrack,
|
||||||
|
$frwd_ref,
|
||||||
|
) = @_;
|
||||||
|
|
||||||
|
our @vservers;
|
||||||
|
our %input_jump_added;
|
||||||
|
our %output_jump_added;
|
||||||
|
our %forward_jump_added;
|
||||||
|
|
||||||
my $arrayref = $typeref->{$interface};
|
my $arrayref = $typeref->{$interface};
|
||||||
my $interfaceref = find_interface $interface;
|
my $interfaceref = find_interface $interface;
|
||||||
my $isport = $interfaceref->{options}{port};
|
my $isport = $interfaceref->{options}{port};
|
||||||
my $bridge = $interfaceref->{bridge};
|
my $bridge = $interfaceref->{bridge};
|
||||||
|
my $notrackref = ensure_chain 'raw' , notrack_chain( $zone );
|
||||||
if ( get_physical( $interface ) eq '+' ) {
|
my $chain1 = rules_target firewall_zone , $zone;
|
||||||
#
|
my $chain2 = rules_target $zone, firewall_zone;
|
||||||
# Insert the interface-specific jumps before this one which is not interface-specific
|
|
||||||
#
|
|
||||||
add_interface_jumps(@interfaces) unless $interface_jumps_added++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for my $hostref ( @$arrayref ) {
|
for my $hostref ( @$arrayref ) {
|
||||||
my @ipsec_in_match = match_ipsec_in $zone , $hostref;
|
my @ipsec_in_match = match_ipsec_in $zone , $hostref;
|
||||||
@ -1640,8 +1606,13 @@ sub generate_matrix() {
|
|||||||
|
|
||||||
for my $net ( @{$hostref->{hosts}} ) {
|
for my $net ( @{$hostref->{hosts}} ) {
|
||||||
my @dest = imatch_dest_net $net;
|
my @dest = imatch_dest_net $net;
|
||||||
|
#
|
||||||
|
# OUTPUT
|
||||||
|
#
|
||||||
if ( $chain1 && ! ( zone_type( $zone) & BPORT ) ) {
|
if ( $chain1 && ! ( zone_type( $zone) & BPORT ) ) {
|
||||||
|
#
|
||||||
|
# Policy from the firewall to this zone is not 'CONTINUE' and this isn't a bport zone
|
||||||
|
#
|
||||||
my $chain1ref = $filter_table->{$chain1};
|
my $chain1ref = $filter_table->{$chain1};
|
||||||
my $nextchain = dest_exclusion( $exclusions, $chain1 );
|
my $nextchain = dest_exclusion( $exclusions, $chain1 );
|
||||||
my $outputref;
|
my $outputref;
|
||||||
@ -1686,7 +1657,12 @@ sub generate_matrix() {
|
|||||||
|
|
||||||
clearrule;
|
clearrule;
|
||||||
|
|
||||||
next if $hostref->{options}{destonly};
|
unless( $hostref->{options}{destonly} ) {
|
||||||
|
#
|
||||||
|
# PREROUTING
|
||||||
|
#
|
||||||
|
my $dnatref = ensure_chain 'nat' , dnat_chain( $zone );
|
||||||
|
my $preroutingref = ensure_chain 'nat', 'dnat';
|
||||||
|
|
||||||
my @source = imatch_source_net $net;
|
my @source = imatch_source_net $net;
|
||||||
|
|
||||||
@ -1727,7 +1703,9 @@ sub generate_matrix() {
|
|||||||
add_ijump $preroutingref, j => 'RETURN', imatch_source_dev( $interface), @source, @ipsec_in_match if $parenthasnat;
|
add_ijump $preroutingref, j => 'RETURN', imatch_source_dev( $interface), @source, @ipsec_in_match if $parenthasnat;
|
||||||
add_ijump $raw_table->{PREROUTING}, j => 'RETURN', imatch_source_dev( $interface), @source, @ipsec_in_match if $parenthasnotrack;
|
add_ijump $raw_table->{PREROUTING}, j => 'RETURN', imatch_source_dev( $interface), @source, @ipsec_in_match if $parenthasnotrack;
|
||||||
}
|
}
|
||||||
|
#
|
||||||
|
# INPUT
|
||||||
|
#
|
||||||
my $chain2ref = $filter_table->{$chain2};
|
my $chain2ref = $filter_table->{$chain2};
|
||||||
my $inputchainref;
|
my $inputchainref;
|
||||||
my $interfacechainref = $filter_table->{input_chain $interface};
|
my $interfacechainref = $filter_table->{input_chain $interface};
|
||||||
@ -1795,22 +1773,23 @@ sub generate_matrix() {
|
|||||||
|
|
||||||
move_rules ( $forwardref , $frwd_ref );
|
move_rules ( $forwardref , $frwd_ref );
|
||||||
}
|
}
|
||||||
}
|
} # Complex non-IPSEC host group
|
||||||
}
|
} # Not a destonly host group
|
||||||
}
|
} # Network Loop
|
||||||
}
|
} # Host Group Loop
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# F O R W A R D I N G
|
# Generate the list of destination zones from the passed source zone when optimization level 1 is selected
|
||||||
#
|
#
|
||||||
my @dest_zones;
|
sub optimize1_zones( $$@ ) {
|
||||||
|
my $zone = shift;
|
||||||
|
my $zoneref = shift;
|
||||||
my $last_chain = '';
|
my $last_chain = '';
|
||||||
|
my @dest_zones;
|
||||||
if ( $config{OPTIMIZE} & 1 ) {
|
|
||||||
my @temp_zones;
|
my @temp_zones;
|
||||||
|
|
||||||
for my $zone1 ( @zones ) {
|
for my $zone1 ( @_ ) {
|
||||||
my $zone1ref = find_zone( $zone1 );
|
my $zone1ref = find_zone( $zone1 );
|
||||||
my $policy = $filter_table->{rules_chain( ${zone}, ${zone1} )}->{policy};
|
my $policy = $filter_table->{rules_chain( ${zone}, ${zone1} )}->{policy};
|
||||||
|
|
||||||
@ -1850,6 +1829,96 @@ sub generate_matrix() {
|
|||||||
push @dest_zones, @temp_zones;
|
push @dest_zones, @temp_zones;
|
||||||
$last_chain = '';
|
$last_chain = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
( $last_chain, @dest_zones );
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate the rules matrix.
|
||||||
|
#
|
||||||
|
# Stealing a comment from the Burroughs B6700 MCP Operating System source, "generate_matrix makes a sow's ear out of a silk purse".
|
||||||
|
#
|
||||||
|
# The biggest disadvantage of the zone-policy-rule model used by Shorewall is that it doesn't scale well as the number of zones increases (Order N**2 where N = number of zones).
|
||||||
|
# A major goal of the rewrite of the compiler in Perl was to restrict those scaling effects to this function and the rules that it generates.
|
||||||
|
#
|
||||||
|
# The function traverses the full "source-zone by destination-zone" matrix and generates the rules necessary to direct traffic through the right set of filter-table and
|
||||||
|
# nat-table rules.
|
||||||
|
#
|
||||||
|
sub generate_matrix() {
|
||||||
|
my @interfaces = ( all_interfaces );
|
||||||
|
#
|
||||||
|
# Should this be the real PREROUTING chain?
|
||||||
|
#
|
||||||
|
my @zones = off_firewall_zones;
|
||||||
|
our @vservers = vserver_zones;
|
||||||
|
|
||||||
|
my $interface_jumps_added = 0;
|
||||||
|
|
||||||
|
our %input_jump_added = ();
|
||||||
|
our %output_jump_added = ();
|
||||||
|
our %forward_jump_added = ();
|
||||||
|
our %ipsec_jump_added = ();
|
||||||
|
|
||||||
|
progress_message2 'Generating Rule Matrix...';
|
||||||
|
progress_message ' Handling complex zones...';
|
||||||
|
|
||||||
|
#
|
||||||
|
# Special processing for configurations with more than 2 off-firewall zones or with other special considerations like IPSEC.
|
||||||
|
#
|
||||||
|
for my $zone ( @zones ) {
|
||||||
|
my $zoneref = find_zone( $zone );
|
||||||
|
handle_complex_zone( $zone, $zoneref ) if @zones > 2 || $zoneref->{complex};
|
||||||
|
}
|
||||||
|
#
|
||||||
|
# NOTRACK from firewall
|
||||||
|
#
|
||||||
|
if ( ( my $notrackref = $raw_table->{notrack_chain(firewall_zone)}) ) {
|
||||||
|
add_ijump $raw_table->{OUTPUT}, j => $notrackref if $notrackref->{referenced};
|
||||||
|
}
|
||||||
|
#
|
||||||
|
# Main source-zone matrix-generation loop
|
||||||
|
#
|
||||||
|
progress_message ' Entering main matrix-generation loop...';
|
||||||
|
|
||||||
|
for my $zone ( @zones ) {
|
||||||
|
my $zoneref = find_zone( $zone );
|
||||||
|
my $source_hosts_ref = $zoneref->{hosts};
|
||||||
|
my $frwd_ref = $filter_table->{zone_forward_chain $zone};
|
||||||
|
my $nested = @{$zoneref->{parents}};
|
||||||
|
my $parenthasnat = 0;
|
||||||
|
my $parenthasnotrack = 0;
|
||||||
|
|
||||||
|
( $nested, $parenthasnat, $parenthasnotrack) = handle_nested_zone( $zone, $zoneref ) if $nested;
|
||||||
|
#
|
||||||
|
# Take care of PREROUTING, INPUT and OUTPUT jumps
|
||||||
|
#
|
||||||
|
for my $typeref ( values %$source_hosts_ref ) {
|
||||||
|
for my $interface ( sort { interface_number( $a ) <=> interface_number( $b ) } keys %$typeref ) {
|
||||||
|
if ( get_physical( $interface ) eq '+' ) {
|
||||||
|
#
|
||||||
|
# Insert the interface-specific jumps before this one which is not interface-specific
|
||||||
|
#
|
||||||
|
add_interface_jumps(@interfaces) unless $interface_jumps_added++;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_pio_jumps( $zone,
|
||||||
|
$zoneref,
|
||||||
|
$typeref,
|
||||||
|
$interface,
|
||||||
|
$nested,
|
||||||
|
$parenthasnat,
|
||||||
|
$parenthasnotrack,
|
||||||
|
$frwd_ref,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#
|
||||||
|
# F O R W A R D I N G
|
||||||
|
#
|
||||||
|
my @dest_zones;
|
||||||
|
my $last_chain = '';
|
||||||
|
|
||||||
|
if ( $config{OPTIMIZE} & 1 ) {
|
||||||
|
( $last_chain , @dest_zones ) = optimize1_zones($zone, $zoneref, @zones );
|
||||||
} else {
|
} else {
|
||||||
@dest_zones = @zones ;
|
@dest_zones = @zones ;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user