mirror of
https://gitlab.com/shorewall/code.git
synced 2025-01-20 12:39:06 +01:00
Allow two limits in the RATE LIMIT columns
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
54461a9a90
commit
f5bdc9e7f4
@ -4876,62 +4876,79 @@ my %norate = ( DROP => 1, REJECT => 1 );
|
|||||||
# Create a "-m limit" match for the passed LIMIT/BURST
|
# Create a "-m limit" match for the passed LIMIT/BURST
|
||||||
#
|
#
|
||||||
sub do_ratelimit( $$ ) {
|
sub do_ratelimit( $$ ) {
|
||||||
my ( $rate, $action ) = @_;
|
my ( $rates, $action ) = @_;
|
||||||
|
|
||||||
return '' unless $rate and $rate ne '-';
|
return '' unless $rates and $rates ne '-';
|
||||||
|
|
||||||
fatal_error "Rate Limiting not available with $action" if $norate{$action};
|
fatal_error "Rate Limiting not available with $action" if $norate{$action};
|
||||||
#
|
|
||||||
# "-m hashlimit" match for the passed LIMIT/BURST
|
|
||||||
#
|
|
||||||
if ( $rate =~ /^[sd]:{1,2}/ ) {
|
|
||||||
require_capability 'HASHLIMIT_MATCH', 'Per-ip rate limiting' , 's';
|
|
||||||
|
|
||||||
my $limit = "-m hashlimit ";
|
my @rates = split_list $rates, 'rate';
|
||||||
my $match = have_capability( 'OLD_HL_MATCH' ) ? 'hashlimit' : 'hashlimit-upto';
|
|
||||||
my $units;
|
|
||||||
|
|
||||||
if ( $rate =~ /^[sd]:((\w*):)?((\d+)(\/(sec|min|hour|day))?):(\d+)$/ ) {
|
if ( @rates == 2 ) {
|
||||||
fatal_error "Invalid Rate ($3)" unless $4;
|
$rates[0] = 's:' . $rates[0];
|
||||||
fatal_error "Invalid Burst ($7)" unless $7;
|
$rates[1] = 'd:' . $rates[1];
|
||||||
$limit .= "--$match $3 --hashlimit-burst $7 --hashlimit-name ";
|
} elsif ( @rates > 2 ) {
|
||||||
$limit .= $2 ? $2 : 'shorewall' . $hashlimitset++;
|
fatal error "Only two rates may be specified";
|
||||||
$limit .= ' --hashlimit-mode ';
|
}
|
||||||
$units = $6;
|
|
||||||
} elsif ( $rate =~ /^[sd]:((\w*):)?((\d+)(\/(sec|min|hour|day))?)$/ ) {
|
|
||||||
fatal_error "Invalid Rate ($3)" unless $4;
|
|
||||||
$limit .= "--$match $3 --hashlimit-name ";
|
|
||||||
$limit .= $2 ? $2 : 'shorewall' . $hashlimitset++;
|
|
||||||
$limit .= ' --hashlimit-mode ';
|
|
||||||
$units = $6;
|
|
||||||
} else {
|
|
||||||
fatal_error "Invalid rate ($rate)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$limit .= $rate =~ /^s:/ ? 'srcip ' : 'dstip ';
|
my $limit = '';
|
||||||
|
|
||||||
if ( $units && $units ne 'sec' ) {
|
for my $rate ( @rates ) {
|
||||||
my $expire = 60000; # 1 minute in milliseconds
|
#
|
||||||
|
# "-m hashlimit" match for the passed LIMIT/BURST
|
||||||
|
#
|
||||||
|
if ( $rate =~ /^([sd]):{1,2}/ ) {
|
||||||
|
require_capability 'HASHLIMIT_MATCH', 'Per-ip rate limiting' , 's';
|
||||||
|
|
||||||
if ( $units ne 'min' ) {
|
my $match = have_capability( 'OLD_HL_MATCH' ) ? 'hashlimit' : 'hashlimit-upto';
|
||||||
$expire *= 60; #At least an hour
|
my $units;
|
||||||
$expire *= 24 if $units eq 'day';
|
|
||||||
|
$limit .= "-m hashlimit ";
|
||||||
|
|
||||||
|
if ( $rate =~ /^[sd]:((\w*):)?((\d+)(\/(sec|min|hour|day))?):(\d+)$/ ) {
|
||||||
|
fatal_error "Invalid Rate ($3)" unless $4;
|
||||||
|
fatal_error "Invalid Burst ($7)" unless $7;
|
||||||
|
$limit .= "--$match $3 --hashlimit-burst $7 --hashlimit-name ";
|
||||||
|
$limit .= $2 ? $2 : 'shorewall' . $hashlimitset++;
|
||||||
|
$limit .= ' --hashlimit-mode ';
|
||||||
|
$units = $6;
|
||||||
|
} elsif ( $rate =~ /^[sd]:((\w*):)?((\d+)(\/(sec|min|hour|day))?)$/ ) {
|
||||||
|
fatal_error "Invalid Rate ($3)" unless $4;
|
||||||
|
$limit .= "--$match $3 --hashlimit-name ";
|
||||||
|
$limit .= $2 ? $2 : 'shorewall' . $hashlimitset++;
|
||||||
|
$limit .= ' --hashlimit-mode ';
|
||||||
|
$units = $6;
|
||||||
|
} else {
|
||||||
|
fatal_error "Invalid rate ($rate)";
|
||||||
}
|
}
|
||||||
|
|
||||||
$limit .= "--hashlimit-htable-expire $expire ";
|
$limit .= $rate =~ /^s:/ ? 'srcip ' : 'dstip ';
|
||||||
}
|
|
||||||
|
|
||||||
$limit;
|
if ( $units && $units ne 'sec' ) {
|
||||||
} elsif ( $rate =~ /^((\d+)(\/(sec|min|hour|day))?):(\d+)$/ ) {
|
my $expire = 60000; # 1 minute in milliseconds
|
||||||
fatal_error "Invalid Rate ($1)" unless $2;
|
|
||||||
fatal_error "Invalid Burst ($5)" unless $5;
|
if ( $units ne 'min' ) {
|
||||||
"-m limit --limit $1 --limit-burst $5 ";
|
$expire *= 60; #At least an hour
|
||||||
} elsif ( $rate =~ /^(\d+)(\/(sec|min|hour|day))?$/ ) {
|
$expire *= 24 if $units eq 'day';
|
||||||
fatal_error "Invalid Rate (${1}${2})" unless $1;
|
}
|
||||||
"-m limit --limit $rate ";
|
|
||||||
} else {
|
$limit .= "--hashlimit-htable-expire $expire ";
|
||||||
fatal_error "Invalid rate ($rate)";
|
}
|
||||||
|
} else {
|
||||||
|
if ( $rate =~ /^((\d+)(\/(sec|min|hour|day))?):(\d+)$/ ) {
|
||||||
|
fatal_error "Invalid Rate ($1)" unless $2;
|
||||||
|
fatal_error "Invalid Burst ($5)" unless $5;
|
||||||
|
$limit = "-m limit --limit $1 --limit-burst $5 ";
|
||||||
|
} elsif ( $rate =~ /^(\d+)(\/(sec|min|hour|day))?$/ ) {
|
||||||
|
fatal_error "Invalid Rate (${1}${2})" unless $1;
|
||||||
|
$limit = "-m limit --limit $rate ";
|
||||||
|
} else {
|
||||||
|
fatal_error "Invalid rate ($rate)";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1226,22 +1226,41 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><emphasis role="bold">RATE LIMIT</emphasis> (rate) - [<emphasis
|
<term><emphasis role="bold">RATE LIMIT</emphasis> (rate) -
|
||||||
role="bold">-</emphasis>|[{<emphasis>s</emphasis>|<emphasis
|
<replaceable>limit</replaceable></term>
|
||||||
role="bold">d</emphasis>}:[[<replaceable>name</replaceable>]:]]]<emphasis>rate</emphasis><emphasis
|
|
||||||
role="bold">/</emphasis>{<emphasis
|
|
||||||
role="bold">sec</emphasis>|<emphasis
|
|
||||||
role="bold">min</emphasis>|<emphasis
|
|
||||||
role="bold">hour</emphasis>|<emphasis
|
|
||||||
role="bold">day</emphasis>}[:<emphasis>burst</emphasis>]</term>
|
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
<para>where <replaceable>limit</replaceable> is one of:</para>
|
||||||
|
|
||||||
|
<simplelist>
|
||||||
|
<member>[<emphasis
|
||||||
|
role="bold">-</emphasis>|[{<emphasis>s</emphasis>|<emphasis
|
||||||
|
role="bold">d</emphasis>}:[[<replaceable>name</replaceable>]:]]]<emphasis>rate</emphasis><emphasis
|
||||||
|
role="bold">/</emphasis>{<emphasis
|
||||||
|
role="bold">sec</emphasis>|<emphasis
|
||||||
|
role="bold">min</emphasis>|<emphasis
|
||||||
|
role="bold">hour</emphasis>|<emphasis
|
||||||
|
role="bold">day</emphasis>}[:<emphasis>burst</emphasis>]</member>
|
||||||
|
|
||||||
|
<member>[<replaceable>name</replaceable>1]:<emphasis>rate1</emphasis><emphasis
|
||||||
|
role="bold">/</emphasis>{<emphasis
|
||||||
|
role="bold">sec</emphasis>|<emphasis
|
||||||
|
role="bold">min</emphasis>|<emphasis
|
||||||
|
role="bold">hour</emphasis>|<emphasis
|
||||||
|
role="bold">day</emphasis>}[:<emphasis>burst1</emphasis>],[<replaceable>name</replaceable>2]:<emphasis>rate2</emphasis><emphasis
|
||||||
|
role="bold">/</emphasis>{<emphasis
|
||||||
|
role="bold">sec</emphasis>|<emphasis
|
||||||
|
role="bold">min</emphasis>|<emphasis
|
||||||
|
role="bold">hour</emphasis>|<emphasis
|
||||||
|
role="bold">day</emphasis>}[:<emphasis>burst2</emphasis>]</member>
|
||||||
|
</simplelist>
|
||||||
|
|
||||||
<para>You may optionally rate-limit the rule by placing a value in
|
<para>You may optionally rate-limit the rule by placing a value in
|
||||||
this column:</para>
|
this column:</para>
|
||||||
|
|
||||||
<para><emphasis>rate</emphasis> is the number of connections per
|
<para><emphasis>rate*</emphasis> is the number of connections per
|
||||||
interval (<emphasis role="bold">sec</emphasis> or <emphasis
|
interval (<emphasis role="bold">sec</emphasis> or <emphasis
|
||||||
role="bold">min</emphasis>) and <emphasis>burst</emphasis> is the
|
role="bold">min</emphasis>) and <emphasis>burst</emphasis>* is the
|
||||||
largest burst permitted. If no <emphasis>burst</emphasis> is given,
|
largest burst permitted. If no <emphasis>burst</emphasis> is given,
|
||||||
a value of 5 is assumed. There may be no no white-space embedded in
|
a value of 5 is assumed. There may be no no white-space embedded in
|
||||||
the specification.</para>
|
the specification.</para>
|
||||||
@ -1250,15 +1269,28 @@
|
|||||||
|
|
||||||
<para>When <option>s:</option> or <option>d:</option> is specified,
|
<para>When <option>s:</option> or <option>d:</option> is specified,
|
||||||
the rate applies per source IP address or per destination IP address
|
the rate applies per source IP address or per destination IP address
|
||||||
respectively. The <replaceable>name</replaceable> may be chosen by
|
respectively. The <replaceable>name</replaceable>s may be chosen by
|
||||||
the user and specifies a hash table to be used to count matching
|
the user and specifiy a hash table to be used to count matching
|
||||||
connections. If not given, the name <emphasis
|
connections. If not given, the name <emphasis
|
||||||
role="bold">shorewallN</emphasis> (where N is a unique integer) is
|
role="bold">shorewallN</emphasis> (where N is a unique integer) is
|
||||||
assumed. Where more than one rule specifies the same name, the
|
assumed. Where more than one rule or POLICY specifies the same name,
|
||||||
connections counts for the rules are aggregated and the individual
|
the connections counts for the rules are aggregated and the
|
||||||
rates apply to the aggregated count.</para>
|
individual rates apply to the aggregated count.</para>
|
||||||
|
|
||||||
<para>Example: <emphasis role="bold">s:ssh:3/min:5</emphasis></para>
|
<para>Beginning with Shorewall 4.6.5, two<replaceable>
|
||||||
|
limit</replaceable>s may be specified, separated by a comma. In this
|
||||||
|
case, the first limit (<replaceable>name1</replaceable>,
|
||||||
|
<replaceable>rate1</replaceable>, burst1) specifies the per-source
|
||||||
|
IP limit and the second limit specifies the per-destination IP
|
||||||
|
limit.</para>
|
||||||
|
|
||||||
|
<para>Example: <emphasis
|
||||||
|
role="bold">client:10/sec:20,:60/sec:100</emphasis></para>
|
||||||
|
|
||||||
|
<para>In this example, the 'client' hash table will be used to
|
||||||
|
enforce the per-source limit and the compiler will pick a unique
|
||||||
|
name for the hash table that tracks the per-destination
|
||||||
|
limit.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
@ -1127,22 +1127,41 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><emphasis role="bold">RATE LIMIT</emphasis> (rate) - [<emphasis
|
<term><emphasis role="bold">RATE LIMIT</emphasis> (rate) -
|
||||||
role="bold">-</emphasis>|[{<emphasis>s</emphasis>|<emphasis
|
<replaceable>limit</replaceable></term>
|
||||||
role="bold">d</emphasis>}:[[<replaceable>name</replaceable>]:]]]<emphasis>rate</emphasis><emphasis
|
|
||||||
role="bold">/</emphasis>{<emphasis
|
|
||||||
role="bold">sec</emphasis>|<emphasis
|
|
||||||
role="bold">min</emphasis>|<emphasis
|
|
||||||
role="bold">hour</emphasis>|<emphasis
|
|
||||||
role="bold">day</emphasis>}[:<emphasis>burst</emphasis>]</term>
|
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
<para>where <replaceable>limit</replaceable> is one of:</para>
|
||||||
|
|
||||||
|
<simplelist>
|
||||||
|
<member>[<emphasis
|
||||||
|
role="bold">-</emphasis>|[{<emphasis>s</emphasis>|<emphasis
|
||||||
|
role="bold">d</emphasis>}:[[<replaceable>name</replaceable>]:]]]<emphasis>rate</emphasis><emphasis
|
||||||
|
role="bold">/</emphasis>{<emphasis
|
||||||
|
role="bold">sec</emphasis>|<emphasis
|
||||||
|
role="bold">min</emphasis>|<emphasis
|
||||||
|
role="bold">hour</emphasis>|<emphasis
|
||||||
|
role="bold">day</emphasis>}[:<emphasis>burst</emphasis>]</member>
|
||||||
|
|
||||||
|
<member>[<replaceable>name</replaceable>1]:<emphasis>rate1</emphasis><emphasis
|
||||||
|
role="bold">/</emphasis>{<emphasis
|
||||||
|
role="bold">sec</emphasis>|<emphasis
|
||||||
|
role="bold">min</emphasis>|<emphasis
|
||||||
|
role="bold">hour</emphasis>|<emphasis
|
||||||
|
role="bold">day</emphasis>}[:<emphasis>burst1</emphasis>],[<replaceable>name</replaceable>2]:<emphasis>rate2</emphasis><emphasis
|
||||||
|
role="bold">/</emphasis>{<emphasis
|
||||||
|
role="bold">sec</emphasis>|<emphasis
|
||||||
|
role="bold">min</emphasis>|<emphasis
|
||||||
|
role="bold">hour</emphasis>|<emphasis
|
||||||
|
role="bold">day</emphasis>}[:<emphasis>burst2</emphasis>]</member>
|
||||||
|
</simplelist>
|
||||||
|
|
||||||
<para>You may optionally rate-limit the rule by placing a value in
|
<para>You may optionally rate-limit the rule by placing a value in
|
||||||
this column:</para>
|
this column:</para>
|
||||||
|
|
||||||
<para><emphasis>rate</emphasis> is the number of connections per
|
<para><emphasis>rate*</emphasis> is the number of connections per
|
||||||
interval (<emphasis role="bold">sec</emphasis> or <emphasis
|
interval (<emphasis role="bold">sec</emphasis> or <emphasis
|
||||||
role="bold">min</emphasis>) and <emphasis>burst</emphasis> is the
|
role="bold">min</emphasis>) and <emphasis>burst</emphasis>* is the
|
||||||
largest burst permitted. If no <emphasis>burst</emphasis> is given,
|
largest burst permitted. If no <emphasis>burst</emphasis> is given,
|
||||||
a value of 5 is assumed. There may be no no white-space embedded in
|
a value of 5 is assumed. There may be no no white-space embedded in
|
||||||
the specification.</para>
|
the specification.</para>
|
||||||
@ -1151,13 +1170,28 @@
|
|||||||
|
|
||||||
<para>When <option>s:</option> or <option>d:</option> is specified,
|
<para>When <option>s:</option> or <option>d:</option> is specified,
|
||||||
the rate applies per source IP address or per destination IP address
|
the rate applies per source IP address or per destination IP address
|
||||||
respectively. The <replaceable>name</replaceable> may be chosen by
|
respectively. The <replaceable>name</replaceable>s may be chosen by
|
||||||
the user and specifies a hash table to be used to count matching
|
the user and specifiy a hash table to be used to count matching
|
||||||
connections. If not given, the name <emphasis
|
connections. If not given, the name <emphasis
|
||||||
role="bold">shorewallN</emphasis> (where N is a unique integer) is
|
role="bold">shorewallN</emphasis> (where N is a unique integer) is
|
||||||
assumed. Where more than one POLICY specifies the same name, the
|
assumed. Where more than one rule or POLICY specifies the same name,
|
||||||
connections counts for the rules are aggregated and the individual
|
the connections counts for the rules are aggregated and the
|
||||||
rates apply to the aggregated count.</para>
|
individual rates apply to the aggregated count.</para>
|
||||||
|
|
||||||
|
<para>Beginning with Shorewall 4.6.5, two<replaceable>
|
||||||
|
limit</replaceable>s may be specified, separated by a comma. In this
|
||||||
|
case, the first limit (<replaceable>name1</replaceable>,
|
||||||
|
<replaceable>rate1</replaceable>, burst1) specifies the per-source
|
||||||
|
IP limit and the second limit specifies the per-destination IP
|
||||||
|
limit.</para>
|
||||||
|
|
||||||
|
<para>Example: <emphasis
|
||||||
|
role="bold">client:10/sec:20,:60/sec:100</emphasis></para>
|
||||||
|
|
||||||
|
<para>In this example, the 'client' hash table will be used to
|
||||||
|
enforce the per-source limit and the compiler will pick a unique
|
||||||
|
name for the hash table that tracks the per-destination
|
||||||
|
limit.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user