diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 402842341..02418913b 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -169,6 +169,7 @@ our %EXPORT_TAGS = ( do_connbytes do_helper do_headers + do_condition have_ipset_rules record_runtime_address conditional_rule @@ -3736,6 +3737,20 @@ sub do_headers( $ ) { "-m ipv6header ${invert}--header ${headers} ${soft}"; } +# +# Generate a -m condition match +# +sub do_condition( $ ) { + my $condition = shift; + + return '' if $condition eq '-'; + + require_capability 'CONDITION_MATCH', 'A non-empty CONDITION column', 's'; + fatal_error "Invalid condition name ($condition)" unless $condition =~ /^[a-zA-Z]\w*$/; + + "-m condition --condition $condition " +} + # # Match Source Interface # diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 26c7f3c93..32527514a 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -280,6 +280,7 @@ my %capdesc = ( NAT_ENABLED => 'NAT', ACCOUNT_TARGET => 'ACCOUNT Target', AUDIT_TARGET => 'AUDIT Target', RAWPOST_TABLE => 'Rawpost Table', + CONDITION_MATCH => 'Condition Match', CAPVERSION => 'Capability Version', KERNELVERSION => 'Kernel Version', ); @@ -444,7 +445,7 @@ sub initialize( $ ) { STATEMATCH => '-m state --state', UNTRACKED => 0, VERSION => "4.4.22.1", - CAPVERSION => 40423 , + CAPVERSION => 40424 , ); # # From shorewall.conf file @@ -664,6 +665,7 @@ sub initialize( $ ) { HEADER_MATCH => undef, ACCOUNT_TARGET => undef, AUDIT_TARGET => undef, + CONDITION_MATCH => undef, CAPVERSION => undef, KERNELVERSION => undef, ); @@ -2671,6 +2673,10 @@ sub Account_Target() { } } +sub Condition_Match() { + qt1( "$iptables -m condition --condition foo" ); +} + sub Audit_Target() { qt1( "$iptables -A $sillyname -j AUDIT --type drop" ); } @@ -2680,6 +2686,7 @@ our %detect_capability = AUDIT_TARGET => \&Audit_Target, ADDRTYPE => \&Addrtype, CLASSIFY_TARGET => \&Classify_Target, + CONDITION_MATCH => \&Condition_Match, COMMENTS => \&Comments, CONNLIMIT_MATCH => \&Connlimit_Match, CONNMARK => \&Connmark, @@ -2853,6 +2860,7 @@ sub determine_capabilities() { $capabilities{ACCOUNT_TARGET} = detect_capability( 'ACCOUNT_TARGET' ); $capabilities{AUDIT_TARGET} = detect_capability( 'AUDIT_TARGET' ); $capabilities{IPSET_V5} = detect_capability( 'IPSET_V5' ); + $capabilities{CONDITION_MATCH} = detect_capability( 'CONDITION_MATCH' ); qt1( "$iptables -F $sillyname" ); diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm index 1de930d26..fee53ca9d 100644 --- a/Shorewall/Perl/Shorewall/Rules.pm +++ b/Shorewall/Perl/Shorewall/Rules.pm @@ -1382,7 +1382,7 @@ sub process_actions() { } -sub process_rule1 ( $$$$$$$$$$$$$$$$ ); +sub process_rule1 ( $$$$$$$$$$$$$$$$$ ); # # Populate an action invocation chain. As new action tuples are encountered, @@ -1415,14 +1415,14 @@ sub process_action( $) { while ( read_a_line ) { - my ($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers ); + my ($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers, $condition ); if ( $format == 1 ) { ($target, $source, $dest, $proto, $ports, $sports, $rate, $user, $mark ) = split_line1 1, 9, 'action file', $rule_commands; - $origdest = $connlimit = $time = $headers = '-'; + $origdest = $connlimit = $time = $headers = $condition = '-'; } else { - ($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers ) - = split_line1 1, 13, 'action file', $action_commands; + ($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers, $condition ) + = split_line1 1, 14, 'action file', $action_commands; } if ( $target eq 'COMMENT' ) { @@ -1456,6 +1456,7 @@ sub process_action( $) { $connlimit, $time, $headers, + $condition, 0 ); } @@ -1485,8 +1486,8 @@ sub use_policy_action( $ ) { # # Expand a macro rule from the rules file # -sub process_macro ( $$$$$$$$$$$$$$$$$ ) { - my ($macro, $chainref, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers, $wildcard ) = @_; +sub process_macro ( $$$$$$$$$$$$$$$$$$ ) { + my ($macro, $chainref, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers, $condition, $wildcard ) = @_; my $nocomment = no_comment; @@ -1504,13 +1505,13 @@ sub process_macro ( $$$$$$$$$$$$$$$$$ ) { while ( read_a_line ) { - my ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders ); + my ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders, $mcondition ); if ( $format == 1 ) { ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $mrate, $muser ) = split_line1 1, 8, 'macro file', $rule_commands; - ( $morigdest, $mmark, $mconnlimit, $mtime, $mheaders ) = qw/- - - - -/; + ( $morigdest, $mmark, $mconnlimit, $mtime, $mheaders, $mcondition ) = qw/- - - - - -/; } else { - ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders ) = split_line1 1, 13, 'macro file', $rule_commands; + ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders, $mcondition ) = split_line1 1, 14, 'macro file', $rule_commands; } if ( $mtarget eq 'COMMENT' ) { @@ -1586,6 +1587,7 @@ sub process_macro ( $$$$$$$$$$$$$$$$$ ) { merge_macro_column( $mconnlimit, $connlimit) , merge_macro_column( $mtime, $time ), merge_macro_column( $mheaders, $headers ), + merge_macro_column( $mcondition, $condition ), $wildcard ); @@ -1618,7 +1620,7 @@ sub verify_audit($;$$) { # Similarly, if a new action tuple is encountered, this function is called recursively for each rule in the action # body. In this latter case, a reference to the tuple's chain is passed in the first ($chainref) argument. # -sub process_rule1 ( $$$$$$$$$$$$$$$$ ) { +sub process_rule1 ( $$$$$$$$$$$$$$$$ $) { my ( $chainref, #reference to Action Chain if we are being called from process_action(); undef otherwise $target, $current_param, @@ -1634,6 +1636,7 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ ) { $connlimit, $time, $headers, + $condition, $wildcard ) = @_; my ( $action, $loglevel) = split_action $target; @@ -1685,6 +1688,7 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ ) { $connlimit, $time, $headers, + $condition, $wildcard ); $macro_nest_level--; @@ -1925,6 +1929,7 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ ) { do_connlimit( $connlimit ), do_time( $time ) , do_headers( $headers ) , + do_condition( $condition ) , ); } else { $rule = join( '', @@ -1934,7 +1939,8 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ ) { do_test( $mark , $globals{TC_MASK} ) , do_connlimit( $connlimit ), do_time( $time ) , - do_headers( $headers ) + do_headers( $headers ) , + do_condition( $condition ) , ); } @@ -2313,8 +2319,8 @@ sub build_zone_list( $$$\$\$ ) { # Process a Record in the rules file # sub process_rule ( ) { - my ( $target, $source, $dest, $protos, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, $time, $headers ) - = split_line1 1, 13, 'rules file', $rule_commands; + my ( $target, $source, $dest, $protos, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, $time, $headers, $condition ) + = split_line1 1, 14, 'rules file', $rule_commands; process_comment, return 1 if $target eq 'COMMENT'; process_section( $source ), return 1 if $target eq 'SECTION'; @@ -2367,6 +2373,7 @@ sub process_rule ( ) { $connlimit, $time, $headers, + $condition, $wild ); } } diff --git a/Shorewall/configfiles/rules b/Shorewall/configfiles/rules index 79fae68cf..068b23ff9 100644 --- a/Shorewall/configfiles/rules +++ b/Shorewall/configfiles/rules @@ -6,8 +6,8 @@ # The manpage is also online at # http://www.shorewall.net/manpages/shorewall-rules.html # -#################################################################################################################################################################### -#ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS +###################################################################################################################################################################################### +#ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS CONDITION # PORT PORT(S) DEST LIMIT GROUP #SECTION ALL #SECTION ESTABLISHED diff --git a/Shorewall/lib.base b/Shorewall/lib.base index e23414417..cae2fdb9e 100644 --- a/Shorewall/lib.base +++ b/Shorewall/lib.base @@ -28,7 +28,7 @@ # SHOREWALL_LIBVERSION=40407 -SHOREWALL_CAPVERSION=40421 +SHOREWALL_CAPVERSION=40424 [ -n "${VARDIR:=/var/lib/shorewall}" ] [ -n "${SHAREDIR:=/usr/share/shorewall}" ] diff --git a/Shorewall/lib.cli b/Shorewall/lib.cli index a669db3c0..a3356e2db 100644 --- a/Shorewall/lib.cli +++ b/Shorewall/lib.cli @@ -1731,6 +1731,7 @@ determine_capabilities() { HEADER_MATCH= ACCOUNT_TARGET= AUDIT_TARGET= + CONDITION_MATCH= chain=fooX$$ @@ -1881,6 +1882,7 @@ determine_capabilities() { qt $IPTABLES -A $chain -j MARK --set-mark 5 && MARK_ANYWHERE=Yes qt $IPTABLES -A $chain -j ACCOUNT --addr 192.168.1.0/29 --tname $chain && ACCOUNT_TARGET=Yes qt $IPTABLES -A $chain -j AUDIT --type drop && AUDIT_TARGET=Yes + qt $IPTABLES -A $chain -m condition --condition foo && CONDITION_MATCH=Yes qt $IPTABLES -F $chain qt $IPTABLES -X $chain qt $IPTABLES -F $chain1 @@ -1975,6 +1977,7 @@ report_capabilities() { report_capability "ACCOUNT Target" $ACCOUNT_TARGET report_capability "AUDIT Target" $AUDIT_TARGET report_capability "ipset V5" $IPSET_V5 + report_capability "Condition Match" $CONDITION_MATCH fi [ -n "$PKTTYPE" ] || USEPKTTYPE= @@ -2045,6 +2048,7 @@ report_capabilities1() { report_capability1 ACCOUNT_TARGET report_capability1 AUDIT_TARGET report_capability1 IPSET_V5 + report_capability1 CONDITION_MATCH echo CAPVERSION=$SHOREWALL_CAPVERSION echo KERNELVERSION=$KERNELVERSION diff --git a/Shorewall6/lib.base b/Shorewall6/lib.base index a4dcae25c..76d1422f1 100644 --- a/Shorewall6/lib.base +++ b/Shorewall6/lib.base @@ -32,7 +32,7 @@ # SHOREWALL_LIBVERSION=40407 -SHOREWALL_CAPVERSION=40423 +SHOREWALL_CAPVERSION=40424 [ -n "${VARDIR:=/var/lib/shorewall6}" ] [ -n "${SHAREDIR:=/usr/share/shorewall6}" ] diff --git a/Shorewall6/lib.cli b/Shorewall6/lib.cli index 8fc9f5113..6b4848b22 100644 --- a/Shorewall6/lib.cli +++ b/Shorewall6/lib.cli @@ -1558,6 +1558,7 @@ determine_capabilities() { ACCOUNT_TARGET= AUDIT_TARGET= IPSET_V5= + CONDITION_MATCH= chain=fooX$$ @@ -1709,6 +1710,7 @@ determine_capabilities() { qt $IP6TABLES -A $chain -m ipv6header --header 255 && HEADER_MATCH=Yes qt $IP6TABLES -A $chain -j ACCOUNT --addr 1::/122 --tname $chain && ACCOUNT_TARGET=Yes qt $IP6TABLES -A $chain -j AUDIT --type drop && AUDIT_TARGET=Yes + qt $IP6TABLES -A $chain -m condition --condition foo && CONDITION_MATCH=Yes qt $IP6TABLES -F $chain @@ -1802,6 +1804,7 @@ report_capabilities() { report_capability "ACCOUNT Target" $ACCOUNT_TARGET report_capability "AUDIT Target" $AUDIT_TARGET report_capability "ipset V5" $IPSET_V5 + report_capability "Condition Match" $CONDITION_MATCH fi [ -n "$PKTTYPE" ] || USEPKTTYPE= @@ -1869,6 +1872,7 @@ report_capabilities1() { report_capability1 ACCOUNT_TARGET report_capability1 AUDIT_TARGET report_capability1 IPSET_V5 + report_capability1 CONDITION_MATCH echo CAPVERSION=$SHOREWALL_CAPVERSION echo KERNELVERSION=$KERNELVERSION diff --git a/manpages/shorewall-rules.xml b/manpages/shorewall-rules.xml index aa46d1e67..6009b4d4d 100644 --- a/manpages/shorewall-rules.xml +++ b/manpages/shorewall-rules.xml @@ -1267,6 +1267,30 @@ + + + HEADERS + + + Added in Shorewall 4.4.15. Not used in IPv4 configurations. If + you with to supply a value for one of the later columns, enter '-' + in this column. + + + + + CONDITION - + [!]condition-name + + + Added in Shorewall 4.4.24. Matches if the value stored in + /proc/net/nf_condition/condition-name + is 1. Does not match if that file contains 0 (the default). If '!' + is supplied, the test is inverted such that there is a match if the + file contains 0. The condition-name must begin with a letter and be + composed of letters, decimal digits or underscores. + + @@ -1457,6 +1481,19 @@ SSH(ACCEPT) net all - - - - s:1/min:3 + + + Example 12: + + + Forward port 80 to dmz host $BACKUP if condition + 'primary_down' is set. + + #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS CONDITION + # PORT(S) PORT(S) DEST LIMIT GROUP + DNAT net dmz:$BACKUP tcp 80 - - - - - - - - primary_down + + diff --git a/manpages6/shorewall6-rules.xml b/manpages6/shorewall6-rules.xml index 11ff82842..ecebf06bf 100644 --- a/manpages6/shorewall6-rules.xml +++ b/manpages6/shorewall6-rules.xml @@ -1102,6 +1102,20 @@ role="bold">! is omitted. + + + CONDITION - + [!]condition-name + + + Added in Shorewall6 4.4.24. Matches if the value stored in + /proc/net/nf_condition/condition-name + is 1. Does not match if that file contains 0 (the default). If '!' + is supplied, the test is inverted such that there is a match if the + file contains 0. The condition-name must begin with a letter and be + composed of letters, decimal digits or underscores. + + @@ -1148,6 +1162,19 @@ SSH(ACCEPT) net all - - - - s:1/min:3 + + + Example 6: + + + Forward port 80 to dmz host $BACKUP if condition + 'primary_down' is set. + + #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS CONDITION + # PORT(S) PORT(S) DEST LIMIT GROUP + DNAT net dmz:$BACKUP tcp 80 - - - - - - - - primary_down + + @@ -1162,8 +1189,8 @@ shorewall6(8), shorewall6-accounting(5), shorewall6-actions(5), shorewall6-blacklist(5), shorewall6-hosts(5), shorewall6-interfaces(5), - shorewall6-maclist(5), shoewall6-netmap(5),shorewall6-params(5), shorewall6-policy(5), - shorewall6-providers(5), shorewall6-route_rules(5), + shorewall6-maclist(5), shoewall6-netmap(5),shorewall6-params(5), + shorewall6-policy(5), shorewall6-providers(5), shorewall6-route_rules(5), shorewall6-routestopped(5), shorewall6.conf(5), shorewall6-secmarks(5), shorewall6-tcclasses(5), shorewall6-tcdevices(5), shorewall6-tcrules(5), shorewall6-tos(5), shorewall6-tunnels(5), shorewall6-zones(5)