From 28cc9eec766a0b61a49b2c700d57ee00ea2dd165 Mon Sep 17 00:00:00 2001 From: teastep Date: Tue, 7 Oct 2008 23:23:07 +0000 Subject: [PATCH] Add CONNLIMIT support git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@8757 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb --- Shorewall-common/changelog.txt | 2 ++ Shorewall-common/policy | 4 ++-- Shorewall-common/releasenotes.txt | 37 ++++++++++++++++++++++++++++++ Shorewall-common/rules | 4 ++-- Shorewall-perl/Shorewall/Chains.pm | 23 ++++++++++++++++++- Shorewall-perl/Shorewall/Policy.pm | 11 ++++++--- Shorewall-perl/Shorewall/Rules.pm | 35 +++++++++++++++------------- docs/support.xml | 31 +++++++++++++------------ manpages/shorewall-policy.xml | 27 +++++++++++++++++++++- manpages/shorewall-rules.xml | 27 +++++++++++++++++++++- 10 files changed, 160 insertions(+), 41 deletions(-) diff --git a/Shorewall-common/changelog.txt b/Shorewall-common/changelog.txt index 958323853..fc7af47ed 100644 --- a/Shorewall-common/changelog.txt +++ b/Shorewall-common/changelog.txt @@ -4,4 +4,6 @@ Changes in Shorewall 4.2.1 2) Fixed minor CONNBYTES editing issue. +3) Add CONNLIMIT to policy and rules. + Initial release of Shorewall 4.2.0. diff --git a/Shorewall-common/policy b/Shorewall-common/policy index a58443d48..8fe5fe14b 100644 --- a/Shorewall-common/policy +++ b/Shorewall-common/policy @@ -7,6 +7,6 @@ # http://www.shorewall.net/manpages/shorewall-policy.html # ############################################################################### -#SOURCE DEST POLICY LOG LIMIT:BURST -# LEVEL +#SOURCE DEST POLICY LOG LIMIT: CONNLIMIT: +# LEVEL BURST MASK #LAST LINE -- DO NOT REMOVE diff --git a/Shorewall-common/releasenotes.txt b/Shorewall-common/releasenotes.txt index fc9e87037..268881fe3 100644 --- a/Shorewall-common/releasenotes.txt +++ b/Shorewall-common/releasenotes.txt @@ -88,6 +88,43 @@ Problems corrected in Shorewall 4.2.1 non-zero. A value of zero for was equivalent to omitting . +Other changes in Shorewall 4.2.1 + +1) With the recent renewed interest in DOS attacks, it seems + appropriate to have connection limiting support in Shorewall. To + that end, a CONNLIMIT column has been added to both the policy and + rules files. + + The content of these columns is of the format + + [!] [:] + + where + + is the limit on simultaneous TCP connections. + + specifies the size of the network to which + the limit applies and is specified as a + CIDR mask length. The default value for + is 32 which means that each remote + IP address can have TCP connections + active at once. + + ! Not allowed in the policy file. In the rules file, it + causes connections to match when the number of + current connections exceeds . + + When specified in the policy file, the limit is envorced on all + connections that are subject to the given policy (just like + LIMIT:BURST). The limit is checked on new connections before the + connection is passed through the rules in the NEW section of the + rules file. + + It is important to note that while the limit is only checked for + those destinations specified in the DEST column, the number of + current connections is calculated over all destinations and not + just the destination specified in the DEST column. + New Features in Shorewall 4.2. 1) Shorewall 4.2 contains support for multiple Internet providers diff --git a/Shorewall-common/rules b/Shorewall-common/rules index ed90106e4..00f21d3ea 100644 --- a/Shorewall-common/rules +++ b/Shorewall-common/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 +###################################################################################################################################### +#ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT # PORT PORT(S) DEST LIMIT GROUP #SECTION ESTABLISHED #SECTION RELATED diff --git a/Shorewall-perl/Shorewall/Chains.pm b/Shorewall-perl/Shorewall/Chains.pm index a44892b8d..f054558cb 100644 --- a/Shorewall-perl/Shorewall/Chains.pm +++ b/Shorewall-perl/Shorewall/Chains.pm @@ -120,6 +120,7 @@ our %EXPORT_TAGS = ( validate_mark do_test do_ratelimit + do_connlimit do_user do_tos do_connbytes @@ -169,7 +170,7 @@ our $VERSION = 4.1.5; # policychain => -- self-reference if this is a policy chain # policypair => [ , ] -- Used for reporting duplicated policies # loglevel => -# synparams => +# synparams => # synchain => # default => # cmdlevel => @@ -1269,6 +1270,26 @@ sub do_ratelimit( $$ ) { } } +# +# Create a "-m connlimit" match for the passed CONNLIMIT +# +sub do_connlimit( $ ) { + my ( $limit ) = @_; + + return '' unless $limit and $limit ne '-'; + + my $invert = $limit =~ s/^!// ? '' : '! '; # Note Carefully -- we actually do 'connlimit-at-or-below' + + if ( $limit =~ /^(\d+):(\d+)$/ ) { + fatal_error "Invalid Mask ($2)" unless $2 > 0 || $2 < 31; + "-m connlimit ${invert}--connlimit-above $1 --connmask $2"; + } elsif ( $limit =~ /^(\d+)$/ ) { + "-m connlimit ${invert}--connlimit-above $limit "; + } else { + fatal_error "Invalid connlimit ($limit)"; + } +} + # # Create a "-m owner" match for the passed USER/GROUP # diff --git a/Shorewall-perl/Shorewall/Policy.pm b/Shorewall-perl/Shorewall/Policy.pm index f83be9859..2d1061610 100644 --- a/Shorewall-perl/Shorewall/Policy.pm +++ b/Shorewall-perl/Shorewall/Policy.pm @@ -212,10 +212,11 @@ sub validate_policy() while ( read_a_line ) { - my ( $client, $server, $originalpolicy, $loglevel, $synparams ) = split_line 3, 5, 'policy file'; + my ( $client, $server, $originalpolicy, $loglevel, $synparams, $connlimit ) = split_line 3, 6, 'policy file'; $loglevel = '' if $loglevel eq '-'; $synparams = '' if $synparams eq '-'; + $connlimit = '' if $connlimit eq '-'; my $clientwild = ( "\L$client" eq 'all' ); @@ -300,8 +301,12 @@ sub validate_policy() $chainref->{loglevel} = validate_level( $loglevel ) if defined $loglevel && $loglevel ne ''; - if ( $synparams ne '' ) { - $chainref->{synparams} = do_ratelimit $synparams, 'ACCEPT'; + if ( $synparams ne '' || $connlimit ne '' ) { + my $value = ''; + fatal_error "Invalid CONNLIMIT ($connlimit)" if $connlimit =~ /^!/; + $value = do_ratelimit $synparams, 'ACCEPT' if $synparams ne ''; + $value = do_connlimit $connlimit if $connlimit ne ''; + $chainref->{synparams} = $value; $chainref->{synchain} = $chain } diff --git a/Shorewall-perl/Shorewall/Rules.pm b/Shorewall-perl/Shorewall/Rules.pm index 009c72c85..2c43bd51c 100644 --- a/Shorewall-perl/Shorewall/Rules.pm +++ b/Shorewall-perl/Shorewall/Rules.pm @@ -811,13 +811,13 @@ sub setup_mac_lists( $ ) { } } -sub process_rule1 ( $$$$$$$$$$$ ); +sub process_rule1 ( $$$$$$$$$$$$ ); # # Expand a macro rule from the rules file # -sub process_macro ( $$$$$$$$$$$$$ ) { - my ($macro, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $wildcard ) = @_; +sub process_macro ( $$$$$$$$$$$$$$ ) { + my ($macro, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $wildcard ) = @_; my $nocomment = no_comment; @@ -906,6 +906,7 @@ sub process_macro ( $$$$$$$$$$$$$ ) { merge_macro_column( $mrate, $rate ) , merge_macro_column( $muser, $user ) , $mark, + $connlimit, $wildcard ); @@ -923,8 +924,8 @@ sub process_macro ( $$$$$$$$$$$$$ ) { # Once a rule has been expanded via wildcards (source and/or dest zone == 'all'), it is processed by this function. If # the target is a macro, the macro is expanded and this function is called recursively for each rule in the expansion. # -sub process_rule1 ( $$$$$$$$$$$ ) { - my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $wildcard ) = @_; +sub process_rule1 ( $$$$$$$$$$$$ ) { + my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, $wildcard ) = @_; my ( $action, $loglevel) = split_action $target; my ( $basictarget, $param ) = get_target_param $action; my $rule = ''; @@ -967,6 +968,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { $ratelimit, $user, $mark, + $connlimit, $wildcard ); $macro_nest_level--; @@ -1106,7 +1108,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { # # Generate Fixed part of the rule # - $rule = join( '', do_proto($proto, $ports, $sports), do_ratelimit( $ratelimit, $basictarget ) , do_user( $user ) , do_test( $mark , 0xFF ) ); + $rule = join( '', do_proto($proto, $ports, $sports), do_ratelimit( $ratelimit, $basictarget ) , do_user( $user ) , do_test( $mark , 0xFF ) , do_connlimit( $connlimit ) ); unless ( $section eq 'NEW' ) { fatal_error "Entries in the $section SECTION of the rules file not permitted with FASTACCEPT=Yes" if $config{FASTACCEPT}; @@ -1171,7 +1173,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { my $interfacesref = $sourceref->{interfaces}; my @interfaces = keys %$interfacesref; $origdest = @interfaces ? "detect:@interfaces" : ALLIPv4; - } else { + } else { $origdest = ALLIPv4; } } @@ -1265,6 +1267,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { $action , '' ); } + # # Add filter table rule, unless this is a NATONLY rule type # @@ -1281,7 +1284,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { $origdest = ''; } - expand_rule( ensure_chain ('filter', $chain ) , + expand_rule( ensure_chain( 'filter', $chain ) , $restriction , $rule , $source , @@ -1299,8 +1302,8 @@ sub process_rule1 ( $$$$$$$$$$$ ) { # # Deals with the ugliness of wildcard zones ('all' in SOURCE and/or DEST column). # -sub process_rule ( $$$$$$$$$$ ) { - my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark ) = @_; +sub process_rule ( $$$$$$$$$$$ ) { + my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit ) = @_; my $intrazone = 0; my $includesrcfw = 1; my $includedstfw = 1; @@ -1362,7 +1365,7 @@ sub process_rule ( $$$$$$$$$$ ) { for my $zone1 ( all_zones ) { if ( $includedstfw || ( zone_type( $zone1 ) ne 'firewall' ) ) { if ( $intrazone || ( $zone ne $zone1 ) ) { - process_rule1 $target, $zone, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 1; + process_rule1 $target, $zone, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, 1; } } } @@ -1370,7 +1373,7 @@ sub process_rule ( $$$$$$$$$$ ) { my $destzone = (split( /:/, $dest, 2 ) )[0]; $destzone = firewall_zone unless defined_zone( $destzone ); # We do this to allow 'REDIRECT all ...'; process_rule1 will catch the case where the dest zone is invalid if ( $intrazone || ( $zone ne $destzone ) ) { - process_rule1 $target, $zone, $dest , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 1; + process_rule1 $target, $zone, $dest , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, 1; } } } @@ -1379,11 +1382,11 @@ sub process_rule ( $$$$$$$$$$ ) { for my $zone ( all_zones ) { my $sourcezone = ( split( /:/, $source, 2 ) )[0]; if ( ( $includedstfw || ( zone_type( $zone ) ne 'firewall') ) && ( ( $sourcezone ne $zone ) || $intrazone) ) { - process_rule1 $target, $source, $zone , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 1; + process_rule1 $target, $source, $zone , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, 1; } } } else { - process_rule1 $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 0; + process_rule1 $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, 0; } progress_message " Rule \"$thisline\" $done"; @@ -1400,7 +1403,7 @@ sub process_rules() { while ( read_a_line ) { - my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark ) = split_line1 1, 10, 'rules file', \%rules_commands; + my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit ) = split_line1 1, 11, 'rules file', \%rules_commands; if ( $target eq 'COMMENT' ) { process_comment; @@ -1426,7 +1429,7 @@ sub process_rules() { if ( "\L$source" =~ /^none(:.*)?$/ || "\L$dest" =~ /^none(:.*)?$/ ) { progress_message "Rule \"$currentline\" ignored." } else { - process_rule $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark; + process_rule $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit; } } } diff --git a/docs/support.xml b/docs/support.xml index 2018b483e..920821cf7 100644 --- a/docs/support.xml +++ b/docs/support.xml @@ -357,13 +357,14 @@ State:Stopped (Thu Mar 30 14:08:11 PDT 2006) - Please give details about what doesn't work. Reports that say - I followed the directions and it didn't work may elicit - sympathy but probably little in the way of help. Again -- if ping from - A to B fails, say so (and see below for information about reporting - ping problems). If Computer B doesn't show up in - Network Neighborhood then say so. If access by IP - address works but by DNS names it doesn't then say so. + Please give details about what doesn't + work. Reports that say I followed the directions and + it didn't work may elicit sympathy but probably little in the + way of help. Again -- if ping from A to B fails, say so (and see below + for information about reporting ping problems). If + Computer B doesn't show up in Network Neighborhood then + say so. If access by IP address works but by DNS names it doesn't then + say so. @@ -373,10 +374,10 @@ State:Stopped (Thu Mar 30 14:08:11 PDT 2006) - Please do NOT include the output of iptables - -L — the output of shorewall - show or shorewall dump is much more - useful to us. + Please do NOT include the output + of iptables -L — the output of shorewall show or shorewall + dump is much more useful to us. @@ -387,10 +388,10 @@ State:Stopped (Thu Mar 30 14:08:11 PDT 2006) - Please do not include Shorewall configuration files unless you - have been specifically asked to do so. The output of - shorewall dump collected as described above is much - more useful. + Please do not include Shorewall + configuration files unless you have been specifically asked + to do so. The output of shorewall dump collected as + described above is much more useful. diff --git a/manpages/shorewall-policy.xml b/manpages/shorewall-policy.xml index 669cf13df..1e5584ab8 100644 --- a/manpages/shorewall-policy.xml +++ b/manpages/shorewall-policy.xml @@ -1,4 +1,6 @@ + shorewall-policy @@ -235,6 +237,29 @@ not limited. + + + CONNLIMIT - [!]limit[:mask] + + + Added in Shorewall-perl 4.2.1. May be used to limit the number + of simultaneous connections from each individual host to + limit connections. While the limit is + only checked on connections to which this policy could apply, the + number of current connections is calculated over all current + connections from the SOURCE host. By default, the limit is applied + to each host individually but can be made to apply to networks of + hosts by specifying a mask. The + mask specifies the width of a VLSM mask + to be applied to the source address; the number of current + connections is then taken over all hosts in the subnet + source-address/mask. + When is specified, the rule matches when the + number of connection exceeds the + limit. + + @@ -287,4 +312,4 @@ shorewall-tcrules(5), shorewall-tos(5), shorewall-tunnels(5), shorewall-zones(5) - \ No newline at end of file + diff --git a/manpages/shorewall-rules.xml b/manpages/shorewall-rules.xml index 14fcae265..b4df60769 100644 --- a/manpages/shorewall-rules.xml +++ b/manpages/shorewall-rules.xml @@ -1,4 +1,6 @@ + shorewall-rules @@ -1071,6 +1073,29 @@ + + + CONNLIMIT - [!]limit[:mask] + + + Added in Shorewall-perl 4.2.1. May be used to limit the number + of simultaneous connections from each individual host to + limit connections. While the limit is + only checked on rules specifying CONNLIMIT, the number of current + connections is calculated over all current connections from the + SOURCE host. By default, the limit is applied to each host but can + be made to apply to networks of hosts by specifying a + mask. The mask + specifies the width of a VLSM mask to be applied to the source + address; the number of current connections is then taken over all + hosts in the subnet + source-address/mask. + When is specified, the rule matches when the + number of connection exceeds the + limit. + + @@ -1267,4 +1292,4 @@ shorewall-tcclasses(5), shorewall-tcdevices(5), shorewall-tcrules(5), shorewall-tos(5), shorewall-tunnels(5), shorewall-zones(5) - \ No newline at end of file +