Multiple limit_req_zone with geo and map in nginx
I need help in defining rate limiting in nginx usging map and geo modules.
I've defined 4 cases with. Each of these cases should have a different rate limit set :
geo $limited_ip {
default 0;
1.1.1.1/24 1;
2.2.2.2/24 2;
3.3.3.3/24 3;
}
I use map module to transfer the ip value of the client to a variable :
map $limited_ip $limited_ip_key {
0 '';
1 $binary_remote_addr;
2 $binary_remote_addr;
3 $binary_remote_addr;
}
Now, I set 4 limit zones. The last zone is for testing :
limit_req_zone $limited_ip_key zone=zone0:10m rate=100r/m;
limit_req_zone $limited_ip_key zone=zone1:10m rate=200r/m;
limit_req_zone $limited_ip_key zone=zone2:10m rate=500r/m;
limit_req_zone $limited_ip_key zone=zone3:10m rate=1r/m;
Finally, I apply the limits in the server{} block :
limit_req zone=zone0 burst=10 nodelay;
limit_req zone=zone1 burst=10 nodelay;
limit_req zone=zone2 burst=10 nodelay;
limit_req zone=zone3 burst=1 nodelay;
The configuration test if ok, I reload nginx, ok too. Using apache bench tool (ab) to hammer the nginx server, it looks like zone3 always match for any source IP. Why do IP from other masks defines by geo module matche zone3 ?
Log :
*2757 limiting requests, excess: 1.697 by zone "zone3", client: 3.3.3.3, server: my.domain.com, request: "HEAD / HTTP/1.0", host: "my.domain.com"
*29449 limiting requests, excess: 1.958 by zone "zone3", client: 2.2.2.2, server: my.domain.com, request: "HEAD / HTTP/2.0", host: "my.domain.com"
All results I found are about 2 zones defined, I can't find examples with more zones. Maybe it's not possible to do it this way ?
Thank you
nginx rate-limiting
add a comment |
I need help in defining rate limiting in nginx usging map and geo modules.
I've defined 4 cases with. Each of these cases should have a different rate limit set :
geo $limited_ip {
default 0;
1.1.1.1/24 1;
2.2.2.2/24 2;
3.3.3.3/24 3;
}
I use map module to transfer the ip value of the client to a variable :
map $limited_ip $limited_ip_key {
0 '';
1 $binary_remote_addr;
2 $binary_remote_addr;
3 $binary_remote_addr;
}
Now, I set 4 limit zones. The last zone is for testing :
limit_req_zone $limited_ip_key zone=zone0:10m rate=100r/m;
limit_req_zone $limited_ip_key zone=zone1:10m rate=200r/m;
limit_req_zone $limited_ip_key zone=zone2:10m rate=500r/m;
limit_req_zone $limited_ip_key zone=zone3:10m rate=1r/m;
Finally, I apply the limits in the server{} block :
limit_req zone=zone0 burst=10 nodelay;
limit_req zone=zone1 burst=10 nodelay;
limit_req zone=zone2 burst=10 nodelay;
limit_req zone=zone3 burst=1 nodelay;
The configuration test if ok, I reload nginx, ok too. Using apache bench tool (ab) to hammer the nginx server, it looks like zone3 always match for any source IP. Why do IP from other masks defines by geo module matche zone3 ?
Log :
*2757 limiting requests, excess: 1.697 by zone "zone3", client: 3.3.3.3, server: my.domain.com, request: "HEAD / HTTP/1.0", host: "my.domain.com"
*29449 limiting requests, excess: 1.958 by zone "zone3", client: 2.2.2.2, server: my.domain.com, request: "HEAD / HTTP/2.0", host: "my.domain.com"
All results I found are about 2 zones defined, I can't find examples with more zones. Maybe it's not possible to do it this way ?
Thank you
nginx rate-limiting
add a comment |
I need help in defining rate limiting in nginx usging map and geo modules.
I've defined 4 cases with. Each of these cases should have a different rate limit set :
geo $limited_ip {
default 0;
1.1.1.1/24 1;
2.2.2.2/24 2;
3.3.3.3/24 3;
}
I use map module to transfer the ip value of the client to a variable :
map $limited_ip $limited_ip_key {
0 '';
1 $binary_remote_addr;
2 $binary_remote_addr;
3 $binary_remote_addr;
}
Now, I set 4 limit zones. The last zone is for testing :
limit_req_zone $limited_ip_key zone=zone0:10m rate=100r/m;
limit_req_zone $limited_ip_key zone=zone1:10m rate=200r/m;
limit_req_zone $limited_ip_key zone=zone2:10m rate=500r/m;
limit_req_zone $limited_ip_key zone=zone3:10m rate=1r/m;
Finally, I apply the limits in the server{} block :
limit_req zone=zone0 burst=10 nodelay;
limit_req zone=zone1 burst=10 nodelay;
limit_req zone=zone2 burst=10 nodelay;
limit_req zone=zone3 burst=1 nodelay;
The configuration test if ok, I reload nginx, ok too. Using apache bench tool (ab) to hammer the nginx server, it looks like zone3 always match for any source IP. Why do IP from other masks defines by geo module matche zone3 ?
Log :
*2757 limiting requests, excess: 1.697 by zone "zone3", client: 3.3.3.3, server: my.domain.com, request: "HEAD / HTTP/1.0", host: "my.domain.com"
*29449 limiting requests, excess: 1.958 by zone "zone3", client: 2.2.2.2, server: my.domain.com, request: "HEAD / HTTP/2.0", host: "my.domain.com"
All results I found are about 2 zones defined, I can't find examples with more zones. Maybe it's not possible to do it this way ?
Thank you
nginx rate-limiting
I need help in defining rate limiting in nginx usging map and geo modules.
I've defined 4 cases with. Each of these cases should have a different rate limit set :
geo $limited_ip {
default 0;
1.1.1.1/24 1;
2.2.2.2/24 2;
3.3.3.3/24 3;
}
I use map module to transfer the ip value of the client to a variable :
map $limited_ip $limited_ip_key {
0 '';
1 $binary_remote_addr;
2 $binary_remote_addr;
3 $binary_remote_addr;
}
Now, I set 4 limit zones. The last zone is for testing :
limit_req_zone $limited_ip_key zone=zone0:10m rate=100r/m;
limit_req_zone $limited_ip_key zone=zone1:10m rate=200r/m;
limit_req_zone $limited_ip_key zone=zone2:10m rate=500r/m;
limit_req_zone $limited_ip_key zone=zone3:10m rate=1r/m;
Finally, I apply the limits in the server{} block :
limit_req zone=zone0 burst=10 nodelay;
limit_req zone=zone1 burst=10 nodelay;
limit_req zone=zone2 burst=10 nodelay;
limit_req zone=zone3 burst=1 nodelay;
The configuration test if ok, I reload nginx, ok too. Using apache bench tool (ab) to hammer the nginx server, it looks like zone3 always match for any source IP. Why do IP from other masks defines by geo module matche zone3 ?
Log :
*2757 limiting requests, excess: 1.697 by zone "zone3", client: 3.3.3.3, server: my.domain.com, request: "HEAD / HTTP/1.0", host: "my.domain.com"
*29449 limiting requests, excess: 1.958 by zone "zone3", client: 2.2.2.2, server: my.domain.com, request: "HEAD / HTTP/2.0", host: "my.domain.com"
All results I found are about 2 zones defined, I can't find examples with more zones. Maybe it's not possible to do it this way ?
Thank you
nginx rate-limiting
nginx rate-limiting
asked Nov 28 '18 at 14:00
Gilles HayjonesGilles Hayjones
11
11
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
I was searching for the same configuration today and could not find an example with more than 2 zones too. So here is what in theory should work (I have not yet tried it out) :
geo $limited_ip {
default 0;
1.1.1.1/24 1;
2.2.2.2/24 2;
3.3.3.3/24 3;
}
map $limited_ip $limited_ip_key0 {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $limited_ip $limited_ip_key1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $limited_ip $limited_ip_key2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $limited_ip $limited_ip_key3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
limit_req_zone $limited_ip_key0 zone=zone0:10m rate=100r/m;
limit_req_zone $limited_ip_key1 zone=zone1:10m rate=200r/m;
limit_req_zone $limited_ip_key2 zone=zone2:10m rate=500r/m;
limit_req_zone $limited_ip_key3 zone=zone3:10m rate=1r/m;
limit_req zone=zone0 burst=10 nodelay;
limit_req zone=zone1 burst=10 nodelay;
limit_req zone=zone2 burst=10 nodelay;
limit_req zone=zone3 burst=1 nodelay;
Explanation:
a) if IP is none of the 3 defined then
$limited_ip_key0 = $binary_remote_addr
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone0 will be matched only, and the rate limit of 100r/m will be applied
b) if IP is 1.1.1.1/24
$limited_ip_key0 = ''
$limited_ip_key1 = $binary_remote_addr
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone1 will be matched only, and the rate limit of 200r/m will be applied
c) if IP is 2.2.2.2/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = $binary_remote_addr
$limited_ip_key3 = ''
thus the zone2 will be matched only, and the rate limit of 500r/m will be applied
d) if IP is 3.3.3.3/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = $binary_remote_addr
thus the zone3 will be matched only, and the rate limit of 1r/m will be applied
Here is a php script to automatically create the required zones so you can be able to administer more zones and ips easily
<?php
list($mapString, $zonesString, $zonesArray) = createZones(
"myendpoint",
array(
"default"=>array(
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone1"=>array(
"ips"=>array(
"11.11.11.11/32",
"1.1.1.1/24"
),
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone2"=>array(
"ips"=>array(
"22.22.22.22/32",
"2.2.2.2/24"
),
"zoneSize"=>"10m",
"rate"=>"20r/s",
"burst"=>"100",
"options"=>"nodelay"
),
"zone3"=>array(
"ips"=>array(
"33.33.33.33/32",
"3.3.3.3/24"
),
"zoneSize"=>"10m",
"rate"=>"30r/s",
"burst"=>"100",
"options"=>""
),
)
);
echo "# Define the ips and mapsn$mapStringn#Define the zonesn$zonesStringnn";
echo "t# limit directives to be placed inside the location sectionn";
foreach ($zonesArray as $zoneName=>$zoneString) {
echo "t$zoneStringn";
}
function createZones($endpointPrefix,$zones) {
$mapString0='geo $'.$endpointPrefix.' {'."nttdefaultt0;";
$mapString1='';
$zonesString='';
$zonesArray=array();
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
if ($zoneName!='default') {
$zoneNum++;
foreach($params['ips'] as $ip) {
$mapString0.="ntt$ipt$zoneNum;";
}
}
}
$mapString0.="n}n";
$zoneNumTotal=$zoneNum;
// now that we now the total zones we can create the maps
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$mapString1.='map $'.$endpointPrefix.' $'.$endpointPrefix.'_key_'.$zoneName.' {';
for($zoneNumTemp=0;$zoneNumTemp<=$zoneNumTotal;$zoneNumTemp++) {
if ($zoneNum==$zoneNumTemp) {
$mapString1.="ntt$zoneNumTempt$binary_remote_addr;";
} else {
$mapString1.="ntt$zoneNumTempt'';";
}
}
$mapString1.="n}nn";
$zoneNum++;
}
// now create the actual zones string
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesString.="n";
if ( isset( $params['ips']) ) {
foreach ($params['ips'] as $ip) {
$zonesString .= "# $ipn";
}
}
$zonesString.='limit_req_zone $'.$endpointPrefix.'_key_'.$zoneName.' zone='.$endpointPrefix.'_'.$zoneName.':'.$params['zoneSize'].' rate='.$params['rate'].';';
$zonesString.="n";
}
// now create the limits that should be applied inside the location sections
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesArray[$zoneName]='limit_req zone='.$endpointPrefix.'_'.$zoneName;
if ($params['burst']) {
$zonesArray[$zoneName].=' burst='.$params['burst'];
}
if ($params['options']) {
$zonesArray[$zoneName].=' '.$params['options'];
}
}
return array($mapString0."n".$mapString1, $zonesString,$zonesArray);
}
When executed the above script produces:
# Define the ips and maps
geo $myendpoint {
default 0;
11.11.11.11/32 1;
1.1.1.1/24 1;
22.22.22.22/32 2;
2.2.2.2/24 2;
33.33.33.33/32 3;
3.3.3.3/24 3;
}
map $myendpoint $myendpoint_key_default {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $myendpoint $myendpoint_key_zone3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
#Define the zones
limit_req_zone $myendpoint_key_default zone=myendpoint_default:10m rate=10r/s;
# 11.11.11.11/32
# 1.1.1.1/24
limit_req_zone $myendpoint_key_zone1 zone=myendpoint_zone1:10m rate=10r/s;
# 22.22.22.22/32
# 2.2.2.2/24
limit_req_zone $myendpoint_key_zone2 zone=myendpoint_zone2:10m rate=20r/s;
# 33.33.33.33/32
# 3.3.3.3/24
limit_req_zone $myendpoint_key_zone3 zone=myendpoint_zone3:10m rate=30r/s;
# limit directives to be placed inside the location section
limit_req zone=myendpoint_default burst=100
limit_req zone=myendpoint_zone1 burst=100
limit_req zone=myendpoint_zone2 burst=100 nodelay
limit_req zone=myendpoint_zone3 burst=100
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53521185%2fmultiple-limit-req-zone-with-geo-and-map-in-nginx%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I was searching for the same configuration today and could not find an example with more than 2 zones too. So here is what in theory should work (I have not yet tried it out) :
geo $limited_ip {
default 0;
1.1.1.1/24 1;
2.2.2.2/24 2;
3.3.3.3/24 3;
}
map $limited_ip $limited_ip_key0 {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $limited_ip $limited_ip_key1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $limited_ip $limited_ip_key2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $limited_ip $limited_ip_key3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
limit_req_zone $limited_ip_key0 zone=zone0:10m rate=100r/m;
limit_req_zone $limited_ip_key1 zone=zone1:10m rate=200r/m;
limit_req_zone $limited_ip_key2 zone=zone2:10m rate=500r/m;
limit_req_zone $limited_ip_key3 zone=zone3:10m rate=1r/m;
limit_req zone=zone0 burst=10 nodelay;
limit_req zone=zone1 burst=10 nodelay;
limit_req zone=zone2 burst=10 nodelay;
limit_req zone=zone3 burst=1 nodelay;
Explanation:
a) if IP is none of the 3 defined then
$limited_ip_key0 = $binary_remote_addr
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone0 will be matched only, and the rate limit of 100r/m will be applied
b) if IP is 1.1.1.1/24
$limited_ip_key0 = ''
$limited_ip_key1 = $binary_remote_addr
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone1 will be matched only, and the rate limit of 200r/m will be applied
c) if IP is 2.2.2.2/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = $binary_remote_addr
$limited_ip_key3 = ''
thus the zone2 will be matched only, and the rate limit of 500r/m will be applied
d) if IP is 3.3.3.3/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = $binary_remote_addr
thus the zone3 will be matched only, and the rate limit of 1r/m will be applied
Here is a php script to automatically create the required zones so you can be able to administer more zones and ips easily
<?php
list($mapString, $zonesString, $zonesArray) = createZones(
"myendpoint",
array(
"default"=>array(
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone1"=>array(
"ips"=>array(
"11.11.11.11/32",
"1.1.1.1/24"
),
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone2"=>array(
"ips"=>array(
"22.22.22.22/32",
"2.2.2.2/24"
),
"zoneSize"=>"10m",
"rate"=>"20r/s",
"burst"=>"100",
"options"=>"nodelay"
),
"zone3"=>array(
"ips"=>array(
"33.33.33.33/32",
"3.3.3.3/24"
),
"zoneSize"=>"10m",
"rate"=>"30r/s",
"burst"=>"100",
"options"=>""
),
)
);
echo "# Define the ips and mapsn$mapStringn#Define the zonesn$zonesStringnn";
echo "t# limit directives to be placed inside the location sectionn";
foreach ($zonesArray as $zoneName=>$zoneString) {
echo "t$zoneStringn";
}
function createZones($endpointPrefix,$zones) {
$mapString0='geo $'.$endpointPrefix.' {'."nttdefaultt0;";
$mapString1='';
$zonesString='';
$zonesArray=array();
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
if ($zoneName!='default') {
$zoneNum++;
foreach($params['ips'] as $ip) {
$mapString0.="ntt$ipt$zoneNum;";
}
}
}
$mapString0.="n}n";
$zoneNumTotal=$zoneNum;
// now that we now the total zones we can create the maps
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$mapString1.='map $'.$endpointPrefix.' $'.$endpointPrefix.'_key_'.$zoneName.' {';
for($zoneNumTemp=0;$zoneNumTemp<=$zoneNumTotal;$zoneNumTemp++) {
if ($zoneNum==$zoneNumTemp) {
$mapString1.="ntt$zoneNumTempt$binary_remote_addr;";
} else {
$mapString1.="ntt$zoneNumTempt'';";
}
}
$mapString1.="n}nn";
$zoneNum++;
}
// now create the actual zones string
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesString.="n";
if ( isset( $params['ips']) ) {
foreach ($params['ips'] as $ip) {
$zonesString .= "# $ipn";
}
}
$zonesString.='limit_req_zone $'.$endpointPrefix.'_key_'.$zoneName.' zone='.$endpointPrefix.'_'.$zoneName.':'.$params['zoneSize'].' rate='.$params['rate'].';';
$zonesString.="n";
}
// now create the limits that should be applied inside the location sections
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesArray[$zoneName]='limit_req zone='.$endpointPrefix.'_'.$zoneName;
if ($params['burst']) {
$zonesArray[$zoneName].=' burst='.$params['burst'];
}
if ($params['options']) {
$zonesArray[$zoneName].=' '.$params['options'];
}
}
return array($mapString0."n".$mapString1, $zonesString,$zonesArray);
}
When executed the above script produces:
# Define the ips and maps
geo $myendpoint {
default 0;
11.11.11.11/32 1;
1.1.1.1/24 1;
22.22.22.22/32 2;
2.2.2.2/24 2;
33.33.33.33/32 3;
3.3.3.3/24 3;
}
map $myendpoint $myendpoint_key_default {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $myendpoint $myendpoint_key_zone3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
#Define the zones
limit_req_zone $myendpoint_key_default zone=myendpoint_default:10m rate=10r/s;
# 11.11.11.11/32
# 1.1.1.1/24
limit_req_zone $myendpoint_key_zone1 zone=myendpoint_zone1:10m rate=10r/s;
# 22.22.22.22/32
# 2.2.2.2/24
limit_req_zone $myendpoint_key_zone2 zone=myendpoint_zone2:10m rate=20r/s;
# 33.33.33.33/32
# 3.3.3.3/24
limit_req_zone $myendpoint_key_zone3 zone=myendpoint_zone3:10m rate=30r/s;
# limit directives to be placed inside the location section
limit_req zone=myendpoint_default burst=100
limit_req zone=myendpoint_zone1 burst=100
limit_req zone=myendpoint_zone2 burst=100 nodelay
limit_req zone=myendpoint_zone3 burst=100
add a comment |
I was searching for the same configuration today and could not find an example with more than 2 zones too. So here is what in theory should work (I have not yet tried it out) :
geo $limited_ip {
default 0;
1.1.1.1/24 1;
2.2.2.2/24 2;
3.3.3.3/24 3;
}
map $limited_ip $limited_ip_key0 {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $limited_ip $limited_ip_key1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $limited_ip $limited_ip_key2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $limited_ip $limited_ip_key3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
limit_req_zone $limited_ip_key0 zone=zone0:10m rate=100r/m;
limit_req_zone $limited_ip_key1 zone=zone1:10m rate=200r/m;
limit_req_zone $limited_ip_key2 zone=zone2:10m rate=500r/m;
limit_req_zone $limited_ip_key3 zone=zone3:10m rate=1r/m;
limit_req zone=zone0 burst=10 nodelay;
limit_req zone=zone1 burst=10 nodelay;
limit_req zone=zone2 burst=10 nodelay;
limit_req zone=zone3 burst=1 nodelay;
Explanation:
a) if IP is none of the 3 defined then
$limited_ip_key0 = $binary_remote_addr
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone0 will be matched only, and the rate limit of 100r/m will be applied
b) if IP is 1.1.1.1/24
$limited_ip_key0 = ''
$limited_ip_key1 = $binary_remote_addr
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone1 will be matched only, and the rate limit of 200r/m will be applied
c) if IP is 2.2.2.2/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = $binary_remote_addr
$limited_ip_key3 = ''
thus the zone2 will be matched only, and the rate limit of 500r/m will be applied
d) if IP is 3.3.3.3/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = $binary_remote_addr
thus the zone3 will be matched only, and the rate limit of 1r/m will be applied
Here is a php script to automatically create the required zones so you can be able to administer more zones and ips easily
<?php
list($mapString, $zonesString, $zonesArray) = createZones(
"myendpoint",
array(
"default"=>array(
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone1"=>array(
"ips"=>array(
"11.11.11.11/32",
"1.1.1.1/24"
),
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone2"=>array(
"ips"=>array(
"22.22.22.22/32",
"2.2.2.2/24"
),
"zoneSize"=>"10m",
"rate"=>"20r/s",
"burst"=>"100",
"options"=>"nodelay"
),
"zone3"=>array(
"ips"=>array(
"33.33.33.33/32",
"3.3.3.3/24"
),
"zoneSize"=>"10m",
"rate"=>"30r/s",
"burst"=>"100",
"options"=>""
),
)
);
echo "# Define the ips and mapsn$mapStringn#Define the zonesn$zonesStringnn";
echo "t# limit directives to be placed inside the location sectionn";
foreach ($zonesArray as $zoneName=>$zoneString) {
echo "t$zoneStringn";
}
function createZones($endpointPrefix,$zones) {
$mapString0='geo $'.$endpointPrefix.' {'."nttdefaultt0;";
$mapString1='';
$zonesString='';
$zonesArray=array();
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
if ($zoneName!='default') {
$zoneNum++;
foreach($params['ips'] as $ip) {
$mapString0.="ntt$ipt$zoneNum;";
}
}
}
$mapString0.="n}n";
$zoneNumTotal=$zoneNum;
// now that we now the total zones we can create the maps
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$mapString1.='map $'.$endpointPrefix.' $'.$endpointPrefix.'_key_'.$zoneName.' {';
for($zoneNumTemp=0;$zoneNumTemp<=$zoneNumTotal;$zoneNumTemp++) {
if ($zoneNum==$zoneNumTemp) {
$mapString1.="ntt$zoneNumTempt$binary_remote_addr;";
} else {
$mapString1.="ntt$zoneNumTempt'';";
}
}
$mapString1.="n}nn";
$zoneNum++;
}
// now create the actual zones string
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesString.="n";
if ( isset( $params['ips']) ) {
foreach ($params['ips'] as $ip) {
$zonesString .= "# $ipn";
}
}
$zonesString.='limit_req_zone $'.$endpointPrefix.'_key_'.$zoneName.' zone='.$endpointPrefix.'_'.$zoneName.':'.$params['zoneSize'].' rate='.$params['rate'].';';
$zonesString.="n";
}
// now create the limits that should be applied inside the location sections
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesArray[$zoneName]='limit_req zone='.$endpointPrefix.'_'.$zoneName;
if ($params['burst']) {
$zonesArray[$zoneName].=' burst='.$params['burst'];
}
if ($params['options']) {
$zonesArray[$zoneName].=' '.$params['options'];
}
}
return array($mapString0."n".$mapString1, $zonesString,$zonesArray);
}
When executed the above script produces:
# Define the ips and maps
geo $myendpoint {
default 0;
11.11.11.11/32 1;
1.1.1.1/24 1;
22.22.22.22/32 2;
2.2.2.2/24 2;
33.33.33.33/32 3;
3.3.3.3/24 3;
}
map $myendpoint $myendpoint_key_default {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $myendpoint $myendpoint_key_zone3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
#Define the zones
limit_req_zone $myendpoint_key_default zone=myendpoint_default:10m rate=10r/s;
# 11.11.11.11/32
# 1.1.1.1/24
limit_req_zone $myendpoint_key_zone1 zone=myendpoint_zone1:10m rate=10r/s;
# 22.22.22.22/32
# 2.2.2.2/24
limit_req_zone $myendpoint_key_zone2 zone=myendpoint_zone2:10m rate=20r/s;
# 33.33.33.33/32
# 3.3.3.3/24
limit_req_zone $myendpoint_key_zone3 zone=myendpoint_zone3:10m rate=30r/s;
# limit directives to be placed inside the location section
limit_req zone=myendpoint_default burst=100
limit_req zone=myendpoint_zone1 burst=100
limit_req zone=myendpoint_zone2 burst=100 nodelay
limit_req zone=myendpoint_zone3 burst=100
add a comment |
I was searching for the same configuration today and could not find an example with more than 2 zones too. So here is what in theory should work (I have not yet tried it out) :
geo $limited_ip {
default 0;
1.1.1.1/24 1;
2.2.2.2/24 2;
3.3.3.3/24 3;
}
map $limited_ip $limited_ip_key0 {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $limited_ip $limited_ip_key1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $limited_ip $limited_ip_key2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $limited_ip $limited_ip_key3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
limit_req_zone $limited_ip_key0 zone=zone0:10m rate=100r/m;
limit_req_zone $limited_ip_key1 zone=zone1:10m rate=200r/m;
limit_req_zone $limited_ip_key2 zone=zone2:10m rate=500r/m;
limit_req_zone $limited_ip_key3 zone=zone3:10m rate=1r/m;
limit_req zone=zone0 burst=10 nodelay;
limit_req zone=zone1 burst=10 nodelay;
limit_req zone=zone2 burst=10 nodelay;
limit_req zone=zone3 burst=1 nodelay;
Explanation:
a) if IP is none of the 3 defined then
$limited_ip_key0 = $binary_remote_addr
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone0 will be matched only, and the rate limit of 100r/m will be applied
b) if IP is 1.1.1.1/24
$limited_ip_key0 = ''
$limited_ip_key1 = $binary_remote_addr
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone1 will be matched only, and the rate limit of 200r/m will be applied
c) if IP is 2.2.2.2/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = $binary_remote_addr
$limited_ip_key3 = ''
thus the zone2 will be matched only, and the rate limit of 500r/m will be applied
d) if IP is 3.3.3.3/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = $binary_remote_addr
thus the zone3 will be matched only, and the rate limit of 1r/m will be applied
Here is a php script to automatically create the required zones so you can be able to administer more zones and ips easily
<?php
list($mapString, $zonesString, $zonesArray) = createZones(
"myendpoint",
array(
"default"=>array(
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone1"=>array(
"ips"=>array(
"11.11.11.11/32",
"1.1.1.1/24"
),
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone2"=>array(
"ips"=>array(
"22.22.22.22/32",
"2.2.2.2/24"
),
"zoneSize"=>"10m",
"rate"=>"20r/s",
"burst"=>"100",
"options"=>"nodelay"
),
"zone3"=>array(
"ips"=>array(
"33.33.33.33/32",
"3.3.3.3/24"
),
"zoneSize"=>"10m",
"rate"=>"30r/s",
"burst"=>"100",
"options"=>""
),
)
);
echo "# Define the ips and mapsn$mapStringn#Define the zonesn$zonesStringnn";
echo "t# limit directives to be placed inside the location sectionn";
foreach ($zonesArray as $zoneName=>$zoneString) {
echo "t$zoneStringn";
}
function createZones($endpointPrefix,$zones) {
$mapString0='geo $'.$endpointPrefix.' {'."nttdefaultt0;";
$mapString1='';
$zonesString='';
$zonesArray=array();
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
if ($zoneName!='default') {
$zoneNum++;
foreach($params['ips'] as $ip) {
$mapString0.="ntt$ipt$zoneNum;";
}
}
}
$mapString0.="n}n";
$zoneNumTotal=$zoneNum;
// now that we now the total zones we can create the maps
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$mapString1.='map $'.$endpointPrefix.' $'.$endpointPrefix.'_key_'.$zoneName.' {';
for($zoneNumTemp=0;$zoneNumTemp<=$zoneNumTotal;$zoneNumTemp++) {
if ($zoneNum==$zoneNumTemp) {
$mapString1.="ntt$zoneNumTempt$binary_remote_addr;";
} else {
$mapString1.="ntt$zoneNumTempt'';";
}
}
$mapString1.="n}nn";
$zoneNum++;
}
// now create the actual zones string
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesString.="n";
if ( isset( $params['ips']) ) {
foreach ($params['ips'] as $ip) {
$zonesString .= "# $ipn";
}
}
$zonesString.='limit_req_zone $'.$endpointPrefix.'_key_'.$zoneName.' zone='.$endpointPrefix.'_'.$zoneName.':'.$params['zoneSize'].' rate='.$params['rate'].';';
$zonesString.="n";
}
// now create the limits that should be applied inside the location sections
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesArray[$zoneName]='limit_req zone='.$endpointPrefix.'_'.$zoneName;
if ($params['burst']) {
$zonesArray[$zoneName].=' burst='.$params['burst'];
}
if ($params['options']) {
$zonesArray[$zoneName].=' '.$params['options'];
}
}
return array($mapString0."n".$mapString1, $zonesString,$zonesArray);
}
When executed the above script produces:
# Define the ips and maps
geo $myendpoint {
default 0;
11.11.11.11/32 1;
1.1.1.1/24 1;
22.22.22.22/32 2;
2.2.2.2/24 2;
33.33.33.33/32 3;
3.3.3.3/24 3;
}
map $myendpoint $myendpoint_key_default {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $myendpoint $myendpoint_key_zone3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
#Define the zones
limit_req_zone $myendpoint_key_default zone=myendpoint_default:10m rate=10r/s;
# 11.11.11.11/32
# 1.1.1.1/24
limit_req_zone $myendpoint_key_zone1 zone=myendpoint_zone1:10m rate=10r/s;
# 22.22.22.22/32
# 2.2.2.2/24
limit_req_zone $myendpoint_key_zone2 zone=myendpoint_zone2:10m rate=20r/s;
# 33.33.33.33/32
# 3.3.3.3/24
limit_req_zone $myendpoint_key_zone3 zone=myendpoint_zone3:10m rate=30r/s;
# limit directives to be placed inside the location section
limit_req zone=myendpoint_default burst=100
limit_req zone=myendpoint_zone1 burst=100
limit_req zone=myendpoint_zone2 burst=100 nodelay
limit_req zone=myendpoint_zone3 burst=100
I was searching for the same configuration today and could not find an example with more than 2 zones too. So here is what in theory should work (I have not yet tried it out) :
geo $limited_ip {
default 0;
1.1.1.1/24 1;
2.2.2.2/24 2;
3.3.3.3/24 3;
}
map $limited_ip $limited_ip_key0 {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $limited_ip $limited_ip_key1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $limited_ip $limited_ip_key2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $limited_ip $limited_ip_key3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
limit_req_zone $limited_ip_key0 zone=zone0:10m rate=100r/m;
limit_req_zone $limited_ip_key1 zone=zone1:10m rate=200r/m;
limit_req_zone $limited_ip_key2 zone=zone2:10m rate=500r/m;
limit_req_zone $limited_ip_key3 zone=zone3:10m rate=1r/m;
limit_req zone=zone0 burst=10 nodelay;
limit_req zone=zone1 burst=10 nodelay;
limit_req zone=zone2 burst=10 nodelay;
limit_req zone=zone3 burst=1 nodelay;
Explanation:
a) if IP is none of the 3 defined then
$limited_ip_key0 = $binary_remote_addr
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone0 will be matched only, and the rate limit of 100r/m will be applied
b) if IP is 1.1.1.1/24
$limited_ip_key0 = ''
$limited_ip_key1 = $binary_remote_addr
$limited_ip_key2 = ''
$limited_ip_key3 = ''
thus the zone1 will be matched only, and the rate limit of 200r/m will be applied
c) if IP is 2.2.2.2/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = $binary_remote_addr
$limited_ip_key3 = ''
thus the zone2 will be matched only, and the rate limit of 500r/m will be applied
d) if IP is 3.3.3.3/24
$limited_ip_key0 = ''
$limited_ip_key1 = ''
$limited_ip_key2 = ''
$limited_ip_key3 = $binary_remote_addr
thus the zone3 will be matched only, and the rate limit of 1r/m will be applied
Here is a php script to automatically create the required zones so you can be able to administer more zones and ips easily
<?php
list($mapString, $zonesString, $zonesArray) = createZones(
"myendpoint",
array(
"default"=>array(
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone1"=>array(
"ips"=>array(
"11.11.11.11/32",
"1.1.1.1/24"
),
"zoneSize"=>"10m",
"rate"=>"10r/s",
"burst"=>"100",
"options"=>""
),
"zone2"=>array(
"ips"=>array(
"22.22.22.22/32",
"2.2.2.2/24"
),
"zoneSize"=>"10m",
"rate"=>"20r/s",
"burst"=>"100",
"options"=>"nodelay"
),
"zone3"=>array(
"ips"=>array(
"33.33.33.33/32",
"3.3.3.3/24"
),
"zoneSize"=>"10m",
"rate"=>"30r/s",
"burst"=>"100",
"options"=>""
),
)
);
echo "# Define the ips and mapsn$mapStringn#Define the zonesn$zonesStringnn";
echo "t# limit directives to be placed inside the location sectionn";
foreach ($zonesArray as $zoneName=>$zoneString) {
echo "t$zoneStringn";
}
function createZones($endpointPrefix,$zones) {
$mapString0='geo $'.$endpointPrefix.' {'."nttdefaultt0;";
$mapString1='';
$zonesString='';
$zonesArray=array();
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
if ($zoneName!='default') {
$zoneNum++;
foreach($params['ips'] as $ip) {
$mapString0.="ntt$ipt$zoneNum;";
}
}
}
$mapString0.="n}n";
$zoneNumTotal=$zoneNum;
// now that we now the total zones we can create the maps
$zoneNum=0;
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$mapString1.='map $'.$endpointPrefix.' $'.$endpointPrefix.'_key_'.$zoneName.' {';
for($zoneNumTemp=0;$zoneNumTemp<=$zoneNumTotal;$zoneNumTemp++) {
if ($zoneNum==$zoneNumTemp) {
$mapString1.="ntt$zoneNumTempt$binary_remote_addr;";
} else {
$mapString1.="ntt$zoneNumTempt'';";
}
}
$mapString1.="n}nn";
$zoneNum++;
}
// now create the actual zones string
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesString.="n";
if ( isset( $params['ips']) ) {
foreach ($params['ips'] as $ip) {
$zonesString .= "# $ipn";
}
}
$zonesString.='limit_req_zone $'.$endpointPrefix.'_key_'.$zoneName.' zone='.$endpointPrefix.'_'.$zoneName.':'.$params['zoneSize'].' rate='.$params['rate'].';';
$zonesString.="n";
}
// now create the limits that should be applied inside the location sections
foreach ($zones as $zoneName=>$params) {
$zoneName=strtolower($zoneName);
$zonesArray[$zoneName]='limit_req zone='.$endpointPrefix.'_'.$zoneName;
if ($params['burst']) {
$zonesArray[$zoneName].=' burst='.$params['burst'];
}
if ($params['options']) {
$zonesArray[$zoneName].=' '.$params['options'];
}
}
return array($mapString0."n".$mapString1, $zonesString,$zonesArray);
}
When executed the above script produces:
# Define the ips and maps
geo $myendpoint {
default 0;
11.11.11.11/32 1;
1.1.1.1/24 1;
22.22.22.22/32 2;
2.2.2.2/24 2;
33.33.33.33/32 3;
3.3.3.3/24 3;
}
map $myendpoint $myendpoint_key_default {
0 $binary_remote_addr;
1 '';
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone1 {
0 '';
1 $binary_remote_addr;
2 '';
3 '';
}
map $myendpoint $myendpoint_key_zone2 {
0 '';
1 '';
2 $binary_remote_addr;
3 '';
}
map $myendpoint $myendpoint_key_zone3 {
0 '';
1 '';
2 '';
3 $binary_remote_addr;
}
#Define the zones
limit_req_zone $myendpoint_key_default zone=myendpoint_default:10m rate=10r/s;
# 11.11.11.11/32
# 1.1.1.1/24
limit_req_zone $myendpoint_key_zone1 zone=myendpoint_zone1:10m rate=10r/s;
# 22.22.22.22/32
# 2.2.2.2/24
limit_req_zone $myendpoint_key_zone2 zone=myendpoint_zone2:10m rate=20r/s;
# 33.33.33.33/32
# 3.3.3.3/24
limit_req_zone $myendpoint_key_zone3 zone=myendpoint_zone3:10m rate=30r/s;
# limit directives to be placed inside the location section
limit_req zone=myendpoint_default burst=100
limit_req zone=myendpoint_zone1 burst=100
limit_req zone=myendpoint_zone2 burst=100 nodelay
limit_req zone=myendpoint_zone3 burst=100
edited Jan 19 at 12:30
answered Jan 18 at 19:06
Manolis AndreadakisManolis Andreadakis
12
12
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53521185%2fmultiple-limit-req-zone-with-geo-and-map-in-nginx%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown