Create better rules when a HELPER appears in an action

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2012-08-11 07:48:03 -07:00
parent 50dfffec94
commit b5af6f03fb
4 changed files with 117 additions and 39 deletions

View File

@ -101,6 +101,7 @@ our %EXPORT_TAGS = (
CHAIN CHAIN
SET SET
AUDIT AUDIT
HELPER
NO_RESTRICT NO_RESTRICT
PREROUTE_RESTRICT PREROUTE_RESTRICT
DESTIFACE_DISALLOW DESTIFACE_DISALLOW
@ -352,6 +353,7 @@ use constant { STANDARD => 1, #defined by Netfilter
CHAIN => 1024, #Manual Chain CHAIN => 1024, #Manual Chain
SET => 2048, #SET SET => 2048, #SET
AUDIT => 4096, #A_ACCEPT, etc AUDIT => 4096, #A_ACCEPT, etc
HELPER => 8192, #CT:helper
}; };
# #
# Valid Targets -- value is a combination of one or more of the above # Valid Targets -- value is a combination of one or more of the above

View File

@ -33,7 +33,7 @@ use strict;
our @ISA = qw(Exporter); our @ISA = qw(Exporter);
our @EXPORT = qw( setup_conntrack ); our @EXPORT = qw( setup_conntrack );
our @EXPORT_OK = qw( process_conntrack_rule ); our @EXPORT_OK = qw( handle_helper_rule );
our $VERSION = 'MODULEVERSION'; our $VERSION = 'MODULEVERSION';
my %valid_ctevent = ( new => 1, related => 1, destroy => 1, reply => 1, assured => 1, protoinfo => 1, helper => 1, mark => 1, natseqinfo => 1, secmark => 1 ); my %valid_ctevent = ( new => 1, related => 1, destroy => 1, reply => 1, assured => 1, protoinfo => 1, helper => 1, mark => 1, natseqinfo => 1, secmark => 1 );
@ -41,21 +41,34 @@ my %valid_ctevent = ( new => 1, related => 1, destroy => 1, reply => 1, assured
# #
# Notrack # Notrack
# #
sub process_conntrack_rule( $$$$$$$ ) { sub process_conntrack_rule( $$$$$$$$$ ) {
my ($action, $source, $dest, $proto, $ports, $sports, $user ) = @_; my ($chainref, $zoneref, $action, $source, $dest, $proto, $ports, $sports, $user ) = @_;
require_capability 'RAW_TABLE', 'conntrack rules', '';
$proto = '' if $proto eq 'any'; $proto = '' if $proto eq 'any';
$ports = '' if $ports eq 'any' || $ports eq 'all'; $ports = '' if $ports eq 'any' || $ports eq 'all';
$sports = '' if $sports eq 'any' || $sports eq 'all'; $sports = '' if $sports eq 'any' || $sports eq 'all';
( my $zone, $source) = split /:/, $source, 2; my $zone;
my $zoneref = find_zone $zone; my $restriction = PREROUTE_RESTRICT;
my $chainref = ensure_raw_chain( notrack_chain $zone );
my $restriction = $zoneref->{type} == FIREWALL || $zoneref->{type} == VSERVER ? OUTPUT_RESTRICT : PREROUTE_RESTRICT;
unless ( $chainref ) {
#
# Entry in the conntrack file
#
if ( $zoneref ) {
$zone = $zoneref->{name};
} else {
($zone, $source) = split /:/, $source, 2;
$zoneref = find_zone ( $zone );
}
$chainref = ensure_raw_chain( notrack_chain $zone );
$restriction = OUTPUT_RESTRICT if $zoneref->{type} == FIREWALL || $zoneref->{type} == VSERVER;
fatal_error 'USER/GROUP is not allowed unless the SOURCE zone is $FW or a Vserver zone' if $user ne '-' && $restriction != OUTPUT_RESTRICT; fatal_error 'USER/GROUP is not allowed unless the SOURCE zone is $FW or a Vserver zone' if $user ne '-' && $restriction != OUTPUT_RESTRICT;
require_capability 'RAW_TABLE', 'conntrack rules', ''; }
my $target = $action; my $target = $action;
my $exception_rule = ''; my $exception_rule = '';
@ -125,6 +138,59 @@ sub process_conntrack_rule( $$$$$$$ ) {
progress_message " Conntrack rule \"$currentline\" $done"; progress_message " Conntrack rule \"$currentline\" $done";
} }
sub handle_helper_rule( $$$$$$$$$$$ ) {
my ( $helper, $source, $dest, $proto, $ports, $sports, $sourceref, $action_target, $actionchain, $user, $rule ) = @_;
if ( $helper ne '-' ) {
fatal_error "A HELPER is not allowed with this ACTION" if $action_target;
#
# This means that an ACCEPT or NAT rule with a helper is being processed
#
process_conntrack_rule( $actionchain ? ensure_raw_chain( $actionchain ) : undef ,
$sourceref ,
"CT:helper:$helper",
$source ,
$dest ,
$proto ,
$ports ,
$sports ,
$user );
} else {
assert( $action_target );
#
# The target is an action
#
if ( $actionchain ) {
#
# And the source is another action chain
#
expand_rule( ensure_raw_chain( $actionchain ) ,
PREROUTE_RESTRICT ,
$rule ,
$source ,
$dest ,
'' ,
$action_target ,
'',
'CT' ,
'' );
} else {
expand_rule( ensure_raw_chain( notrack_chain( $sourceref->{name} ) ) ,
( $sourceref->{type} == FIREWALL || $sourceref->{type} == VSERVER ?
OUTPUT_RESTRICT :
PREROUTE_RESTRICT ) ,
$rule ,
$source ,
$dest ,
'' ,
$action_target ,
'' ,
'CT' ,
'' );
}
}
}
sub process_format( $ ) { sub process_format( $ ) {
my $format = shift; my $format = shift;
@ -186,10 +252,10 @@ sub setup_conntrack() {
if ( $source eq 'all' ) { if ( $source eq 'all' ) {
for my $zone (all_zones) { for my $zone (all_zones) {
process_conntrack_rule( $action, $zone, $dest, $proto, $ports, $sports, $user ); process_conntrack_rule( undef, undef, $action, $zone, $dest, $proto, $ports, $sports, $user );
} }
} else { } else {
process_conntrack_rule( $action, $source, $dest, $proto, $ports, $sports, $user ); process_conntrack_rule( undef, undef, $action, $source, $dest, $proto, $ports, $sports, $user );
} }
} }

View File

@ -34,7 +34,7 @@ use Shorewall::Zones;
use Shorewall::Chains qw(:DEFAULT :internal); use Shorewall::Chains qw(:DEFAULT :internal);
use Shorewall::IPAddrs; use Shorewall::IPAddrs;
use Shorewall::Nat qw(:rules); use Shorewall::Nat qw(:rules);
use Shorewall::Raw qw( process_conntrack_rule ); use Shorewall::Raw qw( handle_helper_rule );
use Scalar::Util 'reftype'; use Scalar::Util 'reftype';
use strict; use strict;
@ -1783,12 +1783,13 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
# #
process_action( $ref ); process_action( $ref );
# #
# Processing the action may determine that the action or one of it's dependents does NAT, so: # Processing the action may determine that the action or one of it's dependents does NAT or HELPER, so:
# #
# - Refresh $actiontype # - Refresh $actiontype
# - Create the associate nat table chain if appropriate. # - Create the associated nat and/or table chain if appropriate.
# #
ensure_chain( 'nat', $ref->{name} ) if ( $actiontype = $targets{$basictarget} ) & NATRULE; ensure_chain( 'nat', $ref->{name} ) if ( $actiontype = $targets{$basictarget} ) & NATRULE;
ensure_chain( 'raw', $ref->{name} ) if ( $actiontype & HELPER );
} }
$action = $basictarget; # Remove params, if any, from $action. $action = $basictarget; # Remove params, if any, from $action.
@ -1803,6 +1804,10 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
$targets{$inaction} |= NATRULE if $inaction; $targets{$inaction} |= NATRULE if $inaction;
fatal_error "NAT rules are only allowed in the NEW section" unless $section eq 'NEW'; fatal_error "NAT rules are only allowed in the NEW section" unless $section eq 'NEW';
} }
if ( $actiontype & HELPER ) {
fatal_error "HELPER rules are only allowed in the NEW section" unless $section eq 'NEW';
}
# #
# Take care of irregular syntax and targets # Take care of irregular syntax and targets
# #
@ -1814,7 +1819,13 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
$bt =~ s/[-+!]$//; $bt =~ s/[-+!]$//;
my %functions = my %functions =
( ACCEPT => sub() { $action = 'RETURN' if $blacklist; } , ( ACCEPT => sub() {
if ( $blacklist ) {
$action = 'RETURN';
} elsif ( $helper ne '-' ) {
$actiontype |= HELPER;
}
} ,
REDIRECT => sub () { REDIRECT => sub () {
my $z = $actiontype & NATONLY ? '' : firewall_zone; my $z = $actiontype & NATONLY ? '' : firewall_zone;
@ -1845,6 +1856,8 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
if ( $function ) { if ( $function ) {
$function->(); $function->();
} elsif ( $actiontype & NATRULE && $helper ne '-' ) {
$actiontype |= HELPER;
} elsif ( $actiontype & SET ) { } elsif ( $actiontype & SET ) {
my %xlate = ( ADD => 'add-set' , DEL => 'del-set' ); my %xlate = ( ADD => 'add-set' , DEL => 'del-set' );
@ -2034,8 +2047,26 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
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 eq 'ALL' || $blacklist;
} }
# #
# Generate CT rules(s), if any
#
if ( $actiontype & HELPER ) {
handle_helper_rule( $helper,
$source,
$origdest ? $origdest : $dest,
$proto,
$ports,
$sports,
$sourceref,
( $actiontype & ACTION ) ? $usedactions{$normalized_target}->{name} : '',
$inaction ? $chain : '' ,
$user ,
$rule ,
);
$targets{$inaction} |= HELPER if $inaction;
}
# Generate NAT rule(s), if any # Generate NAT rule(s), if any
# #
if ( $actiontype & NATRULE ) { if ( $actiontype & NATRULE ) {
@ -2059,17 +2090,6 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
$log_action, $log_action,
); );
unless ( $helper eq '-' ) {
my $rulezone = $inaction ? 'all' : $sourcezone;
process_conntrack_rule( "CT:helper:$helper" ,
"$rulezone:$source",
$origdest,
$proto,
$ports,
$sports,
$user );
}
# #
# After NAT: # After NAT:
# - the destination port will be the server port ($ports) -- we did that above # - the destination port will be the server port ($ports) -- we did that above
@ -2141,17 +2161,6 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
$loglevel , $loglevel ,
$log_action , $log_action ,
'' ); '' );
if ( $action eq 'ACCEPT' && $helper ne '-' ) {
my $rulezone = $inaction ? 'all' : $sourcezone;
process_conntrack_rule( "CT:helper:$helper" ,
"$rulezone:$source",
$origdest ? $origdest : $dest,
$proto,
$ports,
$sports,
$user );
}
} }
return 1; return 1;

View File

@ -118,7 +118,8 @@ use constant { IN_OUT => 1,
# #
# @zones contains the ordered list of zones with sub-zones appearing before their parents. # @zones contains the ordered list of zones with sub-zones appearing before their parents.
# #
# %zones{<zone1> => {type => <zone type> FIREWALL, IP, IPSEC, BPORT; # %zones{<zone1> => {name => <name>,
# type => <zone type> FIREWALL, IP, IPSEC, BPORT;
# complex => 0|1 # complex => 0|1
# super => 0|1 # super => 0|1
# options => { in_out => < policy match string > # options => { in_out => < policy match string >