Optimize nonat rules in certain cases

This commit is contained in:
Tom Eastep 2009-07-16 11:05:37 -07:00
parent 58f0110ad3
commit 55045ace4b
2 changed files with 87 additions and 38 deletions

View File

@ -114,6 +114,7 @@ our %EXPORT_TAGS = (
finish_section finish_section
setup_zone_mss setup_zone_mss
newexclusionchain newexclusionchain
newnonatchain
source_exclusion source_exclusion
dest_exclusion dest_exclusion
clearrule clearrule
@ -242,7 +243,6 @@ use constant { NO_RESTRICT => 0, # FORWARD chain rule - Both -i and
POSTROUTE_RESTRICT => 16, # POSTROUTING chain rule - -i converted to -s <address list> using main routing table POSTROUTE_RESTRICT => 16, # POSTROUTING chain rule - -i converted to -s <address list> using main routing table
ALL_RESTRICT => 12 # fw->fw rule - neither -i nor -o allowed ALL_RESTRICT => 12 # fw->fw rule - neither -i nor -o allowed
}; };
our $exclseq;
our $iprangematch; our $iprangematch;
our $chainseq; our $chainseq;
our $idiotcount; our $idiotcount;
@ -335,11 +335,7 @@ sub initialize( $ ) {
# #
$comment = ''; $comment = '';
# #
# Used to sequence 'exclusion' chains with names 'excl0', 'excl1', ... # Used to sequence chains names.
#
$exclseq = 0;
#
# Used to sequence 'log' chains with names 'log0', 'log1', etc.
# #
$chainseq = 0; $chainseq = 0;
# #
@ -1261,7 +1257,7 @@ sub setup_zone_mss() {
} }
sub newexclusionchain() { sub newexclusionchain() {
my $seq = $exclseq++; my $seq = $chainseq++;
"excl${seq}"; "excl${seq}";
} }
@ -1270,6 +1266,11 @@ sub newlogchain() {
"log${seq}"; "log${seq}";
} }
sub newnonatchain() {
my $seq = $chainseq++;
"nonat${seq}";
}
# #
# If the passed exclusion array is non-empty then: # If the passed exclusion array is non-empty then:
# #
@ -2358,7 +2359,7 @@ sub set_global_variables( $ ) {
# #
# Returns the destination interface specified in the rule, if any. # Returns the destination interface specified in the rule, if any.
# #
sub expand_rule( $$$$$$$$$$ ) sub expand_rule( $$$$$$$$$$;$ )
{ {
my ($chainref , # Chain my ($chainref , # Chain
$restriction, # Determines what to do with interface names in the SOURCE or DEST $restriction, # Determines what to do with interface names in the SOURCE or DEST
@ -2369,7 +2370,8 @@ sub expand_rule( $$$$$$$$$$ )
$target, # Target ('-j' part of the rule) $target, # Target ('-j' part of the rule)
$loglevel , # Log level (and tag) $loglevel , # Log level (and tag)
$disposition, # Primative part of the target (RETURN, ACCEPT, ...) $disposition, # Primative part of the target (RETURN, ACCEPT, ...)
$exceptionrule # Caller's matches used in exclusion case $exceptionrule,# Caller's matches used in exclusion case
$logname, # Name of chain to name in log messages
) = @_; ) = @_;
my ($iiface, $diface, $inets, $dnets, $iexcl, $dexcl, $onets , $oexcl, $trivialiexcl, $trivialdexcl ); my ($iiface, $diface, $inets, $dnets, $iexcl, $dexcl, $onets , $oexcl, $trivialiexcl, $trivialdexcl );
@ -2756,28 +2758,42 @@ sub expand_rule( $$$$$$$$$$ )
if ( $loglevel ne '' ) { if ( $loglevel ne '' ) {
if ( $disposition ne 'LOG' ) { if ( $disposition ne 'LOG' ) {
# unless ( $logname ) {
# Create a chain that both logs and applies the target action #
# # Create a chain that both logs and applies the target action
my $logchainref = new_chain $chainref->{table}, newlogchain; #
# my $logchainref = new_chain $chainref->{table}, newlogchain;
# Jump to the log chain if all of the rule's conditions are met #
# # Jump to the log chain if all of the rule's conditions are met
add_jump( $chainref, $logchainref, $builtin_target{$disposition}, $predicates, 1 ); #
# add_jump( $chainref, $logchainref, $builtin_target{$disposition}, $predicates, 1 );
# Now add the log rule and target rule without predicates to the log chain. #
# # Now add the log rule and target rule without predicates to the log chain.
log_rule_limit( #
$loglevel , log_rule_limit(
$chainref = $logchainref , $loglevel ,
$chain , $chainref = $logchainref ,
$disposition , $chain ,
'', $disposition ,
$logtag, '',
'add', $logtag,
'' ); 'add',
'' );
add_rule( $chainref, $target ); add_rule( $chainref, $target );
} else {
log_rule_limit(
$loglevel ,
$chainref ,
$logname ,
$disposition ,
'',
$logtag,
'add',
$predicates );
add_rule( $chainref, $predicates . $target, 1 );
}
} else { } else {
# #
# The log rule must be added with predicates to the rule chain # The log rule must be added with predicates to the rule chain

View File

@ -1296,43 +1296,76 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
my $nonat_chain; my $nonat_chain;
my $chn;
if ( $sourceref->{type} == FIREWALL ) { if ( $sourceref->{type} == FIREWALL ) {
$nonat_chain = $nat_table->{OUTPUT}; $nonat_chain = $nat_table->{OUTPUT};
} else { } else {
$nonat_chain = ensure_chain 'nat', dnat_chain $sourcezone; $nonat_chain = ensure_chain 'nat', dnat_chain $sourcezone;
my $chn; my @interfaces = keys %{zone_interfaces $sourcezone};
for ( keys %{zone_interfaces $sourcezone} ) { for ( @interfaces ) {
my $ichain = input_chain $_; my $ichain = input_chain $_;
if ( $nat_table->{$ichain} ) { if ( $nat_table->{$ichain} ) {
# #
# Static NAT is defined on this interface # Static NAT is defined on this interface
# #
$chn = new_chain( 'nat', newexclusionchain ) unless $chn; $chn = new_chain( 'nat', newnonatchain ) unless $chn;
add_jump $chn, $nat_table->{$ichain}, 0, "-i $_ "; add_jump $chn, $nat_table->{$ichain}, 0, @interfaces > 1 ? "-i $_ " : '';
} }
} }
if ( $chn ) { if ( $chn ) {
add_rule $chn, '-j ACCEPT'; #
# Call expand_rule() to correctly handle logging. Because
# the 'logname' argument is passed, expand_rule() will
# not create a separate logging chain but will rather emit
# any logging rule in-line.
#
expand_rule( $chn,
PREROUTE_RESTRICT,
'', # Rule
'', # Source
'', # Dest
'', # Original dest
'-j ACCEPT',
$loglevel,
$log_action,
'',
dnat_chain( $sourcezone ) );
$loglevel = '';
$tgt = $chn->{name}; $tgt = $chn->{name};
} else { } else {
$tgt = 'ACCEPT'; $tgt = 'ACCEPT';
} }
} }
expand_rule( $nonat_chain , expand_rule( $nonat_chain ,
PREROUTE_RESTRICT , PREROUTE_RESTRICT ,
$rule , $rule ,
$source , $source ,
$dest , $dest ,
$origdest , $origdest ,
" -j $tgt ", "-j $tgt",
$loglevel , $loglevel ,
$log_action , $log_action ,
'' ); ''
);
#
# Possible optimization if the rule just generated was a simple jump to the nonat chain
#
if ( $chn && ${$nonat_chain->{rules}}[-1] eq "-A -j $tgt" ) {
#
# It was -- delete that rule
#
pop @{$nonat_chain->{rules}};
#
# And move the rules from the nonat chain to the zone dnat chain
#
move_rules ( $chn, $nonat_chain );
}
} }
# #