mirror of
https://gitlab.com/shorewall/code.git
synced 2025-06-20 01:37:59 +02:00
Interface lists in masq and nat files
git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@8068 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
parent
3eb254c0b6
commit
545dd7dbc3
@ -115,187 +115,189 @@ sub do_ipsec_options($)
|
|||||||
#
|
#
|
||||||
sub setup_one_masq($$$$$$$)
|
sub setup_one_masq($$$$$$$)
|
||||||
{
|
{
|
||||||
my ($fullinterface, $networks, $addresses, $proto, $ports, $ipsec, $mark) = @_;
|
my ($interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark) = @_;
|
||||||
|
|
||||||
my $rule = '';
|
|
||||||
my $pre_nat;
|
my $pre_nat;
|
||||||
my $add_snat_aliases = $config{ADD_SNAT_ALIASES};
|
my $add_snat_aliases = $config{ADD_SNAT_ALIASES};
|
||||||
my $destnets = '';
|
my $destnets = '';
|
||||||
my $target = '-j MASQUERADE ';
|
|
||||||
|
|
||||||
#
|
|
||||||
# Handle IPSEC options, if any
|
|
||||||
#
|
|
||||||
if ( $ipsec ne '-' ) {
|
|
||||||
fatal_error "Non-empty IPSEC column requires policy match support in your kernel and iptables" unless $globals{ORIGINAL_POLICY_MATCH};
|
|
||||||
|
|
||||||
if ( $ipsec =~ /^yes$/i ) {
|
|
||||||
$rule .= '-m policy --pol ipsec --dir out ';
|
|
||||||
} elsif ( $ipsec =~ /^no$/i ) {
|
|
||||||
$rule .= '-m policy --pol none --dir out ';
|
|
||||||
} else {
|
|
||||||
$rule .= do_ipsec_options $ipsec;
|
|
||||||
}
|
|
||||||
} elsif ( $capabilities{POLICY_MATCH} ) {
|
|
||||||
$rule .= '-m policy --pol none --dir out ';
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Leading '+'
|
# Leading '+'
|
||||||
#
|
#
|
||||||
$pre_nat = 1 if $fullinterface =~ s/^\+//;
|
$pre_nat = 1 if $interfacelist =~ s/^\+//;
|
||||||
#
|
#
|
||||||
# Parse the remaining part of the INTERFACE column
|
# Parse the remaining part of the INTERFACE column
|
||||||
#
|
#
|
||||||
if ( $fullinterface =~ /^([^:]+)::([^:]*)$/ ) {
|
if ( $interfacelist =~ /^([^:]+)::([^:]*)$/ ) {
|
||||||
$add_snat_aliases = 0;
|
$add_snat_aliases = 0;
|
||||||
$destnets = $2;
|
$destnets = $2;
|
||||||
$fullinterface = $1;
|
$interfacelist = $1;
|
||||||
} elsif ( $fullinterface =~ /^([^:]+:[^:]+):([^:]+)$/ ) {
|
} elsif ( $interfacelist =~ /^([^:]+:[^:]+):([^:]+)$/ ) {
|
||||||
$destnets = $2;
|
$destnets = $2;
|
||||||
$fullinterface = $1;
|
$interfacelist = $1;
|
||||||
} elsif ( $fullinterface =~ /^([^:]+):$/ ) {
|
} elsif ( $interfacelist =~ /^([^:]+):$/ ) {
|
||||||
$add_snat_aliases = 0;
|
$add_snat_aliases = 0;
|
||||||
$fullinterface = $1;
|
$interfacelist = $1;
|
||||||
} elsif ( $fullinterface =~ /^([^:]+):([^:]*)$/ ) {
|
} elsif ( $interfacelist =~ /^([^:]+):([^:]*)$/ ) {
|
||||||
my ( $one, $two ) = ( $1, $2 );
|
my ( $one, $two ) = ( $1, $2 );
|
||||||
if ( $2 =~ /\./ ) {
|
if ( $2 =~ /\./ ) {
|
||||||
$fullinterface = $one;
|
$interfacelist = $one;
|
||||||
$destnets = $two;
|
$destnets = $two;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# Isolate and verify the interface part
|
|
||||||
#
|
|
||||||
( my $interface = $fullinterface ) =~ s/:.*//;
|
|
||||||
|
|
||||||
if ( $interface =~ /(.*)[(](\w*)[)]$/ ) {
|
|
||||||
$interface = $1;
|
|
||||||
my $realm = $2;
|
|
||||||
$fullinterface =~ s/[(]\w*[)]//;
|
|
||||||
$realm = lookup_provider( $realm ) unless $realm =~ /^\d+$/;
|
|
||||||
|
|
||||||
$rule .= "-m realm --realm $realm ";
|
|
||||||
}
|
|
||||||
|
|
||||||
fatal_error "Unknown interface ($interface)" unless find_interface( $interface )->{root};
|
|
||||||
|
|
||||||
my $chainref = ensure_chain('nat', $pre_nat ? snat_chain $interface : masq_chain $interface);
|
|
||||||
#
|
#
|
||||||
# If there is no source or destination then allow all addresses
|
# If there is no source or destination then allow all addresses
|
||||||
#
|
#
|
||||||
$networks = ALLIPv4 if $networks eq '-';
|
$networks = ALLIPv4 if $networks eq '-';
|
||||||
$destnets = ALLIPv4 if $destnets eq '-';
|
$destnets = ALLIPv4 if $destnets eq '-';
|
||||||
#
|
|
||||||
# Handle Protocol and Ports
|
|
||||||
#
|
|
||||||
$rule .= do_proto $proto, $ports, '';
|
|
||||||
#
|
|
||||||
# Handle Mark
|
|
||||||
#
|
|
||||||
$rule .= do_test( $mark, 0xFF) if $mark ne '-';
|
|
||||||
|
|
||||||
my $detectaddress = 0;
|
for my $fullinterface (split /,/, $interfacelist ) {
|
||||||
my $exceptionrule = '';
|
my $rule = '';
|
||||||
my $randomize = '';
|
my $target = '-j MASQUERADE ';
|
||||||
#
|
#
|
||||||
# Parse the ADDRESSES column
|
# Isolate and verify the interface part
|
||||||
#
|
#
|
||||||
if ( $addresses ne '-' ) {
|
( my $interface = $fullinterface ) =~ s/:.*//;
|
||||||
if ( $addresses eq 'random' ) {
|
|
||||||
$randomize = '--random ';
|
|
||||||
} else {
|
|
||||||
$addresses =~ s/:random$// and $randomize = '--random ';
|
|
||||||
|
|
||||||
if ( $addresses =~ /^SAME:nodst:/ ) {
|
if ( $interface =~ /(.*)[(](\w*)[)]$/ ) {
|
||||||
fatal_error "':random' is not supported by the SAME target" if $randomize;
|
$interface = $1;
|
||||||
$target = '-j SAME --nodst ';
|
my $realm = $2;
|
||||||
$addresses =~ s/.*://;
|
$fullinterface =~ s/[(]\w*[)]//;
|
||||||
for my $addr ( split /,/, $addresses ) {
|
$realm = lookup_provider( $realm ) unless $realm =~ /^\d+$/;
|
||||||
$target .= "--to $addr ";
|
|
||||||
}
|
$rule .= "-m realm --realm $realm ";
|
||||||
} elsif ( $addresses =~ /^SAME:/ ) {
|
}
|
||||||
fatal_error "':random' is not supported by the SAME target" if $randomize;
|
|
||||||
$target = '-j SAME ';
|
fatal_error "Unknown interface ($interface)" unless find_interface( $interface )->{root};
|
||||||
$addresses =~ s/.*://;
|
|
||||||
for my $addr ( split /,/, $addresses ) {
|
my $chainref = ensure_chain('nat', $pre_nat ? snat_chain $interface : masq_chain $interface);
|
||||||
$target .= "--to $addr ";
|
#
|
||||||
}
|
# Handle IPSEC options, if any
|
||||||
} elsif ( $addresses eq 'detect' ) {
|
#
|
||||||
my $variable = get_interface_address $interface;
|
if ( $ipsec ne '-' ) {
|
||||||
$target = "-j SNAT --to-source $variable";
|
fatal_error "Non-empty IPSEC column requires policy match support in your kernel and iptables" unless $globals{ORIGINAL_POLICY_MATCH};
|
||||||
|
|
||||||
if ( interface_is_optional $interface ) {
|
if ( $ipsec =~ /^yes$/i ) {
|
||||||
add_commands( $chainref,
|
$rule .= '-m policy --pol ipsec --dir out ';
|
||||||
'',
|
} elsif ( $ipsec =~ /^no$/i ) {
|
||||||
"if [ \"$variable\" != 0.0.0.0 ]; then" );
|
$rule .= '-m policy --pol none --dir out ';
|
||||||
incr_cmd_level( $chainref );
|
|
||||||
$detectaddress = 1;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
my $addrlist = '';
|
$rule .= do_ipsec_options $ipsec;
|
||||||
for my $addr ( split /,/, $addresses ) {
|
}
|
||||||
if ( $addr =~ /^.*\..*\..*\./ ) {
|
} elsif ( $capabilities{POLICY_MATCH} ) {
|
||||||
$target = '-j SNAT ';
|
$rule .= '-m policy --pol none --dir out ';
|
||||||
$addrlist .= "--to-source $addr ";
|
}
|
||||||
$exceptionrule = do_proto( $proto, '', '' ) if $addr =~ /:/;
|
|
||||||
} else {
|
#
|
||||||
$addr =~ s/^://;
|
# Handle Protocol and Ports
|
||||||
$addrlist .= "--to-ports $addr ";
|
#
|
||||||
$exceptionrule = do_proto( $proto, '', '' );
|
$rule .= do_proto $proto, $ports, '';
|
||||||
}
|
#
|
||||||
}
|
# Handle Mark
|
||||||
|
#
|
||||||
|
$rule .= do_test( $mark, 0xFF) if $mark ne '-';
|
||||||
|
|
||||||
|
my $detectaddress = 0;
|
||||||
|
my $exceptionrule = '';
|
||||||
|
my $randomize = '';
|
||||||
|
#
|
||||||
|
# Parse the ADDRESSES column
|
||||||
|
#
|
||||||
|
if ( $addresses ne '-' ) {
|
||||||
|
if ( $addresses eq 'random' ) {
|
||||||
|
$randomize = '--random ';
|
||||||
|
} else {
|
||||||
|
$addresses =~ s/:random$// and $randomize = '--random ';
|
||||||
|
|
||||||
$target .= $addrlist;
|
if ( $addresses =~ /^SAME:nodst:/ ) {
|
||||||
|
fatal_error "':random' is not supported by the SAME target" if $randomize;
|
||||||
|
$target = '-j SAME --nodst ';
|
||||||
|
$addresses =~ s/.*://;
|
||||||
|
for my $addr ( split /,/, $addresses ) {
|
||||||
|
$target .= "--to $addr ";
|
||||||
|
}
|
||||||
|
} elsif ( $addresses =~ /^SAME:/ ) {
|
||||||
|
fatal_error "':random' is not supported by the SAME target" if $randomize;
|
||||||
|
$target = '-j SAME ';
|
||||||
|
$addresses =~ s/.*://;
|
||||||
|
for my $addr ( split /,/, $addresses ) {
|
||||||
|
$target .= "--to $addr ";
|
||||||
|
}
|
||||||
|
} elsif ( $addresses eq 'detect' ) {
|
||||||
|
my $variable = get_interface_address $interface;
|
||||||
|
$target = "-j SNAT --to-source $variable";
|
||||||
|
|
||||||
|
if ( interface_is_optional $interface ) {
|
||||||
|
add_commands( $chainref,
|
||||||
|
'',
|
||||||
|
"if [ \"$variable\" != 0.0.0.0 ]; then" );
|
||||||
|
incr_cmd_level( $chainref );
|
||||||
|
$detectaddress = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
my $addrlist = '';
|
||||||
|
for my $addr ( split /,/, $addresses ) {
|
||||||
|
if ( $addr =~ /^.*\..*\..*\./ ) {
|
||||||
|
$target = '-j SNAT ';
|
||||||
|
$addrlist .= "--to-source $addr ";
|
||||||
|
$exceptionrule = do_proto( $proto, '', '' ) if $addr =~ /:/;
|
||||||
|
} else {
|
||||||
|
$addr =~ s/^://;
|
||||||
|
$addrlist .= "--to-ports $addr ";
|
||||||
|
$exceptionrule = do_proto( $proto, '', '' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$target .= $addrlist;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$target .= $randomize;
|
||||||
|
} else {
|
||||||
|
$add_snat_aliases = 0;
|
||||||
}
|
}
|
||||||
|
#
|
||||||
$target .= $randomize;
|
# And Generate the Rule(s)
|
||||||
} else {
|
#
|
||||||
$add_snat_aliases = 0;
|
expand_rule( $chainref ,
|
||||||
}
|
POSTROUTE_RESTRICT ,
|
||||||
#
|
$rule ,
|
||||||
# And Generate the Rule(s)
|
$networks ,
|
||||||
#
|
$destnets ,
|
||||||
expand_rule( $chainref ,
|
'' ,
|
||||||
POSTROUTE_RESTRICT ,
|
$target ,
|
||||||
$rule ,
|
'' ,
|
||||||
$networks ,
|
'' ,
|
||||||
$destnets ,
|
$exceptionrule );
|
||||||
'' ,
|
|
||||||
$target ,
|
if ( $detectaddress ) {
|
||||||
'' ,
|
decr_cmd_level( $chainref );
|
||||||
'' ,
|
add_command( $chainref , 'fi' );
|
||||||
$exceptionrule );
|
}
|
||||||
|
|
||||||
if ( $detectaddress ) {
|
if ( $add_snat_aliases ) {
|
||||||
decr_cmd_level( $chainref );
|
my ( $interface, $alias , $remainder ) = split( /:/, $fullinterface, 3 );
|
||||||
add_command( $chainref , 'fi' );
|
fatal_error "Invalid alias ($alias:$remainder)" if defined $remainder;
|
||||||
}
|
for my $address ( split /,/, $addresses ) {
|
||||||
|
my ( $addrs, $port ) = split /:/, $address;
|
||||||
if ( $add_snat_aliases ) {
|
next unless $addrs;
|
||||||
my ( $interface, $alias , $remainder ) = split( /:/, $fullinterface, 3 );
|
next if $addrs eq 'detect';
|
||||||
fatal_error "Invalid alias ($alias:$remainder)" if defined $remainder;
|
for my $addr ( ip_range_explicit $addrs ) {
|
||||||
for my $address ( split /,/, $addresses ) {
|
unless ( $addresses_to_add{$addr} ) {
|
||||||
my ( $addrs, $port ) = split /:/, $address;
|
emit "del_ip_addr $addr $interface" unless $config{RETAIN_ALIASES};
|
||||||
next unless $addrs;
|
$addresses_to_add{$addr} = 1;
|
||||||
next if $addrs eq 'detect';
|
if ( defined $alias ) {
|
||||||
for my $addr ( ip_range_explicit $addrs ) {
|
push @addresses_to_add, $addr, "$interface:$alias";
|
||||||
unless ( $addresses_to_add{$addr} ) {
|
$alias++;
|
||||||
emit "del_ip_addr $addr $interface" unless $config{RETAIN_ALIASES};
|
} else {
|
||||||
$addresses_to_add{$addr} = 1;
|
push @addresses_to_add, $addr, $interface;
|
||||||
if ( defined $alias ) {
|
}
|
||||||
push @addresses_to_add, $addr, "$interface:$alias";
|
|
||||||
$alias++;
|
|
||||||
} else {
|
|
||||||
push @addresses_to_add, $addr, $interface;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
progress_message " Masq record \"$currentline\" $done";
|
progress_message " Masq record \"$currentline\" $done";
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -399,7 +401,6 @@ sub do_one_nat( $$$$$ )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
progress_message " NAT entry \"$currentline\" $done";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -413,12 +414,20 @@ sub setup_nat() {
|
|||||||
|
|
||||||
while ( read_a_line ) {
|
while ( read_a_line ) {
|
||||||
|
|
||||||
my ( $external, $interface, $internal, $allints, $localnat ) = split_line1 3, 5, 'nat file';
|
my ( $external, $interfacelist, $internal, $allints, $localnat ) = split_line1 3, 5, 'nat file';
|
||||||
|
|
||||||
if ( $external eq 'COMMENT' ) {
|
if ( $external eq 'COMMENT' ) {
|
||||||
process_comment;
|
process_comment;
|
||||||
} else {
|
} else {
|
||||||
do_one_nat $external, $interface, $internal, $allints, $localnat;
|
( $interfacelist, my $digit ) = split /:/, $interfacelist;
|
||||||
|
|
||||||
|
$digit = defined $digit ? ":$digit" : '';
|
||||||
|
|
||||||
|
for my $interface ( split /,/, $interfacelist ) {
|
||||||
|
do_one_nat $external, "${interface}${digit}", $internal, $allints, $localnat;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress_message " NAT entry \"$currentline\" $done";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user