Optimize RELATED rules.

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2013-01-06 16:48:37 -08:00
parent d4c9885c09
commit edc0a84e5d
2 changed files with 91 additions and 39 deletions

View File

@ -131,6 +131,7 @@ our %EXPORT_TAGS = (
forward_option_chain forward_option_chain
rules_chain rules_chain
blacklist_chain blacklist_chain
related_chain
zone_forward_chain zone_forward_chain
use_forward_chain use_forward_chain
input_chain input_chain
@ -1567,6 +1568,13 @@ sub blacklist_chain($$) {
&rules_chain(@_) . '~'; &rules_chain(@_) . '~';
} }
#
# Name of the related chain between an ordered pair of zones
#
sub related_chain($$) {
'+' . &rules_chain(@_);
}
# #
# Create the base for a chain involving the passed interface -- we make this a function so it will be # Create the base for a chain involving the passed interface -- we make this a function so it will be
# easy to change the mapping should the need ever arrive. # easy to change the mapping should the need ever arrive.

View File

@ -806,7 +806,7 @@ sub optimize_policy_chains() {
# Modules moved from the Chains module in 4.4.18 # Modules moved from the Chains module in 4.4.18
################################################################################ ################################################################################
sub finish_chain_section( $$ ); sub finish_chain_section( $$$ );
# #
# Create a rules chain if necessary and populate it with the appropriate ESTABLISHED,RELATED rule(s) and perform SYN rate limiting. # Create a rules chain if necessary and populate it with the appropriate ESTABLISHED,RELATED rule(s) and perform SYN rate limiting.
@ -823,9 +823,9 @@ sub ensure_rules_chain( $ )
unless ( $chainref->{referenced} ) { unless ( $chainref->{referenced} ) {
if ( $section =~/^(NEW|DEFAULTACTION)$/ ) { if ( $section =~/^(NEW|DEFAULTACTION)$/ ) {
finish_chain_section $chainref , 'ESTABLISHED,RELATED'; finish_chain_section $chainref , $chainref, 'ESTABLISHED,RELATED';
} elsif ( $section eq 'RELATED' ) { } elsif ( $section eq 'RELATED' ) {
finish_chain_section $chainref , 'ESTABLISHED'; finish_chain_section $chainref , $chainref, 'ESTABLISHED';
} }
$chainref->{referenced} = 1; $chainref->{referenced} = 1;
@ -837,56 +837,75 @@ sub ensure_rules_chain( $ )
# #
# Add ESTABLISHED,RELATED rules and synparam jumps to the passed chain # Add ESTABLISHED,RELATED rules and synparam jumps to the passed chain
# #
sub finish_chain_section ($$) { sub finish_chain_section ($$$) {
my ($chainref, $state ) = @_; my ($chainref,
$chain1ref,
$state ) = @_;
my $chain = $chainref->{name}; my $chain = $chainref->{name};
my $related_level = $config{RELATED_LOG_LEVEL}; my $related_level = $config{RELATED_LOG_LEVEL};
my $related_target = $globals{RELATED_TARGET}; my $related_target = $globals{RELATED_TARGET};
my $save_comment = push_comment; my $save_comment = push_comment;
my $relatedchain = $chainref->{name} =~ /^\+/;
if ( $state =~ /RELATED/ && ( $related_level || $related_target ne 'ACCEPT' ) ) { if ( $state =~ /RELATED/ && ( $related_level || $related_target ne 'ACCEPT' ) ) {
if ( $related_level ) { if ( $related_level ) {
my $relatedref = new_chain( 'filter', "+$chainref->{name}" ); my $relatedref;
if ( $relatedchain ) {
$relatedref = $chainref;
} else {
$relatedref = new_chain( 'filter', "+$chainref->{name}" );
}
log_rule( $related_level, log_rule( $related_level,
$relatedref, $relatedref,
$config{RELATED_DISPOSITION}, $config{RELATED_DISPOSITION},
'' ); '' );
add_ijump( $relatedref, g => $related_target ); add_ijump( $relatedref, g => $related_target );
$related_target = $relatedref->{name}; $related_target = $relatedref->{name} unless $relatedchain;
} }
add_ijump $chainref, g => $related_target, state_imatch 'RELATED'; if ( $relatedchain ) {
add_ijump $chainref, g => $related_target;
} else {
add_ijump $chainref, g => $related_target, state_imatch 'RELATED';
}
$state =~ s/,?RELATED//; $state =~ s/,?RELATED//;
} }
if ( $state ) {
add_ijump $chainref, j => 'ACCEPT', state_imatch $state unless $config{FASTACCEPT}; if ( $state && ! $config{FASTACCEPT} ) {
if ( $chainref->{name} eq $chain1ref->{name} ) {
add_ijump $chainref, j => 'ACCEPT', state_imatch $state;
} else {
add_ijump $chainref, j => 'ACCEPT';
}
} }
if ($sections{NEW} ) { if ($sections{NEW} ) {
if ( $chainref->{is_policy} ) { if ( $chain1ref->{is_policy} ) {
if ( $chainref->{synparams} ) { if ( $chain1ref->{synparams} ) {
my $synchainref = ensure_chain 'filter', syn_flood_chain $chainref; my $synchainref = ensure_chain 'filter', syn_flood_chain $chain1ref;
if ( $section eq 'DEFAULTACTION' ) { if ( $section eq 'DEFAULTACTION' ) {
if ( $chainref->{policy} =~ /^(ACCEPT|CONTINUE|QUEUE|NFQUEUE)/ ) { if ( $chain1ref->{policy} =~ /^(ACCEPT|CONTINUE|QUEUE|NFQUEUE)/ ) {
add_ijump $chainref, j => $synchainref, p => 'tcp --syn'; add_ijump $chain1ref, j => $synchainref, p => 'tcp --syn';
} }
} else { } else {
add_ijump $chainref, j => $synchainref, p => 'tcp --syn'; add_ijump $chain1ref, j => $synchainref, p => 'tcp --syn';
} }
} }
} else { } else {
my $policychainref = $filter_table->{$chainref->{policychain}}; my $policychainref = $filter_table->{$chain1ref->{policychain}};
if ( $policychainref->{synparams} ) { if ( $policychainref->{synparams} ) {
my $synchainref = ensure_chain 'filter', syn_flood_chain $policychainref; my $synchainref = ensure_chain 'filter', syn_flood_chain $policychainref;
add_ijump $chainref, j => $synchainref, p => 'tcp --syn'; add_ijump $chain1ref, j => $synchainref, p => 'tcp --syn';
} }
} }
$chainref->{new} = @{$chainref->{rules}}; $chain1ref->{new} = @{$chain1ref->{rules}};
} }
pop_comment( $save_comment ); pop_comment( $save_comment );
@ -900,10 +919,19 @@ sub finish_section ( $ ) {
$sections{$_} = 1 for split /,/, $sections; $sections{$_} = 1 for split /,/, $sections;
my $function;
if ( $section eq 'RELATED' ) {
$function = \&related_chain;
} else {
$function = \&rules_chain;
}
for my $zone ( all_zones ) { for my $zone ( all_zones ) {
for my $zone1 ( all_zones ) { for my $zone1 ( all_zones ) {
my $chainref = $chain_table{'filter'}{rules_chain( $zone, $zone1 )}; my $chainref = $filter_table->{$function->( $zone, $zone1 ) };
finish_chain_section $chainref, $sections if $chainref->{referenced}; my $chain1ref = $filter_table->{rules_chain( $zone, $zone1 )};
finish_chain_section $chainref || $chain1ref, $chain1ref, $sections if $chain1ref->{referenced};
} }
} }
} }
@ -2227,22 +2255,39 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
# #
$chainref = ensure_rules_chain $chain; $chainref = ensure_rules_chain $chain;
# #
# Handle use of the blacklist chain # Handle rules not in the NEW section
# #
if ( $blacklist ) { unless ( $section eq 'NEW' ) {
my $blacklistchain = blacklist_chain( ${sourcezone}, ${destzone} ); my $auxchain;
my $blacklistref = $filter_table->{$blacklistchain}; my $auxref;
unless ( $blacklistref ) { if ( $blacklist ) {
my @state; $auxchain = blacklist_chain( ${sourcezone}, ${destzone} );
$blacklistref = new_chain 'filter', $blacklistchain; } elsif ( $section eq 'RELATED' ) {
$blacklistref->{blacklistsection} = 1; $auxchain = related_chain( ${sourcezone}, ${destzone} );
@state = state_imatch( 'NEW,INVALID' ) if $config{BLACKLISTNEWONLY};
add_ijump( $chainref, j => $blacklistref, @state );
} }
$chain = $blacklistchain; if ( $auxchain ) {
$chainref = $blacklistref; $auxref = $filter_table->{$auxchain};
unless ( $auxref ) {
my @state;
$auxref = new_chain 'filter', $auxchain;
if ( $blacklist ) {
@state = state_imatch( 'NEW,INVALID' ) if $config{BLACKLISTNEWONLY};
$auxref->{blacklistsection} = 1;
} else {
@state = state_imatch( $section )
};
add_ijump( $chainref, j => $auxref, @state );
}
$chain = $auxchain;
$chainref = $auxref;
}
} }
} }
} }
@ -2322,15 +2367,14 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
); );
} }
unless ( $section =~ /^NEW|DEFAULTACTION$/ || $inaction || $basictarget eq 'dropInvalid' ) { unless ( $section =~ /^NEW|DEFAULTACTION$/ || $inaction || $blacklist || $basictarget eq 'dropInvalid' ) {
if ( $config{FASTACCEPT} ) { if ( $config{FASTACCEPT} ) {
fatal_error "Entries in the $section SECTION of the rules file not permitted with FASTACCEPT=Yes" unless fatal_error "Entries in the $section SECTION of the rules file not permitted with FASTACCEPT=Yes" unless
$section eq 'BLACKLIST' || $section eq 'RELATED' && ( $config{RELATED_DISPOSITION} ne 'ACCEPT' || $config{RELATED_LOG_LEVEL} )
( $section eq 'RELATED' && ( $config{RELATED_DISPOSITION} ne 'ACCEPT' || $config{RELATED_LOG_LEVEL} ) ) }
}
fatal_error "$basictarget rules are not allowed in the $section SECTION" if $actiontype & ( NATRULE | NONAT ); fatal_error "$basictarget rules are not allowed in the $section SECTION" if $actiontype & ( NATRULE | NONAT );
$rule .= "$globals{STATEMATCH} $section " unless $section eq 'ALL' || $blacklist; $rule .= "$globals{STATEMATCH} $section " unless $section =~ /^ALL|RELATED$/ || $blacklist;
} }
# #
# Generate CT rules(s), if any # Generate CT rules(s), if any