mirror of
https://gitlab.com/shorewall/code.git
synced 2024-12-16 19:30:44 +01:00
Finish DETECT_DNAT_IPADDRS initial implementation
git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@5644 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
parent
cb9a3650bd
commit
8f117dcd95
@ -931,6 +931,44 @@ sub log_rule_limit( $$$$$$$$ ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub log_rule_limit_command( $$$$$$$$ ) {
|
||||||
|
my ($loopcount, $level, $chainref, $chain, $disposition, $limit, $tag, $predicates ) = @_;
|
||||||
|
|
||||||
|
my $prefix;
|
||||||
|
|
||||||
|
$limit = $env{LOGLIMIT} unless $limit;
|
||||||
|
|
||||||
|
if ( $tag ) {
|
||||||
|
if ( $config{LOGTAGONLY} ) {
|
||||||
|
$chain = $tag;
|
||||||
|
$tag = '';
|
||||||
|
} else {
|
||||||
|
$tag .= ' ';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$tag = '' unless defined $tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $env{LOGRULENUMBERS} ) {
|
||||||
|
$prefix = (sprintf $config{LOGFORMAT} , $chain , $chainref->{log}++, $disposition ) . $tag;
|
||||||
|
} else {
|
||||||
|
$prefix = (sprintf $config{LOGFORMAT} , $chain , $disposition) . $tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( length $prefix > 29 ) {
|
||||||
|
$prefix = substr $prefix, 0, 29;
|
||||||
|
warning_message "Log Prefix shortened to \"$prefix\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $level eq 'ULOG' ) {
|
||||||
|
$prefix = "-j ULOG $env{LOGPARMS} --ulog-prefix \"$prefix\" ";
|
||||||
|
} else {
|
||||||
|
$prefix = "-j LOG $env{LOGPARMS} --log-level $level --log-prefix \"$prefix\" ";
|
||||||
|
}
|
||||||
|
|
||||||
|
add_command( $chainref, ( ' ' x $loopcount ) . "echo \"-A $chainref->{name} " . $predicates . $prefix . '" >&3' );
|
||||||
|
}
|
||||||
|
|
||||||
sub log_rule( $$$$ ) {
|
sub log_rule( $$$$ ) {
|
||||||
my ( $level, $chainref, $disposition, $predicates ) = @_;
|
my ( $level, $chainref, $disposition, $predicates ) = @_;
|
||||||
|
|
||||||
@ -945,6 +983,24 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
my ($chainref , $restriction, $rule, $source, $dest, $origdest, $target, $loglevel , $disposition, $exceptionrule ) = @_;
|
my ($chainref , $restriction, $rule, $source, $dest, $origdest, $target, $loglevel , $disposition, $exceptionrule ) = @_;
|
||||||
my ($iiface, $diface, $inets, $dnets, $iexcl, $dexcl, $onets , $oexcl );
|
my ($iiface, $diface, $inets, $dnets, $iexcl, $dexcl, $onets , $oexcl );
|
||||||
my $chain = $chainref->{name};
|
my $chain = $chainref->{name};
|
||||||
|
|
||||||
|
sub finish_detect_loops( $$ ) {
|
||||||
|
my ( $chainref, $chain, $ruleref, $detectcount, $newchainneeded ) = @_;
|
||||||
|
|
||||||
|
}
|
||||||
|
#
|
||||||
|
# Handle Log Level
|
||||||
|
#
|
||||||
|
my $logtag;
|
||||||
|
|
||||||
|
if ( $loglevel ) {
|
||||||
|
( $loglevel, $logtag ) = split /:/, $loglevel;
|
||||||
|
|
||||||
|
if ( $loglevel =~ /^none!?$/i ) {
|
||||||
|
return 1 if $disposition eq 'LOG';
|
||||||
|
$loglevel = $logtag = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
#
|
#
|
||||||
# Isolate Source Interface, if any
|
# Isolate Source Interface, if any
|
||||||
#
|
#
|
||||||
@ -962,10 +1018,12 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
} else {
|
} else {
|
||||||
$source = '';
|
$source = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Count of the number of parameters to the current rule that are to be detected at run-time
|
# Count of the number of unclosed loops in generated shell code
|
||||||
#
|
#
|
||||||
my $detectcount = 0;
|
my $loopcount = 0;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Verify Inteface, if any
|
# Verify Inteface, if any
|
||||||
#
|
#
|
||||||
@ -973,11 +1031,11 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
fatal_error "Unknown Interface ($iiface): \"$line\"" unless known_interface $iiface;
|
fatal_error "Unknown Interface ($iiface): \"$line\"" unless known_interface $iiface;
|
||||||
|
|
||||||
if ( $restriction == POSTROUTE_RESTRICT ) {
|
if ( $restriction == POSTROUTE_RESTRICT ) {
|
||||||
add_command( $chainref , (' ' x $detectcount) . "sources=\$(get_routed_networks $iiface)" );
|
add_command( $chainref , "sources=\$(get_routed_networks $iiface)" );
|
||||||
add_command( $chainref , (' ' x $detectcount) . qq([ -z "\$sources" ] && fatal_error "Unable to determine the routes through interface \"$iiface\"") );
|
add_command( $chainref , qq([ -z "\$sources" ] && fatal_error "Unable to determine the routes through interface \"$iiface\"") );
|
||||||
add_command( $chainref , (' ' x $detectcount) . 'for source in $sources; do' );
|
add_command( $chainref , 'for source in $sources; do' );
|
||||||
$rule .= '-s $source';
|
$rule .= '-s $source';
|
||||||
$detectcount++;
|
$loopcount++;
|
||||||
} else {
|
} else {
|
||||||
$rule .= "-i $iiface ";
|
$rule .= "-i $iiface ";
|
||||||
}
|
}
|
||||||
@ -989,6 +1047,26 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
if ( $dest ) {
|
if ( $dest ) {
|
||||||
if ( $dest eq '-' ) {
|
if ( $dest eq '-' ) {
|
||||||
$dest = '';
|
$dest = '';
|
||||||
|
} elsif ( $restriction == PREROUTE_RESTRICTION $dest =~ /^detect:(.*)$/ ) {
|
||||||
|
#
|
||||||
|
# DETECT_DNAT_IPADDRS=Yes and we're generating the nat rule
|
||||||
|
#
|
||||||
|
my @interfaces = split /\s+/, $1;
|
||||||
|
|
||||||
|
if ( @interfaces > 1 ) {
|
||||||
|
add_command $chainref, (' ' x $loopcount) . "addresses=";
|
||||||
|
|
||||||
|
for my $interface ( @interfaces ) {
|
||||||
|
add_command $chainref , (' ' x $loopcount) . 'addresses="$addresses $(find_first_interface_address $interface)';
|
||||||
|
add_command( $chainref , (' ' x $loopcount) . 'for address in $addresses; do' );
|
||||||
|
}
|
||||||
|
$loopcount++;
|
||||||
|
} else {
|
||||||
|
add_command $chainref , (' ' x $loopcount) . 'address= $(find_first_interface_address $interface)';
|
||||||
|
}
|
||||||
|
|
||||||
|
$rule .= '-d $address';
|
||||||
|
$dest = '';
|
||||||
} elsif ( $dest =~ /^([^:]+):([^:]+)$/ ) {
|
} elsif ( $dest =~ /^([^:]+):([^:]+)$/ ) {
|
||||||
$diface = $1;
|
$diface = $1;
|
||||||
$dnets = $2;
|
$dnets = $2;
|
||||||
@ -1007,45 +1085,54 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
fatal_error "Unknown Interface ($diface) in rule \"$line\"" unless known_interface $diface;
|
fatal_error "Unknown Interface ($diface) in rule \"$line\"" unless known_interface $diface;
|
||||||
|
|
||||||
if ( $restriction == PREROUTE_RESTRICT ) {
|
if ( $restriction == PREROUTE_RESTRICT ) {
|
||||||
add_command( $chainref , (' ' x $detectcount) . "dests=\$(find_interface_addresses $diface)" );
|
add_command( $chainref , (' ' x $loopcount) . "dests=\$(find_interface_addresses $diface)" );
|
||||||
add_command( $chainref , (' ' x $detectcount) . qq([ -z "\$dests" ] && fatal_error "Unable to determine the address(es) of interface \"$diface\"") );
|
add_command( $chainref , (' ' x $loopcount) . qq([ -z "\$dests" ] && fatal_error "Unable to determine the address(es) of interface \"$diface\"") );
|
||||||
|
|
||||||
add_command( $chainref , (' ' x $detectcount) . 'for dest in $dests; do' );
|
add_command( $chainref , (' ' x $loopcount) . 'for dest in $dests; do' );
|
||||||
$rule .= '-d $dest';
|
$rule .= '-d $dest';
|
||||||
$detectcount++;
|
$loopcount++;
|
||||||
} else {
|
} else {
|
||||||
$rule .= "-o $diface ";
|
$rule .= "-o $diface ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#
|
|
||||||
# If people are too lazy to specify their configuration fully, we don't go out of our way to reduce the number of rules.
|
|
||||||
#
|
|
||||||
if ( $detectcount ) {
|
|
||||||
my $newchainref = new_anon_chain( $chainref );
|
|
||||||
|
|
||||||
add_command $chainref, (' ' x $detectcount) . qq(echo "-A $chain $rule -j $newchainref->{name}" >&3;);
|
if ( $origdest ) {
|
||||||
|
if ( $origdest eq '-' ) {
|
||||||
|
$origdest = '';
|
||||||
|
} elsif ( $origdest =~ /^detect:(.*)$/ ) {
|
||||||
|
my @interfaces = split /\s+/, $1;
|
||||||
|
|
||||||
while ( $detectcount-- ) {
|
if ( @interfaces > 1 ) {
|
||||||
add_command( $chainref, (' ' x $detectcount) . 'done' );
|
add_command $chainref, (' ' x $loopcount) . "addresses=";
|
||||||
|
|
||||||
|
for my $interface ( split /\s+/, $1 ) {
|
||||||
|
add_command $chainref , (' ' x $loopcount) . 'addresses="$addresses $(find_first_interface_address $interface)"';
|
||||||
|
add_command( $chainref , (' ' x $loopcount) . 'for address in $addresses; do' );
|
||||||
|
}
|
||||||
|
$loopcount++;
|
||||||
|
} else {
|
||||||
|
add_command $chainref , (' ' x $loopcount) . 'address="$(find_first_interface_address $interface)"';
|
||||||
}
|
}
|
||||||
|
|
||||||
$chainref = $newchainref;
|
$rule .= '-m conntrack --ctorigdst $address';
|
||||||
$rule = '';
|
$origdest = '';
|
||||||
|
} elsif ( $origdest =~ /^([^!]+)?!([^!]+)$/ ) {
|
||||||
|
$onets = $1;
|
||||||
|
$oexcl = $2;
|
||||||
|
} else {
|
||||||
|
$oexcl = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
if ( ! $onets ) {
|
||||||
# Handle Log Level
|
my @oexcl = split /,/, $oexcl;
|
||||||
#
|
if ( @oexcl == 1 ) {
|
||||||
my $logtag;
|
$rule .= "-m conntrack --ctorigdst ! $oexcl ";
|
||||||
|
$oexcl = '';
|
||||||
if ( $loglevel ) {
|
|
||||||
( $loglevel, $logtag ) = split /:/, $loglevel;
|
|
||||||
|
|
||||||
if ( $loglevel =~ /^none!?$/i ) {
|
|
||||||
return 1 if $disposition eq 'LOG';
|
|
||||||
$loglevel = $logtag = '';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$oexcl = '';
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Determine if there is Source Exclusion
|
# Determine if there is Source Exclusion
|
||||||
@ -1091,25 +1178,6 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
$dexcl = '';
|
$dexcl = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $origdest ) {
|
|
||||||
if ( $origdest =~ /^([^!]+)?!([^!]+)$/ ) {
|
|
||||||
$onets = $1;
|
|
||||||
$oexcl = $2;
|
|
||||||
} else {
|
|
||||||
$oexcl = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! $onets ) {
|
|
||||||
my @oexcl = split /,/, $oexcl;
|
|
||||||
if ( @oexcl == 1 ) {
|
|
||||||
$rule .= "-m conntrack --ctorigdst ! $oexcl ";
|
|
||||||
$oexcl = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$oexcl = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$inets = ALLIPv4 unless $inets;
|
$inets = ALLIPv4 unless $inets;
|
||||||
$dnets = ALLIPv4 unless $dnets;
|
$dnets = ALLIPv4 unless $dnets;
|
||||||
$onets = ALLIPv4 unless $onets;
|
$onets = ALLIPv4 unless $onets;
|
||||||
@ -1128,10 +1196,14 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
for my $inet ( split /,/, $inets ) {
|
for my $inet ( split /,/, $inets ) {
|
||||||
$inet = match_source_net $inet;
|
$inet = match_source_net $inet;
|
||||||
for my $dnet ( split /,/, $dnets ) {
|
for my $dnet ( split /,/, $dnets ) {
|
||||||
|
if ( $loopcount ) {
|
||||||
|
add_rule_comand( $chainref, $loopcount, $rule . $inet . ( match_dest_net $dnet ) . $onet . "-j $echain" );
|
||||||
|
} else {
|
||||||
add_rule $chainref, $rule . $inet . ( match_dest_net $dnet ) . $onet . "-j $echain";
|
add_rule $chainref, $rule . $inet . ( match_dest_net $dnet ) . $onet . "-j $echain";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# The final rule in the exclusion chain will not qualify the source or destination
|
# The final rule in the exclusion chain will not qualify the source or destination
|
||||||
@ -1147,6 +1219,27 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
#
|
#
|
||||||
# Generate RETURNs for each exclusion
|
# Generate RETURNs for each exclusion
|
||||||
#
|
#
|
||||||
|
if ( $loopcount ) {
|
||||||
|
for my $net ( split ',', $iexcl ) {
|
||||||
|
add_command( $echainref, (' ' x $loopcount ) . "echo \"-A $echain " . ( match_source_net $net ) . '-j RETURN" >&3' );
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $net ( split ',', $dexcl ) {
|
||||||
|
add_command( $echainref, (' ' x $loopcount ) . "echo \"-A $echain " . ( match_dest_net $net ) . '-j RETURN" >&3' );
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $net ( split ',', $oexcl ) {
|
||||||
|
add_command( $echainref, (' ' x $loopcount ) . "echo \"-A $echain " . ( match_orig_dest $net ) . '-j RETURN" >&3' );
|
||||||
|
}
|
||||||
|
#
|
||||||
|
# Log rule
|
||||||
|
#
|
||||||
|
log_rule_limit_command $loopcount, $loglevel , $echainref , $chain, $disposition , '', $logtag , '' if $loglevel;
|
||||||
|
#
|
||||||
|
# Generate Final Rule
|
||||||
|
#
|
||||||
|
add_command( $echainref, (' ' x $loopcount ) . "echo \"-A $echain " . $exceptionrule . $target ) unless $disposition eq 'LOG';
|
||||||
|
} else {
|
||||||
for my $net ( split ',', $iexcl ) {
|
for my $net ( split ',', $iexcl ) {
|
||||||
add_rule $echainref, ( match_source_net $net ) . '-j RETURN';
|
add_rule $echainref, ( match_source_net $net ) . '-j RETURN';
|
||||||
}
|
}
|
||||||
@ -1158,7 +1251,6 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
for my $net ( split ',', $oexcl ) {
|
for my $net ( split ',', $oexcl ) {
|
||||||
add_rule $echainref, ( match_orig_dest $net ) . '-j RETURN';
|
add_rule $echainref, ( match_orig_dest $net ) . '-j RETURN';
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Log rule
|
# Log rule
|
||||||
#
|
#
|
||||||
@ -1167,7 +1259,7 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
# Generate Final Rule
|
# Generate Final Rule
|
||||||
#
|
#
|
||||||
add_rule $echainref, $exceptionrule . $target unless $disposition eq 'LOG';
|
add_rule $echainref, $exceptionrule . $target unless $disposition eq 'LOG';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
#
|
#
|
||||||
# No exclusions
|
# No exclusions
|
||||||
@ -1177,6 +1269,10 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
for my $inet ( split /,/, $inets ) {
|
for my $inet ( split /,/, $inets ) {
|
||||||
$inet = match_source_net $inet;
|
$inet = match_source_net $inet;
|
||||||
for my $dnet ( split /,/, $dnets ) {
|
for my $dnet ( split /,/, $dnets ) {
|
||||||
|
if ( $loopcount ) {
|
||||||
|
log_rule_limit_command $loopcount, $loglevel , $chainref , $chain, $disposition , '' , $logtag , $rule . $inet . match_dest_net( $dnet ) . $onet if $loglevel;
|
||||||
|
add_command( $chainref, (' ' x $loopcount ) . "echo \"-A $chain" . $rule . $inet . match_dest_net( $dnet ) . $onet . $target . '" >&3') unless $disposition eq 'LOG';
|
||||||
|
} else {
|
||||||
log_rule_limit $loglevel , $chainref , $chain, $disposition , '' , $logtag , 'add' , $rule . $inet . match_dest_net( $dnet ) . $onet if $loglevel;
|
log_rule_limit $loglevel , $chainref , $chain, $disposition , '' , $logtag , 'add' , $rule . $inet . match_dest_net( $dnet ) . $onet if $loglevel;
|
||||||
add_rule $chainref, $rule . $inet . match_dest_net( $dnet ) . $onet . $target unless $disposition eq 'LOG';
|
add_rule $chainref, $rule . $inet . match_dest_net( $dnet ) . $onet . $target unless $disposition eq 'LOG';
|
||||||
}
|
}
|
||||||
@ -1185,6 +1281,11 @@ sub expand_rule( $$$$$$$$$$ )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ( $loopcount-- ) {
|
||||||
|
add_command( $chainref, (' ' x $loopcount) . 'done' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# If the destination chain exists, then at the end of the source chain add a jump to the destination.
|
# If the destination chain exists, then at the end of the source chain add a jump to the destination.
|
||||||
#
|
#
|
||||||
|
@ -930,11 +930,13 @@ sub process_rule1 ( $$$$$$$$$ ) {
|
|||||||
$target = '-j REDIRECT --to-port ' . ( $serverport ? $serverport : $ports );
|
$target = '-j REDIRECT --to-port ' . ( $serverport ? $serverport : $ports );
|
||||||
}
|
}
|
||||||
|
|
||||||
unless ( $origdest and $origdest ne '-' ) {
|
unless ( $origdest && $origdest ne '-' && $origdest ne 'detect' ) {
|
||||||
if ( $config{DETECT_DNAT_ADDRS} ) {
|
if ( $config{DETECT_DNAT_ADDRS} ) {
|
||||||
$origdest = 'detect';
|
my $interfacesref = $zones{$sourcezone}{interfaces};
|
||||||
|
my $interfaces = "@$interfacesref";
|
||||||
|
$origdest = $interfaces ? "detect:$interfaces" : ALLIPv4;
|
||||||
} else {
|
} else {
|
||||||
origdest = ALLIPv4;
|
$origdest = ALLIPv4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#
|
#
|
||||||
@ -959,21 +961,27 @@ sub process_rule1 ( $$$$$$$$$ ) {
|
|||||||
$loglevel = '';
|
$loglevel = '';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$origdest = ALLIPv4 unless $origdest and $origdest ne '-';
|
|
||||||
|
|
||||||
if ( $actiontype & NONAT ) {
|
if ( $actiontype & NONAT ) {
|
||||||
#
|
#
|
||||||
# NONAT or ACCEPT+ -- May not specify a destination interface
|
# NONAT or ACCEPT+ -- May not specify a destination interface
|
||||||
#
|
#
|
||||||
fatal_error "Invalid DEST ($dest) in $action rule \"$line\"" if $dest =~ /:/;
|
fatal_error "Invalid DEST ($dest) in $action rule \"$line\"" if $dest =~ /:/;
|
||||||
|
|
||||||
|
$origdest = '' unless $origdest and $origdest ne '-';
|
||||||
|
|
||||||
|
if ( $origdest eq 'detect' ) {
|
||||||
|
my $interfacesref = $zones{$sourcezone}{interfaces};
|
||||||
|
my $interfaces = "@$interfacesref";
|
||||||
|
$origdest = $interfaces ? "detect:$interfaces" : ALLIPv4;
|
||||||
|
}
|
||||||
|
|
||||||
expand_rule
|
expand_rule
|
||||||
ensure_chain ('nat' , $zones{$sourcezone}{type} eq 'firewall' ? 'OUTPUT' : dnat_chain $sourcezone) ,
|
ensure_chain ('nat' , $zones{$sourcezone}{type} eq 'firewall' ? 'OUTPUT' : dnat_chain $sourcezone) ,
|
||||||
PREROUTE_RESTRICT ,
|
PREROUTE_RESTRICT ,
|
||||||
$rule ,
|
$rule ,
|
||||||
$source ,
|
$source ,
|
||||||
$dest ,
|
$dest ,
|
||||||
'' ,
|
$origdest ,
|
||||||
'-j RETURN ' ,
|
'-j RETURN ' ,
|
||||||
$loglevel ,
|
$loglevel ,
|
||||||
$action ,
|
$action ,
|
||||||
|
Loading…
Reference in New Issue
Block a user