Re-implement exclusion in CONTINUE/NONAT/ACCEPT+ rules

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2010-08-27 10:09:42 -07:00
parent 57bcfee559
commit c98cf8aea6
5 changed files with 87 additions and 45 deletions

View File

@ -3483,59 +3483,76 @@ sub expand_rule( $$$$$$$$$$;$ )
fatal_error "SOURCE interface may not be specified with a source IP address in the POSTROUTING chain" if $restriction == POSTROUTE_RESTRICT && $iiface && ( $inets ne ALLIP || $iexcl || $trivialiexcl);
fatal_error "DEST interface may not be specified with a destination IP address in the PREROUTING chain" if $restriction == PREROUTE_RESTRICT && $diface && ( $dnets ne ALLIP || $dexcl || $trivialdexcl);
my $fromref;
my ( $fromref, $done );
if ( $iexcl || $dexcl || $oexcl ) {
#
# We have non-trivial exclusion -- need to create an exclusion chain
#
fatal_error "Exclusion is not possible in ACCEPT+/CONTINUE/NONAT rules" if $disposition eq 'RETURN' || $disposition eq 'CONTINUE';
if ( $disposition eq 'RETURN' || $disposition eq 'CONTINUE' ) {
#
# We can't use an exclusion chain -- we mark those packets to be excluded and then condition the following rules based on the mark value
#
require_capability 'MARK_ANYWHERE' , 'Exclusion in ACCEPT+/CONTINUE/NONAT rules', 's';
add_rule $chainref = $chainref , '-j MARK --and-mark ' . in_hex( $globals{EXCLUSION_MASK} ^ 0xffffffff );
my $exclude = '-j MARK --or-mark ' . in_hex( $globals{EXCLUSION_MASK} );
#
# Create the Exclusion Chain
#
my $echain = newexclusionchain;
add_rule $chainref, ( match_source_net $_ , $restriction ) . $exclude for ( mysplit $iexcl );
add_rule $chainref, ( match_dest_net $_ ) . $exclude for ( mysplit $dexcl );
add_rule $chainref, ( match_orig_dest $_ ) . $exclude for ( mysplit $oexcl );
my $echainref = new_chain $chainref->{table}, $echain;
$rule .= '-m mark --mark 0/' . in_hex( $globals{EXCLUSION_MASK} ) . ' ';
} else {
#
# Create the Exclusion Chain
#
my $echain = newexclusionchain;
#
# Use the current rule and send all possible matches to the exclusion chain
#
for my $onet ( mysplit $onets ) {
$onet = match_orig_dest $onet;
for my $inet ( mysplit $inets ) {
for my $dnet ( mysplit $dnets ) {
#
# We evaluate the source net match in the inner loop to accomodate systems without $capabilities{KLUDGEFREE}
#
add_jump( $chainref, $echainref, 0, join( '', $rule, match_source_net( $inet, $restriction ), match_dest_net( $dnet ), $onet ), 1 );
my $echainref = new_chain $chainref->{table}, $echain;
#
# Use the current rule and send all possible matches to the exclusion chain
#
for my $onet ( mysplit $onets ) {
$onet = match_orig_dest $onet;
for my $inet ( mysplit $inets ) {
for my $dnet ( mysplit $dnets ) {
#
# We evaluate the source net match in the inner loop to accomodate systems without $capabilities{KLUDGEFREE}
#
add_jump( $chainref, $echainref, 0, join( '', $rule, match_source_net( $inet, $restriction ), match_dest_net( $dnet ), $onet ), 1 );
}
}
}
}
#
# Generate RETURNs for each exclusion
#
add_rule $echainref, ( match_source_net $_ , $restriction ) . '-j RETURN' for ( mysplit $iexcl );
add_rule $echainref, ( match_dest_net $_ ) . '-j RETURN' for ( mysplit $dexcl );
add_rule $echainref, ( match_orig_dest $_ ) . '-j RETURN' for ( mysplit $oexcl );
#
# Log rule
#
log_rule_limit( $loglevel ,
$echainref ,
$chain,
$disposition eq 'reject' ? 'REJECT' : $disposition ,
'' ,
$logtag ,
'add' ,
'' )
if $loglevel;
#
# Generate Final Rule
#
add_rule $fromref = $echainref, $exceptionrule . $jump , 1 unless $disposition eq 'LOG';
} else {
#
# Generate RETURNs for each exclusion
#
add_rule $echainref, ( match_source_net $_ , $restriction ) . '-j RETURN' for ( mysplit $iexcl );
add_rule $echainref, ( match_dest_net $_ ) . '-j RETURN' for ( mysplit $dexcl );
add_rule $echainref, ( match_orig_dest $_ ) . '-j RETURN' for ( mysplit $oexcl );
#
# Log rule
#
log_rule_limit( $loglevel ,
$echainref ,
$chain,
$disposition eq 'reject' ? 'REJECT' : $disposition ,
'' ,
$logtag ,
'add' ,
'' )
if $loglevel;
#
# Generate Final Rule
#
add_rule $fromref = $echainref, $exceptionrule . $jump , 1 unless $disposition eq 'LOG';
$done = 1;
}
}
unless ( $done ) {
#
# No exclusions
#

View File

@ -3092,7 +3092,12 @@ sub get_configuration( $ ) {
if ( $config{PROVIDER_OFFSET} ) {
$config{PROVIDER_OFFSET} = $config{MASK_BITS} if $config{PROVIDER_OFFSET} < $config{MASK_BITS};
fatal_error 'PROVIDER_BITS + PROVIDER_OFFSET > 32' if $config{PROVIDER_BITS} + $config{PROVIDER_OFFSET} > 32;
fatal_error 'PROVIDER_BITS + PROVIDER_OFFSET > 32' if $config{PROVIDER_BITS} + $config{PROVIDER_OFFSET} > 31;
$globals{EXCLUSION_MASK} = 1 << ( $config{PROVIDER_OFFSET} + $config{PROVIDER_BITS} );
} elsif ( $config{TC_BITS} >= $config{PROVIDER_BITS} ) {
$globals{EXCLUSION_MASK} = 1 << $config{TC_BITS};
} else {
$globals{EXCLUSION_MASK} = 1 << $config{PROVIDER_BITS};
}
$globals{TC_MAX} = make_mask( $config{TC_BITS} );

View File

@ -393,7 +393,7 @@ sub process_tc_rule( ) {
'' ,
"$target $mark" ,
'' ,
'' ,
$target ,
'' ) )
&& $device ) {
#

View File

@ -2,6 +2,12 @@ Changes in Shorewall 4.4.13
1) Allow zone lists in rules SOURCE and DEST.
2) Fix exclusion in the blacklist file.
3) Correct several old exclusion bugs.
4) Fix exclusion with CONTINUE/NONAT/ACCEPT+
Changes in Shorewall 4.4.12
1) Fix IPv6 shorecap program.

View File

@ -28,11 +28,25 @@ VI. PROBLEMS CORRECTED AND NEW FEATURES IN PRIOR RELEASES
4) Previously, if REQUIRE_INTERFACE=Yes then start/restart would fail
if the last optional interface tested was not available.
5) Exclusion in the blacklist file was correctly validated but was then
ignored when generating iptables (ip6tables) rules.
6) Previously, non-trivial exclusion (more than one excluded
address/net) in CONTINUE, NONAT and ACCEPT+ rules generated
valid but incorrect iptables input. This has been corrected but
requires that your iptables/kernel support marking rules in any
Netfilter table.
This fix implements a new 'Mark in any table' capability; those
who utilize a capabilities file should re-generate the file using
this release.
----------------------------------------------------------------------------
I I. K N O W N P R O B L E M S R E M A I N I N G
----------------------------------------------------------------------------
None.
1) On systems running Upstart, shorewall-init cannot reliably start the
firewall before interfaces are brought up.
----------------------------------------------------------------------------
I I I. N E W F E A T U R E S I N T H I S R E L E A S E