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:
teastep 2008-01-15 02:39:21 +00:00
parent 3eb254c0b6
commit 545dd7dbc3

View File

@ -115,181 +115,183 @@ 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 ";
}
} 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 ) { $rule .= "-m realm --realm $realm ";
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; fatal_error "Unknown interface ($interface)" unless find_interface( $interface )->{root};
} else {
$add_snat_aliases = 0;
}
#
# And Generate the Rule(s)
#
expand_rule( $chainref ,
POSTROUTE_RESTRICT ,
$rule ,
$networks ,
$destnets ,
'' ,
$target ,
'' ,
'' ,
$exceptionrule );
if ( $detectaddress ) { my $chainref = ensure_chain('nat', $pre_nat ? snat_chain $interface : masq_chain $interface);
decr_cmd_level( $chainref ); #
add_command( $chainref , 'fi' ); # 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 ( $add_snat_aliases ) { if ( $ipsec =~ /^yes$/i ) {
my ( $interface, $alias , $remainder ) = split( /:/, $fullinterface, 3 ); $rule .= '-m policy --pol ipsec --dir out ';
fatal_error "Invalid alias ($alias:$remainder)" if defined $remainder; } elsif ( $ipsec =~ /^no$/i ) {
for my $address ( split /,/, $addresses ) { $rule .= '-m policy --pol none --dir out ';
my ( $addrs, $port ) = split /:/, $address; } else {
next unless $addrs; $rule .= do_ipsec_options $ipsec;
next if $addrs eq 'detect'; }
for my $addr ( ip_range_explicit $addrs ) { } elsif ( $capabilities{POLICY_MATCH} ) {
unless ( $addresses_to_add{$addr} ) { $rule .= '-m policy --pol none --dir out ';
emit "del_ip_addr $addr $interface" unless $config{RETAIN_ALIASES}; }
$addresses_to_add{$addr} = 1;
if ( defined $alias ) { #
push @addresses_to_add, $addr, "$interface:$alias"; # Handle Protocol and Ports
$alias++; #
} else { $rule .= do_proto $proto, $ports, '';
push @addresses_to_add, $addr, $interface; #
# 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 ';
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;
}
#
# And Generate the Rule(s)
#
expand_rule( $chainref ,
POSTROUTE_RESTRICT ,
$rule ,
$networks ,
$destnets ,
'' ,
$target ,
'' ,
'' ,
$exceptionrule );
if ( $detectaddress ) {
decr_cmd_level( $chainref );
add_command( $chainref , 'fi' );
}
if ( $add_snat_aliases ) {
my ( $interface, $alias , $remainder ) = split( /:/, $fullinterface, 3 );
fatal_error "Invalid alias ($alias:$remainder)" if defined $remainder;
for my $address ( split /,/, $addresses ) {
my ( $addrs, $port ) = split /:/, $address;
next unless $addrs;
next if $addrs eq 'detect';
for my $addr ( ip_range_explicit $addrs ) {
unless ( $addresses_to_add{$addr} ) {
emit "del_ip_addr $addr $interface" unless $config{RETAIN_ALIASES};
$addresses_to_add{$addr} = 1;
if ( defined $alias ) {
push @addresses_to_add, $addr, "$interface:$alias";
$alias++;
} else {
push @addresses_to_add, $addr, $interface;
}
} }
} }
} }
@ -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";
} }
} }