mirror of
https://gitlab.com/shorewall/code.git
synced 2024-11-25 09:03:30 +01:00
Implement INPUT SNAT
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
3bf5066f82
commit
a9a379c5a5
@ -25,7 +25,7 @@
|
||||
# loaded after this one and replaces some of the functions declared here.
|
||||
#
|
||||
|
||||
SHOREWALL_CAPVERSION=50106
|
||||
SHOREWALL_CAPVERSION=50112
|
||||
|
||||
if [ -z "$g_basedir" ]; then
|
||||
#
|
||||
@ -2863,6 +2863,7 @@ determine_capabilities() {
|
||||
qt $g_tool -t nat -A $chain -j NETMAP --to 2001:470:B:227::/64 && NETMAP_TARGET=Yes
|
||||
fi
|
||||
qt $g_tool -t nat -A $chain -j MASQUERADE && MASQUERADE_TGT=Yes
|
||||
qt $g_tool -t nat -L INPUT -n && NAT_INPUT_CHAIN=Yes
|
||||
qt $g_tool -t nat -A $chain -p udplite -m multiport --dport 33 -j REDIRECT --to-port 22 && UDPREDIRECT=Yes
|
||||
qt $g_tool -t nat -F $chain
|
||||
qt $g_tool -t nat -X $chain
|
||||
@ -3331,6 +3332,7 @@ report_capabilities_unsorted() {
|
||||
report_capability "NFQUEUE CPU Fanout (CPU_FANOUT)" $CPU_FANOUT
|
||||
report_capability "NETMAP Target (NETMAP_TARGET)" $NETMAP_TARGET
|
||||
report_capability "--nflog-size support (NFLOG_SIZE)" $NFLOG_SIZE
|
||||
report_capability "INPUT chain in nat table (NAT_INPUT_CHAIN)" $NAT_INPUT_CHAIN
|
||||
|
||||
echo " Kernel Version (KERNELVERSION): $KERNELVERSION"
|
||||
echo " Capabilities Version (CAPVERSION): $CAPVERSION"
|
||||
@ -3439,6 +3441,7 @@ report_capabilities_unsorted1() {
|
||||
report_capability1 NETMAP_TARGET
|
||||
report_capability1 NFLOG_SIZE
|
||||
report_capability1 RESTORE_WAIT_OPTION
|
||||
report_capability1 NAT_INPUT_CHAIN
|
||||
|
||||
report_capability1 AMANDA_HELPER
|
||||
report_capability1 FTP_HELPER
|
||||
|
@ -3182,6 +3182,8 @@ sub initialize_chain_table($) {
|
||||
new_builtin_chain 'nat', $chain, 'ACCEPT';
|
||||
}
|
||||
|
||||
new_builtin_chain 'nat', 'INPUT', 'ACCEPT' if have_capability('NAT_INPUT_CHAIN');
|
||||
|
||||
for my $chain ( qw(PREROUTING INPUT OUTPUT ) ) {
|
||||
new_builtin_chain 'mangle', $chain, 'ACCEPT';
|
||||
}
|
||||
@ -3244,6 +3246,8 @@ sub initialize_chain_table($) {
|
||||
new_builtin_chain 'nat', $chain, 'ACCEPT';
|
||||
}
|
||||
|
||||
new_builtin_chain 'nat', 'INPUT', 'ACCEPT' if have_capability('NAT_INPUT_CHAIN');
|
||||
|
||||
for my $chain ( qw(PREROUTING INPUT OUTPUT FORWARD POSTROUTING ) ) {
|
||||
new_builtin_chain 'mangle', $chain, 'ACCEPT';
|
||||
}
|
||||
|
@ -496,6 +496,7 @@ our %capdesc = ( NAT_ENABLED => 'NAT',
|
||||
NFLOG_SIZE => '--nflog-size support',
|
||||
RESTORE_WAIT_OPTION
|
||||
=> 'iptables-restore --wait option',
|
||||
NAT_INPUT_CHAIN => 'INPUT chain in NAT table',
|
||||
AMANDA_HELPER => 'Amanda Helper',
|
||||
FTP_HELPER => 'FTP Helper',
|
||||
FTP0_HELPER => 'FTP-0 Helper',
|
||||
@ -835,7 +836,7 @@ sub initialize( $;$$$) {
|
||||
EXPORT => 0,
|
||||
KLUDGEFREE => '',
|
||||
VERSION => "5.1.8-Beta1",
|
||||
CAPVERSION => 50106 ,
|
||||
CAPVERSION => 50112 ,
|
||||
BLACKLIST_LOG_TAG => '',
|
||||
RELATED_LOG_TAG => '',
|
||||
MACLIST_LOG_TAG => '',
|
||||
@ -1129,6 +1130,7 @@ sub initialize( $;$$$) {
|
||||
NETMAP_TARGET => undef,
|
||||
NFLOG_SIZE => undef,
|
||||
RESTORE_WAIT_OPTION => undef,
|
||||
NAT_INPUT_CHAIN => undef,
|
||||
|
||||
AMANDA_HELPER => undef,
|
||||
FTP_HELPER => undef,
|
||||
@ -4446,6 +4448,12 @@ sub Nat_Enabled() {
|
||||
qt1( "$iptables $iptablesw -t nat -L -n" );
|
||||
}
|
||||
|
||||
sub Nat_Input_Chain {
|
||||
have_capability( 'NAT_ENABLED' ) || return '';
|
||||
|
||||
qt1( "$iptables $iptablesw -t nat -L INPUT -n" );
|
||||
}
|
||||
|
||||
sub Persistent_Snat() {
|
||||
have_capability( 'NAT_ENABLED' ) || return '';
|
||||
|
||||
@ -5091,6 +5099,7 @@ our %detect_capability =
|
||||
MASQUERADE_TGT => \&Masquerade_Tgt,
|
||||
MULTIPORT => \&Multiport,
|
||||
NAT_ENABLED => \&Nat_Enabled,
|
||||
NAT_INPUT_CHAIN => \&Nat_Input_Chain,
|
||||
NETBIOS_NS_HELPER => \&Netbios_ns_Helper,
|
||||
NETMAP_TARGET => \&Netmap_Target,
|
||||
NEW_CONNTRACK_MATCH => \&New_Conntrack_Match,
|
||||
@ -5190,6 +5199,7 @@ sub determine_capabilities() {
|
||||
#
|
||||
$capabilities{NAT_ENABLED} = detect_capability( 'NAT_ENABLED' );
|
||||
$capabilities{PERSISTENT_SNAT} = detect_capability( 'PERSISTENT_SNAT' );
|
||||
$capabilities{NAT_INPUT_CHAIN} = detect_capability( 'NAT_INPUT_CHAIN' );
|
||||
$capabilities{MANGLE_ENABLED} = detect_capability( 'MANGLE_ENABLED' );
|
||||
|
||||
if ( $capabilities{CONNTRACK_MATCH} = detect_capability( 'CONNTRACK_MATCH' ) ) {
|
||||
|
@ -5501,22 +5501,6 @@ sub process_snat1( $$$$$$$$$$$$ ) {
|
||||
$interfaces = $dest;
|
||||
}
|
||||
#
|
||||
# Handle IPSEC options, if any
|
||||
#
|
||||
if ( $ipsec ne '-' ) {
|
||||
fatal_error "Non-empty IPSEC column requires policy match support in your kernel and iptables" unless have_capability( 'POLICY_MATCH' );
|
||||
|
||||
if ( $ipsec =~ /^yes$/i ) {
|
||||
$baserule .= do_ipsec_options 'out', 'ipsec', '';
|
||||
} elsif ( $ipsec =~ /^no$/i ) {
|
||||
$baserule .= do_ipsec_options 'out', 'none', '';
|
||||
} else {
|
||||
$baserule .= do_ipsec_options 'out', 'ipsec', $ipsec;
|
||||
}
|
||||
} elsif ( have_ipsec ) {
|
||||
$baserule .= '-m policy --pol none --dir out ';
|
||||
}
|
||||
#
|
||||
# Handle Protocol, Ports and Condition
|
||||
#
|
||||
$baserule .= do_proto( $proto, $ports, '' );
|
||||
@ -5527,7 +5511,9 @@ sub process_snat1( $$$$$$$$$$$$ ) {
|
||||
$baserule .= do_user( $user ) if $user ne '-';
|
||||
$baserule .= do_probability( $probability ) if $probability ne '-';
|
||||
|
||||
for my $fullinterface ( split_list( $interfaces, 'interface' ) ) {
|
||||
my @interfaces = split_list( $interfaces, 'interface' );
|
||||
|
||||
for my $fullinterface ( @interfaces ) {
|
||||
|
||||
my $rule = '';
|
||||
my $saveaddresses = $addresses;
|
||||
@ -5535,36 +5521,71 @@ sub process_snat1( $$$$$$$$$$$$ ) {
|
||||
my $savebaserule = $baserule;
|
||||
my $interface = $fullinterface;
|
||||
|
||||
$interface =~ s/:.*//; #interface name may include 'alias'
|
||||
|
||||
unless ( $inaction ) {
|
||||
if ( $interface =~ /(.*)[(](\w*)[)]$/ ) {
|
||||
$interface = $1;
|
||||
my $provider = $2;
|
||||
|
||||
fatal_error "Missing Provider ($dest)" unless supplied $provider;
|
||||
|
||||
$dest =~ s/[(]\w*[)]//;
|
||||
my $realm = provider_realm( $provider );
|
||||
|
||||
fatal_error "$provider is not a shared-interface provider" unless $realm;
|
||||
|
||||
$rule .= "-m realm --realm $realm ";
|
||||
}
|
||||
|
||||
fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface );
|
||||
|
||||
if ( $interfaceref->{root} ) {
|
||||
$interface = $interfaceref->{name} if $interface eq $interfaceref->{physical};
|
||||
if ( $inaction ) {
|
||||
$interface =~ s/:.*// if $family == F_IPV4; #interface name may include 'alias'
|
||||
} else {
|
||||
if ( $interface eq firewall_zone ) {
|
||||
if ( @interfaces == 1 ) {
|
||||
fatal_error q('+' not valid when the DEST is $FW) if $pre_nat;
|
||||
fatal_error q('MASQUERADE' not allowed when DEST is $FW) if $action eq 'MASQUERADE';
|
||||
require_capability 'NAT_INPUT_CHAIN', '$FW in the DEST column', 's';
|
||||
$interface = '';
|
||||
} else {
|
||||
fatal_error q($FW may not appear in a list of interfaces);
|
||||
}
|
||||
} else {
|
||||
$rule .= match_dest_dev( $interface );
|
||||
$interface = $interfaceref->{name};
|
||||
$interface =~ s/:.*// if $family == F_IPV4; #interface name may include 'alias'
|
||||
|
||||
if ( $interface =~ /(.*)[(](\w*)[)]$/ ) {
|
||||
$interface = $1;
|
||||
my $provider = $2;
|
||||
|
||||
fatal_error "Missing Provider ($dest)" unless supplied $provider;
|
||||
|
||||
$dest =~ s/[(]\w*[)]//;
|
||||
my $realm = provider_realm( $provider );
|
||||
|
||||
fatal_error "$provider is not a shared-interface provider" unless $realm;
|
||||
|
||||
$rule .= "-m realm --realm $realm ";
|
||||
}
|
||||
|
||||
fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface );
|
||||
|
||||
if ( $interfaceref->{root} ) {
|
||||
$interface = $interfaceref->{name} if $interface eq $interfaceref->{physical};
|
||||
} else {
|
||||
$rule .= match_dest_dev( $interface );
|
||||
$interface = $interfaceref->{name};
|
||||
}
|
||||
}
|
||||
|
||||
$chainref = ensure_chain('nat', $pre_nat ? snat_chain $interface : masq_chain $interface);
|
||||
$chainref = $interface ? ensure_chain('nat', $pre_nat ? snat_chain $interface : masq_chain $interface) : $nat_table->{INPUT};
|
||||
}
|
||||
|
||||
$baserule .= do_condition( $condition , $chainref->{name} );
|
||||
#
|
||||
# Handle IPSEC options, if any
|
||||
#
|
||||
if ( $ipsec ne '-' ) {
|
||||
fatal_error "Non-empty IPSEC column requires policy match support in your kernel and iptables" unless have_capability( 'POLICY_MATCH' );
|
||||
|
||||
my $dir = $interface ? 'out' : 'in';
|
||||
|
||||
if ( $ipsec =~ /^yes$/i ) {
|
||||
$baserule .= do_ipsec_options $dir, 'ipsec', '';
|
||||
} elsif ( $ipsec =~ /^no$/i ) {
|
||||
$baserule .= do_ipsec_options $dir, 'none', '';
|
||||
} else {
|
||||
$baserule .= do_ipsec_options $dir, 'ipsec', $ipsec;
|
||||
}
|
||||
} elsif ( have_ipsec ) {
|
||||
if ( $interface ) {
|
||||
$baserule .= '-m policy --pol none --dir out ';
|
||||
} else {
|
||||
$baserule .= '-m policy --pol none --dir in ';
|
||||
}
|
||||
}
|
||||
|
||||
my $detectaddress = 0;
|
||||
my $exceptionrule = '';
|
||||
@ -5572,6 +5593,7 @@ sub process_snat1( $$$$$$$$$$$$ ) {
|
||||
|
||||
if ( $action eq 'SNAT' ) {
|
||||
if ( $addresses eq 'detect' ) {
|
||||
fatal_error q('detect' not allowed when the destination is $FW) unless $interface;
|
||||
my $variable = get_interface_address $interface;
|
||||
$target .= " --to-source $variable";
|
||||
|
||||
@ -5698,6 +5720,7 @@ sub process_snat1( $$$$$$$$$$$$ ) {
|
||||
$target .= $addrlist;
|
||||
}
|
||||
} elsif ( $action eq 'MASQUERADE' ) {
|
||||
fatal_error q('MASQUERADE' not allowed when the destination is $FW') unless $interface;
|
||||
if ( supplied $addresses ) {
|
||||
validate_portpair1($proto, $addresses );
|
||||
$target .= " --to-ports $addresses";
|
||||
@ -5715,7 +5738,7 @@ sub process_snat1( $$$$$$$$$$$$ ) {
|
||||
$params,
|
||||
$loglevel,
|
||||
$source,
|
||||
supplied( $destnets ) && $destnets ne '-' ? $inaction ? $destnets : join( ':', $interface, $destnets ) : $inaction ? '-' : $interface,
|
||||
supplied( $destnets ) && $destnets ne '-' ? $inaction || $interface ? join( ':', $interface, $destnets ) : $destnets : $inaction ? '-' : $interface,
|
||||
$proto,
|
||||
$ports,
|
||||
$ipsec,
|
||||
@ -5780,7 +5803,7 @@ sub process_snat1( $$$$$$$$$$$$ ) {
|
||||
$destnets = ALLIP unless supplied $destnets && $destnets ne '-';
|
||||
|
||||
expand_rule( $chainref ,
|
||||
POSTROUTE_RESTRICT ,
|
||||
$interface ? POSTROUTE_RESTRICT : INPUT_RESTRICT ,
|
||||
$prerule ,
|
||||
$baserule . $inlinematches . $rule ,
|
||||
$source ,
|
||||
@ -5795,7 +5818,7 @@ sub process_snat1( $$$$$$$$$$$$ ) {
|
||||
|
||||
conditional_rule_end( $chainref ) if $detectaddress || $conditional;
|
||||
|
||||
if ( $add_snat_aliases && $addresses ) {
|
||||
if ( $interface && $add_snat_aliases && $addresses ) {
|
||||
my ( $interface, $alias , $remainder ) = split( /:/, $fullinterface, 3 );
|
||||
fatal_error "Invalid alias ($alias:$remainder)" if defined $remainder;
|
||||
for my $address ( split_list $addresses, 'address' ) {
|
||||
|
@ -253,10 +253,10 @@
|
||||
<listitem>
|
||||
<para>Set of hosts that you wish to masquerade. You can specify this
|
||||
as an <emphasis>address</emphasis> (net or host) or as an
|
||||
<emphasis>interface</emphasis> (use of an
|
||||
<emphasis>interface</emphasis> is deprecated). If you give the name
|
||||
of an interface, the interface must be up before you start the
|
||||
firewall and the Shorewall rules compiler will warn you of that
|
||||
<emphasis>interface</emphasis>. Unless you want to perform SNAT in
|
||||
the INPUT chain (see DEST below), if you give the name of an
|
||||
interface (deprecated), the interface must be up before you start
|
||||
the firewall and the Shorewall rules compiler will warn you of that
|
||||
fact. (Shorewall will use your main routing table to determine the
|
||||
appropriate addresses to masquerade).</para>
|
||||
|
||||
@ -268,9 +268,9 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><emphasis role="bold">DEST</emphasis> -
|
||||
<emphasis>interface</emphasis>[<emphasis
|
||||
{<emphasis>interface</emphasis>[<emphasis
|
||||
role="bold">:</emphasis><emphasis>digit][,</emphasis><emphasis>interface</emphasis>[<emphasis
|
||||
role="bold">:</emphasis><emphasis>digit</emphasis>]]...[<emphasis
|
||||
role="bold">:</emphasis><emphasis>digit</emphasis>]]...|$FW}[<emphasis
|
||||
role="bold">:</emphasis>[<emphasis>dest-address</emphasis>[<emphasis
|
||||
role="bold">,</emphasis><emphasis>dest-address</emphasis>]...[<emphasis>exclusion</emphasis>]]</term>
|
||||
|
||||
@ -286,6 +286,10 @@
|
||||
is the only use for the alias name; it may not appear in any other
|
||||
place in your Shorewall configuration.</emphasis></para>
|
||||
|
||||
<para>Beginning with Shorewall 5.1.12, SNAT may be performed in the
|
||||
nat table's INPUT chain by specifying $FW rather than one or more
|
||||
interfaces. </para>
|
||||
|
||||
<para>Each interface must match an entry in <ulink
|
||||
url="/manpages/shorewall-interfaces.html">shorewall-interfaces</ulink>(5).
|
||||
Shorewall allows loose matches to wildcard entries in <ulink
|
||||
|
Loading…
Reference in New Issue
Block a user