mirror of
https://gitlab.com/shorewall/code.git
synced 2024-12-20 21:30:44 +01:00
Create better rules when a HELPER appears in an action
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
50dfffec94
commit
b5af6f03fb
@ -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
|
||||||
|
@ -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;
|
|
||||||
|
|
||||||
fatal_error 'USER/GROUP is not allowed unless the SOURCE zone is $FW or a Vserver zone' if $user ne '-' && $restriction != OUTPUT_RESTRICT;
|
unless ( $chainref ) {
|
||||||
require_capability 'RAW_TABLE', 'conntrack rules', '';
|
#
|
||||||
|
# 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;
|
||||||
|
}
|
||||||
|
|
||||||
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 >
|
||||||
|
Loading…
Reference in New Issue
Block a user