From 267637f13984fea2b92bd7303dee3ada0fd46bab Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Wed, 20 May 2015 10:55:21 -0700 Subject: [PATCH] NFQUEUE enhancements Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Rules.pm | 61 +++++++++++++++++++---- Shorewall/manpages/shorewall-policy.xml | 12 +++-- Shorewall/manpages/shorewall-rules.xml | 24 ++++++--- Shorewall6/manpages/shorewall6-policy.xml | 14 ++++-- Shorewall6/manpages/shorewall6-rules.xml | 22 ++++++-- 5 files changed, 106 insertions(+), 27 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm index 9ab41cdd5..0c1fd4e1a 100644 --- a/Shorewall/Perl/Shorewall/Rules.pm +++ b/Shorewall/Perl/Shorewall/Rules.pm @@ -468,6 +468,52 @@ sub process_default_action( $$$$ ) { $default; } +# +# Verify an NFQUEUE specification and return the appropriate ip[6]tables target +# +sub handle_nfqueue( $$ ) { + my ($params, $allow_bypass ) = @_; + my $action; + + require_capability( 'NFQUEUE_TARGET', 'NFQUEUE Rules and Policies', '' ); + + my ( $queue, $bypass ) = split ',', $params; + + if ( $queue eq 'bypass' ) { + fatal_error "'bypass' is not allowed in this context" unless $allow_bypass; + fatal_error "Invalid NFQUEUE options (bypass,$bypass)" if supplied $bypass; + return 'NFQUEUE --queue-bypass'; + } + + my ( $queue1, $queue2 ) = split ':', $queue; + + my $queuenum1 = numeric_value( $queue1 ); + my $queuenum2; + + fatal_error "Invalid NFQUEUE queue number ($queue1)" unless defined( $queuenum1) && $queuenum1 >= 0 && $queuenum1 <= 65535; + + if ( supplied $queue2 ) { + $queuenum2 = numeric_value( $queue2 ); + + fatal_error "Invalid NFQUEUE queue number ($queue2)" unless defined( $queuenum2) && $queuenum2 >= 0 && $queuenum2 <= 65535 && $queuenum1 < $queuenum2; + } + + if ( supplied $bypass ) { + fatal_error "Invalid NFQUEUE option ($bypass)" if $bypass ne 'bypass'; + fatal_error "'bypass' is not allowed in this context" unless $allow_bypass; + + $bypass =' --queue-bypass'; + } else { + $bypass = ''; + } + + if ( supplied $queue2 ) { + return "NFQUEUE --queue-balance ${queuenum1}:${queuenum2}${bypass}"; + } else { + return "NFQUEUE --queue-num ${queuenum1}${bypass}"; + } +} + # # Process an entry in the policy file. # @@ -518,11 +564,9 @@ sub process_a_policy() { $default = process_default_action( $originalpolicy, $policy, $default, $level ); if ( defined $queue ) { - fatal_error "Invalid policy ($policy($queue))" unless $policy eq 'NFQUEUE'; - require_capability( 'NFQUEUE_TARGET', 'An NFQUEUE Policy', 's' ); - my $queuenum = numeric_value( $queue ); - fatal_error "Invalid NFQUEUE queue number ($queue)" unless defined( $queuenum) && $queuenum <= 65535; - $policy = "NFQUEUE --queue-num $queuenum"; + $policy = handle_nfqueue( $queue, + 0 # Don't allow 'bypass' + ); } elsif ( $policy eq 'NONE' ) { fatal_error "NONE policy not allowed with \"all\"" if $clientwild || $serverwild; @@ -2276,10 +2320,9 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$$ ) { return $generated; } elsif ( $actiontype & NFQ ) { - require_capability( 'NFQUEUE_TARGET', 'NFQUEUE Rules', '' ); - my $paramval = $param eq '' ? 0 : numeric_value( $param ); - fatal_error "Invalid value ($param) for NFQUEUE queue number" unless defined($paramval) && $paramval <= 65535; - $action = "NFQUEUE --queue-num $paramval"; + $action = handle_nfqueue( $param, + 1 # Allow 'bypass' + ); } elsif ( $actiontype & SET ) { require_capability( 'IPSET_MATCH', 'SET and UNSET rules', '' ); fatal_error "$action rules require a set name parameter" unless $param; diff --git a/Shorewall/manpages/shorewall-policy.xml b/Shorewall/manpages/shorewall-policy.xml index 3a65c2498..fb53245e6 100644 --- a/Shorewall/manpages/shorewall-policy.xml +++ b/Shorewall/manpages/shorewall-policy.xml @@ -105,7 +105,7 @@ role="bold">REJECT|CONTINUE|QUEUE|NFQUEUE[(queuenumber)]|NFQUEUE[(queuenumber1[,queuenumber2])]|NONE}[:{default-action-or-macro[:level]|None}] @@ -180,8 +180,14 @@ Queue the request for a user-space application using the nfnetlink_queue mechanism. If a - queuenumber is not given, queue - zero (0) is assumed. + queuenumber1 is not given, queue + zero (0) is assumed. Beginning with Shorewall 4.6.10, a second + queue number (queuenumber2) may be given. This specifies a + range of queues to use. Packets are then balanced across the + given queues. This is useful for multicore systems: start + multiple instances of the userspace program on queues x, x+1, + .. x+n and use "x:x+n". Packets belonging to the same + connection are put into the same nfqueue. diff --git a/Shorewall/manpages/shorewall-rules.xml b/Shorewall/manpages/shorewall-rules.xml index 8ecb34f5b..5e84772a4 100644 --- a/Shorewall/manpages/shorewall-rules.xml +++ b/Shorewall/manpages/shorewall-rules.xml @@ -559,24 +559,36 @@ NFQUEUE[(queuenumber)] + role="bold">NFQUEUE[([queuenumber1[:queuenumber2][,bypass]]|bypass)] Queues the packet to a user-space application using the nfnetlink_queue mechanism. If a - queuenumber is not specified, queue - zero (0) is assumed. + queuenumber1 is not specified, + queue zero (0) is assumed. Beginning with Shorewall 4.6.10, + the keyword bypass can be + given. By default, if no userspace program is listening on an + NFQUEUE, then all packets that are to be queued are dropped. + When this option is used, the NFQUEUE rule is silently + bypassed instead. The packet will move on to the next rule. + Also beginning in Shorewall 4.6.10, a second queue number + (queuenumber2) may be specified. + This specifies a range of queues to use. Packets are then + balanced across the given queues. This is useful for multicore + systems: start multiple instances of the userspace program on + queues x, x+1, .. x+n and use "x:x+n". Packets belonging to + the same connection are put into the same nfqueue. - NFQUEUE![(queuenumber)] + NFQUEUE[([queuenumber1[,queuenumber2][,bypass]]|bypass)] like NFQUEUE but exempts the rule from being suppressed by OPTIMIZE=1 in shorewall.conf(5). + url="/manpages6/shorewall6.conf.html">shorewall6.conf(5). diff --git a/Shorewall6/manpages/shorewall6-policy.xml b/Shorewall6/manpages/shorewall6-policy.xml index f1390689c..1024eb424 100644 --- a/Shorewall6/manpages/shorewall6-policy.xml +++ b/Shorewall6/manpages/shorewall6-policy.xml @@ -105,9 +105,9 @@ role="bold">REJECT|CONTINUE|QUEUE|NFQUEUE[(queuenumber)]|NFQUEUE[(queuenumber1[,queuenumber2])]|NONE}[:{default-action-or-macro|:{default-action-or-macro[:level]|None}] @@ -180,8 +180,14 @@ Queue the request for a user-space application using the nfnetlink_queue mechanism. If a - queuenumber is not given, queue - zero (0) is assumed. + queuenumber1 is not given, queue + zero (0) is assumed. Beginning with Shorewall 4.6.10, a second + queue number (queuenumber2) may be given. This specifies a + range of queues to use. Packets are then balanced across the + given queues. This is useful for multicore systems: start + multiple instances of the userspace program on queues x, x+1, + .. x+n and use "x:x+n". Packets belonging to the same + connection are put into the same nfqueue. diff --git a/Shorewall6/manpages/shorewall6-rules.xml b/Shorewall6/manpages/shorewall6-rules.xml index d5646db7b..2c0f50ab6 100644 --- a/Shorewall6/manpages/shorewall6-rules.xml +++ b/Shorewall6/manpages/shorewall6-rules.xml @@ -534,19 +534,31 @@ NFQUEUE[(queuenumber)] + role="bold">NFQUEUE[([queuenumber1[:queuenumber2][,bypass]]|bypass)] Queues the packet to a user-space application using the nfnetlink_queue mechanism. If a - queuenumber is not specified, queue - zero (0) is assumed. + queuenumber1 is not specified, + queue zero (0) is assumed. Beginning with Shorewall 4.6.10, + the keyword bypass can be + given. By default, if no userspace program is listening on an + NFQUEUE, then all packets that are to be queued are dropped. + When this option is used, the NFQUEUE rule is silently + bypassed instead. The packet will move on to the next rule. + Also beginning in Shorewall 4.6.10, a second queue number + (queuenumber2) may be specified. + This specifies a range of queues to use. Packets are then + balanced across the given queues. This is useful for multicore + systems: start multiple instances of the userspace program on + queues x, x+1, .. x+n and use "x:x+n". Packets belonging to + the same connection are put into the same nfqueue. - NFQUEUE![(queuenumber)] + NFQUEUE[([queuenumber1[,queuenumber2][,bypass]]|bypass)] like NFQUEUE but exempts the rule from being suppressed