diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm
index 2c66c22b6..0d2c7c921 100644
--- a/Shorewall/Perl/Shorewall/Chains.pm
+++ b/Shorewall/Perl/Shorewall/Chains.pm
@@ -117,6 +117,7 @@ our %EXPORT_TAGS = (
OPTIMIZE_RULESET_MASK
OPTIMIZE_MASK
+ state_match
state_imatch
initialize_chain_table
copy_rules
@@ -3715,6 +3716,16 @@ sub port_count( $ ) {
#
# Generate a state match
#
+sub state_match( $ ) {
+ my $state = shift;
+
+ if ( $state eq 'ALL' ) {
+ ''
+ } else {
+ have_capability 'CONNTRACK_MATCH' ? ( "-m conntrack --ctstate $state " ) : ( "-m state --state $state " );
+ }
+}
+
sub state_imatch( $ ) {
my $state = shift;
diff --git a/Shorewall/Perl/Shorewall/Tc.pm b/Shorewall/Perl/Shorewall/Tc.pm
index c85226fd0..897a6c865 100644
--- a/Shorewall/Perl/Shorewall/Tc.pm
+++ b/Shorewall/Perl/Shorewall/Tc.pm
@@ -174,6 +174,12 @@ my $family;
my $divertref; # DIVERT chain
+my %validstates = ( NEW => 0,
+ RELATED => 0,
+ ESTABLISHED => 0,
+ UNTRACKED => 0,
+ INVALID => 0,
+ );
#
# Rather than initializing globals in an INIT block or during declaration,
# we initialize them in a function. This is done for two reasons:
@@ -199,14 +205,14 @@ sub initialize( $ ) {
}
sub process_tc_rule( ) {
- my ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability , $dscp );
+ my ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability , $dscp , $state );
if ( $family == F_IPV4 ) {
- ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $probability, $dscp ) =
- split_line1 'tcrules file', { mark => 0, action => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, probability => 12 , dscp => 13 }, { COMMENT => 0, FORMAT => 2 } , 14;
+ ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $probability, $dscp, $state ) =
+ split_line1 'tcrules file', { mark => 0, action => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, probability => 12 , dscp => 13, state => 14 }, { COMMENT => 0, FORMAT => 2 } , 15;
$headers = '-';
} else {
- ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability, $dscp ) =
- split_line1 'tcrules file', { mark => 0, action => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, headers => 12, probability => 13 , dscp => 14 }, { COMMENT => 0, FORMAT => 2 }, 15;
+ ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability, $dscp, $state ) =
+ split_line1 'tcrules file', { mark => 0, action => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, headers => 12, probability => 13 , dscp => 14 , state => 15 }, { COMMENT => 0, FORMAT => 2 }, 16;
}
our @tccmd;
@@ -259,6 +265,7 @@ sub process_tc_rule( ) {
my $cmd;
my $rest;
my $matches = '';
+ my $mark1;
my %processtcc = ( sticky => sub() {
if ( $chain eq 'tcout' ) {
@@ -501,7 +508,7 @@ sub process_tc_rule( ) {
$chain = $tcsref->{chain} if $tcsref->{chain};
$target = $tcsref->{target} if $tcsref->{target};
- $mark = "$mark/" . in_hex( $globals{TC_MASK} ) if $connmark = $tcsref->{connmark};
+ $mark = "$mark/" . in_hex( $globals{TC_MASK} ) if $connmark = $tcsref->{connmark} && $mark !~ m'/';
require_capability ('CONNMARK' , "CONNMARK Rules", '' ) if $connmark;
@@ -584,15 +591,23 @@ sub process_tc_rule( ) {
}
}
- validate_mark $mark;
+ if ( $mark =~ /-/ ) {
+ ( $mark, $mark1 ) = split /-/, $mark, 2;
+ validate_mark $mark;
+ fatal_error "Invalid mark range ($mark-$mark1)" if $mark =~ m'/';
+ validate_mark $mark1;
+ require_capability 'STATISTIC_MATCH', 'A mark range', 's';
+ } else {
+ validate_mark $mark;
- if ( $config{PROVIDER_OFFSET} ) {
- my $val = numeric_value( $cmd );
- fatal_error "Invalid MARK/CLASSIFY ($cmd)" unless defined $val;
- my $limit = $globals{TC_MASK};
- unless ( have_capability 'FWMARK_RT_MASK' ) {
- fatal_error "Marks <= $limit may not be set in the PREROUTING or OUTPUT chains when HIGH_ROUTE_MARKS=Yes"
- if $cmd && ( $chain eq 'tcpre' || $chain eq 'tcout' ) && $val <= $limit;
+ if ( $config{PROVIDER_OFFSET} ) {
+ my $val = numeric_value( $cmd );
+ fatal_error "Invalid MARK/CLASSIFY ($cmd)" unless defined $val;
+ my $limit = $globals{TC_MASK};
+ unless ( have_capability 'FWMARK_RT_MASK' ) {
+ fatal_error "Marks <= $limit may not be set in the PREROUTING or OUTPUT chains when HIGH_ROUTE_MARKS=Yes"
+ if $cmd && ( $chain eq 'tcpre' || $chain eq 'tcout' ) && $val <= $limit;
+ }
}
}
}
@@ -600,26 +615,88 @@ sub process_tc_rule( ) {
fatal_error "USER/GROUP only allowed in the OUTPUT chain" unless ( $user eq '-' || ( $chain eq 'tcout' || $chain eq 'tcpost' ) );
- if ( ( my $result = expand_rule( ensure_chain( 'mangle' , $chain ) ,
- $restrictions{$chain} | $restriction,
- do_proto( $proto, $ports, $sports) . $matches .
- do_user( $user ) .
- do_test( $testval, $globals{TC_MASK} ) .
- do_length( $length ) .
- do_tos( $tos ) .
- do_connbytes( $connbytes ) .
- do_helper( $helper ) .
- do_headers( $headers ) .
- do_probability( $probability ) .
- do_dscp( $dscp ) ,
- $source ,
- $dest ,
- '' ,
- $mark ? "$target $mark" : $target,
- '' ,
- $target ,
- '' ) )
- && $device ) {
+ if ( $state ne '-' ) {
+ my @state = split_list( $state, 'state' );
+ my %state = %validstates;
+
+ for ( @state ) {
+ fatal_error "Invalid STATE ($_)" unless exists $state{$_};
+ fatal_error "Duplicate STATE ($_)" if $state{$_};
+ }
+ } else {
+ $state = 'ALL';
+ }
+
+ if ( $mark1 ) {
+ #
+ # A Mark Range
+ #
+ my $chainref = ensure_chain( 'mangle', $chain );
+
+ ( $mark1, my $mask ) = split( '/', $mark1 );
+
+ my ( $markval, $mark1val ) = ( numeric_value $mark, numeric_value $mark1 );
+
+ fatal_error "Invalid mark range ($mark-$mark1)" unless $markval < $mark1val;
+
+ $mask = $globals{TC_MASK} unless supplied $mask;
+
+ $mask = numeric_value $mask;
+
+ my $increment = 1;
+
+ $increment <<= 1 until $increment & $mask;
+
+ $mask = in_hex $mask;
+
+ my $marks = $mark1val - $markval + 1;
+
+ for ( my $packet = 0; $packet < $marks; $packet++, $markval += $increment ) {
+ my $match = "-m statistic --mode nth --every $marks --packet $packet ";
+
+ expand_rule( $chainref,
+ $restrictions{$chain} | $restriction,
+ $match .
+ do_user( $user ) .
+ do_test( $testval, $globals{TC_MASK} ) .
+ do_test( $testval, $globals{TC_MASK} ) .
+ do_length( $length ) .
+ do_tos( $tos ) .
+ do_connbytes( $connbytes ) .
+ do_helper( $helper ) .
+ do_headers( $headers ) .
+ do_probability( $probability ) .
+ do_dscp( $dscp ) .
+ state_match( $state ) ,
+ $source ,
+ $dest ,
+ '' ,
+ "$target " . join( '/', in_hex( $markval ) , $mask ) ,
+ '',
+ $target ,
+ '' );
+ }
+ } elsif ( ( my $result = expand_rule( ensure_chain( 'mangle' , $chain ) ,
+ $restrictions{$chain} | $restriction,
+ do_proto( $proto, $ports, $sports) . $matches .
+ do_user( $user ) .
+ do_test( $testval, $globals{TC_MASK} ) .
+ do_length( $length ) .
+ do_tos( $tos ) .
+ do_connbytes( $connbytes ) .
+ do_helper( $helper ) .
+ do_headers( $headers ) .
+ do_probability( $probability ) .
+ do_dscp( $dscp ) .
+ state_match( $state ) ,
+ $source ,
+ $dest ,
+ '' ,
+ $mark ? "$target $mark" : $target,
+ '' ,
+ $target ,
+ '' ) )
+ && $device ) {
#
# expand_rule() returns destination device if any
#
diff --git a/Shorewall/manpages/shorewall-masq.xml b/Shorewall/manpages/shorewall-masq.xml
index 92b731c9a..be2dc7a25 100644
--- a/Shorewall/manpages/shorewall-masq.xml
+++ b/Shorewall/manpages/shorewall-masq.xml
@@ -619,6 +619,29 @@
eth0:+myset[dst] - 206.124.146.177
+
+
+ Example 7:
+
+
+ SNAT outgoing connections on eth0 from 192.168.1.0/24 in
+ round-robin fashion between addresses 1.1.1.1, 1.1.1.3, and 1.1.1.9
+ (Shorewall 4.5.9 and later).
+
+ /etc/shorewall/tcrules:
+
+ #ACTION SOURCE DEST PROTO PORT(S) SOURCE USER TEST
+ # PORT(S)
+ 1-3:CF 192.168.1.0/24 eth0 ; state=NEW
+
+/etc/shorewall/masq:
+
+ #INTERFACE SOURCE ADDRESS ...
+ eth0 192.168.1.0/24 1.1.1.1 ; mark=1:C
+ eth0 192.168.1.0/24 1.1.1.3 ; mark=2:C
+ eth0 192.168.1.0/24 1.1.1.4 ; mark=3:C
+
+
diff --git a/Shorewall/manpages/shorewall-tcrules.xml b/Shorewall/manpages/shorewall-tcrules.xml
index d23953d94..60875b96c 100644
--- a/Shorewall/manpages/shorewall-tcrules.xml
+++ b/Shorewall/manpages/shorewall-tcrules.xml
@@ -131,8 +131,12 @@
The mark value may be optionally followed by "/" and a
mask value (used to determine those bits of the connection mark
- to actually be set). The mark and optional mask are then
- followed by one of:
+ to actually be set). When a mask is specified, the result of
+ logically ANDing the mark value with the mask must be the same
+ as the mark value.
+
+ The mark and optional mask are then followed by one
+ of:
@@ -178,26 +182,114 @@
+
- Special considerations for If
- HIGH_ROUTE_MARKS=Yes in shorewall.conf(5).
+
+ A mark range which is a pair of integers separated by a
+ dash ("-"). Added in Shorewall 4.5.9.
- If HIGH_ROUTE_MARKS=Yes, then you may also specify a value
- in the range 0x0100-0xFF00 with the low-order byte being zero.
- Such values may only be used in the PREROUTING chain (value
- followed by :P or you have set
- MARK_IN_FORWARD_CHAIN=No in shorewall.conf(5) and have not
- followed the value with ) or the OUTPUT chain
- (SOURCE is $FW). With
- HIGH_ROUTE_MARKS=Yes, non-zero mark values less that 256 are not
- permitted. Shorewall prohibits non-zero mark values less that
- 256 in the OUTPUT chain when HIGH_ROUTE_MARKS=Yes. While earlier
- versions allow such values in the OUTPUT chain, it is strongly
- recommended that with HIGH_ROUTE_MARKS=Yes, you use the
- POSTROUTING chain to apply traffic shaping
- marks/classification.
+ May be optionally followed by a slash ("/") and a mask and
+ requires the Statistics Match capability
+ in iptables and kernel. Marks in the specified range are
+ assigned to packets on a round-robin fashion.
+
+ When a mask is specified, the result of logically ANDing
+ the mark value with the mask must be the same as the mark value.
+ The least significant bit in the mask is used as an increment.
+ For example, if '0x200-0x400/0xff00' is specified, then the
+ assigned mark values are 0x200, 0x300 and 0x400 in equal
+ proportions. If no mask is specified, then ( 2 ** MASK_BITS ) -
+ 1 is assumed (MASK_BITS is set in shorewall.conf(5)).
+
+ May optionally be followed by :P, :F,:T or
+ :I where
+ :P indicates that marking should occur in the
+ PREROUTING chain, :F indicates
+ that marking should occur in the FORWARD chain, :I indicates that marking should occur in
+ the INPUT chain (added in Shorewall 4.4.13), and :T indicates that marking should occur in
+ the POSTROUTING chain. If neither :P, :F
+ nor :T follow the mark value
+ then the chain is determined as follows:
+
+ - If the SOURCE is $FW[:address-or-range[,address-or-range]...],
+ then the rule is inserted into the OUTPUT chain. When
+ HIGH_ROUTE_MARKS=Yes, only high mark values may be assigned
+ there. Packet marking rules for traffic shaping of packets
+ originating on the firewall must be coded in the POSTROUTING
+ chain (see below).
+
+ - Otherwise, the chain is determined by the setting of
+ MARK_IN_FORWARD_CHAIN in shorewall.conf(5).
+
+ Please note that :I is
+ included for completeness and affects neither traffic shaping
+ nor policy routing.
+
+ If your kernel and iptables include CONNMARK support then
+ you can also mark the connection rather than the packet.
+
+ The mark range may be optionally followed by "/" and a
+ mask value (used to determine those bits of the connection mark
+ to actually be set). When a mask is specified, the result of
+ logically ANDing the mark value with each of the masks must be
+ the same as the mark value.
+
+ The mark and optional mask are then followed by one
+ of:
+
+
+
+ C
+
+
+ Mark the connection in the chain determined by the
+ setting of MARK_IN_FORWARD_CHAIN
+
+
+
+
+ CF
+
+
+ Mark the connection in the FORWARD chain
+
+
+
+
+ CP
+
+
+ Mark the connection in the PREROUTING chain.
+
+
+
+
+ CT
+
+
+ Mark the connecdtion in the POSTROUTING chain
+
+
+
+
+ CI
+
+
+ Mark the connection in the INPUT chain. This option
+ is included for completeness and has no applicability to
+ traffic shaping or policy routing.
+
+
+
@@ -530,6 +622,17 @@ SAME $FW 0.0.0.0/0 tcp 80,443
role="bold">:F
+
+ STATE {NEW|RELATED|ESTABLISHED|INVALID} [,...]
+
+ Added in Shorewall 4.5.9. The rule will only match if the
+ packet's connection is in one of the listed states.
+
+
TOS(tos[/mask])
@@ -1124,6 +1227,29 @@ Normal-Service => 0x00
mark has been set, save it to the connection mark.
+
+
+ Example 2:
+
+
+ SNAT outgoing connections on eth0 from 192.168.1.0/24 in
+ round-robin fashion between addresses 1.1.1.1, 1.1.1.3, and 1.1.1.9
+ (Shorewall 4.5.9 and later).
+
+ /etc/shorewall/tcrules:
+
+ #ACTION SOURCE DEST PROTO PORT(S) SOURCE USER TEST
+ # PORT(S)
+ 1-3:CF 192.168.1.0/24 eth0 ; state=NEW
+
+/etc/shorewall/masq:
+
+ #INTERFACE SOURCE ADDRESS ...
+ eth0 192.168.1.0/24 1.1.1.1 ; mark=1:C
+ eth0 192.168.1.0/24 1.1.1.3 ; mark=2:C
+ eth0 192.168.1.0/24 1.1.1.4 ; mark=3:C
+
+
diff --git a/Shorewall6/manpages/shorewall6-tcrules.xml b/Shorewall6/manpages/shorewall6-tcrules.xml
index b999b82b2..6ef430563 100644
--- a/Shorewall6/manpages/shorewall6-tcrules.xml
+++ b/Shorewall6/manpages/shorewall6-tcrules.xml
@@ -131,8 +131,12 @@
The mark value may be optionally followed by "/" and a
mask value (used to determine those bits of the connection mark
- to actually be set). The mark and optional mask are then
- followed by one of:+
+ to actually be set). When a mask is specified, the result of
+ logically ANDing the mark value with the mask must be the same
+ as the mark value.
+
+ The mark and optional mask are then followed by one
+ of:+
@@ -178,26 +182,114 @@
+
- Special considerations for If
- HIGH_ROUTE_MARKS=Yes in shorewall6.conf(5).
+
+ A mark range which is a pair of integers separated by a
+ dash ("-"). Added in Shorewall 4.5.9.
- If HIGH_ROUTE_MARKS=Yes, then you may also specify a value
- in the range 0x0100-0xFF00 with the low-order byte being zero.
- Such values may only be used in the PREROUTING chain (value
- followed by :P or you have set
- MARK_IN_FORWARD_CHAIN=No in shorewall6.conf(5) and have
- not followed the value with ) or the OUTPUT
- chain (SOURCE is $FW). With
- HIGH_ROUTE_MARKS=Yes, non-zero mark values less that 256 are not
- permitted. Shorewall6 prohibits non-zero mark values less that
- 256 in the OUTPUT chain when HIGH_ROUTE_MARKS=Yes. While earlier
- versions allow such values in the OUTPUT chain, it is strongly
- recommended that with HIGH_ROUTE_MARKS=Yes, you use the
- POSTROUTING chain to apply traffic shaping
- marks/classification.
+ May be optionally followed by a slash ("/") and a mask and
+ requires the Statistics Match capability
+ in iptables and kernel. Marks in the specified range are
+ assigned to packets on a round-robin fashion.
+
+ When a mask is specified, the result of logically ANDing
+ the mark value with the mask must be the same as the mark value.
+ The least significant bit in the mask is used as an increment.
+ For example, if '0x200-0x400/0xff00' is specified, then the
+ assigned mark values are 0x200, 0x300 and 0x400 in equal
+ proportions. If no mask is specified, then ( 2 ** MASK_BITS ) -
+ 1 is assumed (MASK_BITS is set in shorewall6.conf(5)).
+
+ May optionally be followed by :P, :F,:T or
+ :I where
+ :P indicates that marking should occur in the
+ PREROUTING chain, :F indicates
+ that marking should occur in the FORWARD chain, :I indicates that marking should occur in
+ the INPUT chain (added in Shorewall 4.4.13), and :T indicates that marking should occur in
+ the POSTROUTING chain. If neither :P, :F
+ nor :T follow the mark value
+ then the chain is determined as follows:
+
+ - If the SOURCE is $FW[:address-or-range[,address-or-range]...],
+ then the rule is inserted into the OUTPUT chain. When
+ HIGH_ROUTE_MARKS=Yes, only high mark values may be assigned
+ there. Packet marking rules for traffic shaping of packets
+ originating on the firewall must be coded in the POSTROUTING
+ chain (see below).
+
+ - Otherwise, the chain is determined by the setting of
+ MARK_IN_FORWARD_CHAIN in shorewall.conf(5).
+
+ Please note that :I is
+ included for completeness and affects neither traffic shaping
+ nor policy routing.
+
+ If your kernel and iptables include CONNMARK support then
+ you can also mark the connection rather than the packet.
+
+ The mark range may be optionally followed by "/" and a
+ mask value (used to determine those bits of the connection mark
+ to actually be set). When a mask is specified, the result of
+ logically ANDing the mark value with each of the masks must be
+ the same as the mark value.
+
+ The mark and optional mask are then followed by one
+ of:
+
+
+
+ C
+
+
+ Mark the connection in the chain determined by the
+ setting of MARK_IN_FORWARD_CHAIN
+
+
+
+
+ CF
+
+
+ Mark the connection in the FORWARD chain
+
+
+
+
+ CP
+
+
+ Mark the connection in the PREROUTING chain.
+
+
+
+
+ CT
+
+
+ Mark the connecdtion in the POSTROUTING chain
+
+
+
+
+ CI
+
+
+ Mark the connection in the INPUT chain. This option
+ is included for completeness and has no applicability to
+ traffic shaping or policy routing.
+
+
+
@@ -451,6 +543,17 @@ SAME $FW 0.0.0.0/0 tcp 80,443
role="bold">:F
+
+ STATE {NEW|RELATED|ESTABLISHED|INVALID} [,...]
+
+ Added in Shorewall 4.5.9. The rule will only match if the
+ packet's connection is in one of the listed states.
+
+
TOS(tos[/mask])
diff --git a/docs/PacketMarking.xml b/docs/PacketMarking.xml
index d05f85d5d..1defd85e1 100644
--- a/docs/PacketMarking.xml
+++ b/docs/PacketMarking.xml
@@ -278,8 +278,9 @@ tcp 6 19 TIME_WAIT src=206.124.146.176 dst=192.136.34.98 sport=58597 dport=
Shorewall actually allows you to have complete control over the
layout of the 32-bit mark using the following options in shorewall.conf (5) (these
- options were documents in the shorewall.conf manpage in Shorewall
- 4.4.26):
+ options were documentrf in the shorewall.conf(5) manpage in
+ Shorewall 4.4.26):
@@ -339,9 +340,9 @@ tcp 6 19 TIME_WAIT src=206.124.146.176 dst=192.136.34.98 sport=58597 dport=
The relationship between these options is shown in this
diagram.
-
+
-
+ The default values of these options are determined by the settings
of other options as follows: