diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm
index acbfeea71..719fce778 100644
--- a/Shorewall/Perl/Shorewall/Chains.pm
+++ b/Shorewall/Perl/Shorewall/Chains.pm
@@ -3370,6 +3370,13 @@ sub combine_dports {
\@rules;
}
+my %bad_match = ( conntrack => 1,
+ dscp => 1,
+ ecn => 1,
+ mark => 1,
+ set => 1,
+ tos => 1,
+ u32 => 1 );
#
# Delete duplicate rules from the passed chain.
#
@@ -3388,22 +3395,10 @@ sub delete_duplicates {
my $duplicate = 0;
if ( $baseref->{mode} == CAT_MODE ) {
- $docheck = 1;
- #
- # We must not suppress duplicate rules that match on things that can
- # be altered by other rules in the chain
- #
- for ( qw( mark connmark dscp tos set ecn u32 ) ) {
- $docheck = 0, last if exists $baseref->{$_};
- }
- } else {
- $docheck = 0;
- }
-
- if ( $docheck ) {
my $ports1;
- my @keys1 = sort( keys( %$baseref ) );
- my $rulenum = @_;
+ my @keys1 = sort( keys( %$baseref ) );
+ my $rulenum = @_;
+ my $adjacent = 1;
{
RULE:
@@ -3419,12 +3414,24 @@ sub delete_duplicates {
my $keynum = 0;
- for my $key ( @keys1 ) {
- next RULE unless $key eq $keys2[$keynum++];
- next RULE unless compare_values( $baseref->{$key}, $ruleref->{$key} );
+ if ( $adjacent > 0 ) {
+ for my $key ( @keys1 ) {
+ next RULE unless $key eq $keys2[$keynum++];
+ next RULE unless compare_values( $baseref->{$key}, $ruleref->{$key} );
+ }
+ } else {
+ for my $key ( @keys1 ) {
+ last RULE if $bad_match{$key};
+ next RULE unless $key eq $keys2[$keynum++];
+ next RULE unless compare_values( $baseref->{$key}, $ruleref->{$key} );
+ }
}
$duplicate = 1;
+ $adjacent++;
+
+ } continue {
+ $adjacent--;
}
}
}
diff --git a/Shorewall/manpages/shorewall.conf.xml b/Shorewall/manpages/shorewall.conf.xml
index 6ce4a3d48..3315a3e35 100644
--- a/Shorewall/manpages/shorewall.conf.xml
+++ b/Shorewall/manpages/shorewall.conf.xml
@@ -1725,8 +1725,13 @@ net all DROP infothen the chain name is 'net2all'
comments are replaced by 'and others'.
Beginning in Shorewall 4.5.10, this option also suppresses
- duplicate rules in a chain that don't include mark, connmark,
- dscp, tos, set, ecn or u32 matches.
+ duplicate adjacent rules and duplicate non-adjacent rules that
+ don't include mark, connmark, dscp, ecn, set, tos
+ or u32 matches.
diff --git a/Shorewall6/manpages/shorewall6.conf.xml b/Shorewall6/manpages/shorewall6.conf.xml
index 06bb0b857..6976ec74a 100644
--- a/Shorewall6/manpages/shorewall6.conf.xml
+++ b/Shorewall6/manpages/shorewall6.conf.xml
@@ -1526,8 +1526,13 @@ net all DROP infothen the chain name is 'net2all'
comments are replaced by 'and others'.
Beginning in Shorewall 4.5.10, this option also suppresses
- duplicate rules in a chain that don't include mark, connmark,
- dscp, tos, set, ecn or u32 matches.
+ duplicate adjacent rules and duplicate non-adjacent rules that
+ don't include mark, connmark, dscp, ecn, set, tos
+ or u32 matches.