Allow MARK, CONNMARK, SAVE and RESTORE in the nat table

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2018-06-14 09:18:48 -07:00
parent a8b6a301f2
commit bfb9852eb6
No known key found for this signature in database
GPG Key ID: 96E6B3F2423A4D10
4 changed files with 98 additions and 30 deletions

View File

@ -153,6 +153,9 @@ our %EXPORT_TAGS = (
STICKY STICKY
STICKO STICKO
REALPREROUTING REALPREROUTING
REALINPUT
REALOUTPUT
REALPOSTROUTING
ACTIONCHAIN ACTIONCHAIN
unreachable_warning unreachable_warning
@ -490,16 +493,19 @@ use constant { NO_RESTRICT => 0, # FORWARD chain rule - Both -i an
# Mangle Table allowed chains enumeration # Mangle Table allowed chains enumeration
# #
use constant { use constant {
PREROUTING => 1, #Actually tcpre PREROUTING => 1, #Actually tcpre
INPUT => 2, #Actually tcin INPUT => 2, #Actually tcin
FORWARD => 4, #Actually tcfor FORWARD => 4, #Actually tcfor
OUTPUT => 8, #Actually tcout OUTPUT => 8, #Actually tcout
POSTROUTING => 16, #Actually tcpost POSTROUTING => 16, #Actually tcpost
ALLCHAINS => 31, STICKY => 32,
STICKY => 32, STICKO => 64,
STICKO => 64, REALPREROUTING => 128,
REALPREROUTING => 128, REALINPUT => 256,
ACTIONCHAIN => 256, REALOUTPUT => 512,
REALPOSTROUTING => 1024,
ALLCHAINS => 2047,
ACTIONCHAIN => 2048,
}; };
# #

View File

@ -465,7 +465,7 @@ our %capdesc = ( NAT_ENABLED => 'NAT',
TPROXY_TARGET => 'TPROXY Target', TPROXY_TARGET => 'TPROXY Target',
FLOW_FILTER => 'Flow Classifier', FLOW_FILTER => 'Flow Classifier',
FWMARK_RT_MASK => 'fwmark route mask', FWMARK_RT_MASK => 'fwmark route mask',
MARK_ANYWHERE => 'Mark in the filter table', MARK_ANYWHERE => 'Mark in the filter and nat tables',
HEADER_MATCH => 'Header Match', HEADER_MATCH => 'Header Match',
ACCOUNT_TARGET => 'ACCOUNT Target', ACCOUNT_TARGET => 'ACCOUNT Target',
AUDIT_TARGET => 'AUDIT Target', AUDIT_TARGET => 'AUDIT Target',

View File

@ -4077,6 +4077,10 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
O => OUTPUT, O => OUTPUT,
T => POSTROUTING, T => POSTROUTING,
R => REALPREROUTING, R => REALPREROUTING,
NP => REALPREROUTING,
NI => REALINPUT,
NO => REALOUTPUT,
NT => REALPOSTROUTING
); );
my %chainlabels = ( 1 => 'PREROUTING', my %chainlabels = ( 1 => 'PREROUTING',
@ -4085,14 +4089,17 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
8 => 'OUTPUT', 8 => 'OUTPUT',
16 => 'POSTROUTING' ); 16 => 'POSTROUTING' );
my %chainnames = ( 1 => 'tcpre', my %chainnames = ( 1 => 'tcpre',
2 => 'tcin', 2 => 'tcin',
4 => 'tcfor', 4 => 'tcfor',
8 => 'tcout', 8 => 'tcout',
16 => 'tcpost', 16 => 'tcpost',
32 => 'sticky', 32 => 'sticky',
64 => 'sticko', 64 => 'sticko',
128 => 'PREROUTING', 128 => 'PREROUTING',
256 => 'INPUT',
512 => 'OUTPUT',
1024 => 'POSTROUTING',
); );
my $inchain = defined $chainref; my $inchain = defined $chainref;
@ -4116,6 +4123,8 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
my $actiontype; my $actiontype;
my $commandref; my $commandref;
my $prerule = ''; my $prerule = '';
my $table = 'mangle';
my $tabletype = MANGLE_TABLE;
# #
# Subroutine for handling MARK and CONNMARK. We use an enclosure so as to keep visibility of the # Subroutine for handling MARK and CONNMARK. We use an enclosure so as to keep visibility of the
# function's local variables without making them static. process_mangle_rule1() is called # function's local variables without making them static. process_mangle_rule1() is called
@ -4157,7 +4166,7 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
$option ||= ( $and_or eq '|' ? '--or-mark' : $and_or ? '--and-mark' : '--set-mark' ); $option ||= ( $and_or eq '|' ? '--or-mark' : $and_or ? '--and-mark' : '--set-mark' );
my $chainref = ensure_chain( 'mangle', $chain = $chainnames{$chain} ); my $chainref = ensure_chain( $table, $chain = $chainnames{$chain} );
$restriction |= $chainref->{restriction}; $restriction |= $chainref->{restriction};
@ -4476,7 +4485,7 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
my ( $tgt, $options ) = split( ' ', $params, 2 ); my ( $tgt, $options ) = split( ' ', $params, 2 );
my $target_type = $builtin_target{$tgt}; my $target_type = $builtin_target{$tgt};
fatal_error "Unknown target ($tgt)" unless $target_type; fatal_error "Unknown target ($tgt)" unless $target_type;
fatal_error "The $tgt TARGET is not allowed in the mangle table" unless $target_type & MANGLE_TABLE; fatal_error "The $tgt TARGET is not allowed in the mangle table" unless $target_type & $tabletype;
$target = $params; $target = $params;
$usergenerated = 1; $usergenerated = 1;
}, },
@ -4492,7 +4501,7 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
my ( $tgt, $options ) = split( ' ', $params, 2 ); my ( $tgt, $options ) = split( ' ', $params, 2 );
my $target_type = $builtin_target{$tgt}; my $target_type = $builtin_target{$tgt};
fatal_error "Unknown target ($tgt)" unless $target_type; fatal_error "Unknown target ($tgt)" unless $target_type;
fatal_error "The $tgt TARGET is not allowed in the mangle table" unless $target_type & MANGLE_TABLE; fatal_error "The $tgt TARGET is not allowed in the mangle table" unless $target_type & $tabletype;
$target = $params; $target = $params;
$usergenerated = 1; $usergenerated = 1;
}, },
@ -4564,7 +4573,7 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
RESTORE => { RESTORE => {
defaultchain => 0, defaultchain => 0,
allowedchains => PREROUTING | INPUT | FORWARD | OUTPUT | POSTROUTING, allowedchains => PREROUTING | INPUT | FORWARD | OUTPUT | POSTROUTING | REALPREROUTING | REALINPUT | REALOUTPUT | REALPOSTROUTING,
minparams => 0, minparams => 0,
maxparams => 1, maxparams => 1,
function => sub () { function => sub () {
@ -4600,7 +4609,7 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
SAVE => { SAVE => {
defaultchain => 0, defaultchain => 0,
allowedchains => PREROUTING | INPUT | FORWARD | OUTPUT | POSTROUTING, allowedchains => PREROUTING | INPUT | FORWARD | OUTPUT | POSTROUTING | REALPREROUTING | REALINPUT | REALOUTPUT | REALPOSTROUTING,
minparams => 0, minparams => 0,
maxparams => 1, maxparams => 1,
function => sub () { function => sub () {
@ -4846,6 +4855,14 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
fatal_error "A chain designator may not be specified in an action body" if $inaction; fatal_error "A chain designator may not be specified in an action body" if $inaction;
my $temp = $designators{$designator}; my $temp = $designators{$designator};
fatal_error "Invalid chain designator ( $designator )" unless $temp; fatal_error "Invalid chain designator ( $designator )" unless $temp;
if ( $designator =~ /^N/ ) {
fatal_error "Only MARK, CONNMARK, SAVE and RESTORE may be used in the nat table" unless $cmd =~ /^(?:(?:(?:CONN)MARK)|SAVE|RESTORE)[(]?/;
require_capability('MARK_ANYWHERE', "The $designator designator", 's');
$table = 'nat';
$tabletype = NAT_TABLE;
}
$designator = $temp; $designator = $temp;
} }
@ -4878,12 +4895,21 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
if ( $source ne '-' ) { if ( $source ne '-' ) {
if ( $source eq $fw ) { if ( $source eq $fw ) {
fatal_error 'Rules with SOURCE $FW must use the OUTPUT chain' if $designator && $designator != OUTPUT; if ( $designator ) {
$chain = OUTPUT; fatal_error 'Rules with SOURCE $FW must use the OUTPUT chain' unless $designator & ( OUTPUT | REALOUTPUT );
$chain = $designator;
} else {
$chain = OUTPUT;
}
$source = '-'; $source = '-';
} elsif ( $source =~ s/^($fw):// ) { } elsif ( $source =~ s/^($fw):// ) {
fatal_error 'Rules with SOURCE $FW must use the OUTPUT chain' if $designator && $designator != OUTPUT; if ( $designator ) {
$chain = OUTPUT; fatal_error 'Rules with SOURCE $FW must use the OUTPUT chain' unless $designator & ( OUTPUT | REALOUTPUT );
$chain = $designator;
} else {
$chain = OUTPUT;
}
} }
} }
@ -4953,11 +4979,11 @@ sub process_mangle_rule1( $$$$$$$$$$$$$$$$$$$ ) {
} else { } else {
$resolve_chain->(); $resolve_chain->();
fatal_error "$cmd rules are not allowed in the $chainlabels{$chain} chain" unless $commandref->{allowedchains} & $chain; fatal_error "$cmd rules are not allowed in the $chainlabels{$chain} chain" unless $commandref->{allowedchains} & $chain;
unless ( $chain == OUTPUT || $chain == POSTROUTING ) { unless ( $chain & ( OUTPUT | POSTROUTING | REALOUTPUT | REALPOSTROUTING ) ) {
fatal_error 'A USER/GROUP may only be specified when the SOURCE is $FW' unless $user eq '-'; fatal_error 'A USER/GROUP may only be specified when the SOURCE is $FW' unless $user eq '-';
} }
$chainref = ensure_chain( 'mangle', $chainnames{$chain} ); $chainref = ensure_chain( $table, $chainnames{$chain} );
} }
$restriction |= $chainref->{restriction}; $restriction |= $chainref->{restriction};

View File

@ -90,8 +90,44 @@
<para>INPUT chain.</para> <para>INPUT chain.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>NP</term>
<listitem>
<para>PREROUTING chain in the nat table.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>NI</term>
<listitem>
<para>INPUT chain in the nat table.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>NO</term>
<listitem>
<para>OUTPUT chain in the nat table.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>NT</term>
<listitem>
<para>POSTROUTING chain in the nat table.</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
<para>The nat table designators were added in Shorewall 5.2.1. When
a nat table designator is given, only the CONNMARK, MARK, SAVE and
RESTORE commands may be used.</para>
<para>Unless otherwise specified for the particular <para>Unless otherwise specified for the particular
<replaceable>command</replaceable>, the default chain is PREROUTING <replaceable>command</replaceable>, the default chain is PREROUTING
when MARK_IN_FORWARD_CHAIN=No in <ulink when MARK_IN_FORWARD_CHAIN=No in <ulink