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
setup_zone_mss
newexclusionchain
newnonatchain
source_exclusion
dest_exclusion
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
ALL_RESTRICT => 12 # fw->fw rule - neither -i nor -o allowed
};
our $exclseq;
our $iprangematch;
our $chainseq;
our $idiotcount;
@ -335,11 +335,7 @@ sub initialize( $ ) {
#
$comment = '';
#
# Used to sequence 'exclusion' chains with names 'excl0', 'excl1', ...
#
$exclseq = 0;
#
# Used to sequence 'log' chains with names 'log0', 'log1', etc.
# Used to sequence chains names.
#
$chainseq = 0;
#
@ -1261,7 +1257,7 @@ sub setup_zone_mss() {
}
sub newexclusionchain() {
my $seq = $exclseq++;
my $seq = $chainseq++;
"excl${seq}";
}
@ -1270,6 +1266,11 @@ sub newlogchain() {
"log${seq}";
}
sub newnonatchain() {
my $seq = $chainseq++;
"nonat${seq}";
}
#
# 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.
#
sub expand_rule( $$$$$$$$$$ )
sub expand_rule( $$$$$$$$$$;$ )
{
my ($chainref , # Chain
$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)
$loglevel , # Log level (and tag)
$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 );
@ -2756,28 +2758,42 @@ sub expand_rule( $$$$$$$$$$ )
if ( $loglevel ne '' ) {
if ( $disposition ne 'LOG' ) {
#
# Create a chain that both logs and applies the target action
#
my $logchainref = new_chain $chainref->{table}, newlogchain;
#
# Jump to the log chain if all of the rule's conditions are met
#
add_jump( $chainref, $logchainref, $builtin_target{$disposition}, $predicates, 1 );
#
# Now add the log rule and target rule without predicates to the log chain.
#
log_rule_limit(
$loglevel ,
$chainref = $logchainref ,
$chain ,
$disposition ,
'',
$logtag,
'add',
'' );
unless ( $logname ) {
#
# Create a chain that both logs and applies the target action
#
my $logchainref = new_chain $chainref->{table}, newlogchain;
#
# Jump to the log chain if all of the rule's conditions are met
#
add_jump( $chainref, $logchainref, $builtin_target{$disposition}, $predicates, 1 );
#
# Now add the log rule and target rule without predicates to the log chain.
#
log_rule_limit(
$loglevel ,
$chainref = $logchainref ,
$chain ,
$disposition ,
'',
$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 {
#
# 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 $chn;
if ( $sourceref->{type} == FIREWALL ) {
$nonat_chain = $nat_table->{OUTPUT};
} else {
$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 $_;
if ( $nat_table->{$ichain} ) {
#
# Static NAT is defined on this interface
#
$chn = new_chain( 'nat', newexclusionchain ) unless $chn;
add_jump $chn, $nat_table->{$ichain}, 0, "-i $_ ";
$chn = new_chain( 'nat', newnonatchain ) unless $chn;
add_jump $chn, $nat_table->{$ichain}, 0, @interfaces > 1 ? "-i $_ " : '';
}
}
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};
} else {
$tgt = 'ACCEPT';
}
}
expand_rule( $nonat_chain ,
PREROUTE_RESTRICT ,
$rule ,
$source ,
$dest ,
$origdest ,
" -j $tgt ",
"-j $tgt",
$loglevel ,
$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 );
}
}
#