nginx限制策略

在nginx服务中通过限制访问频率的策略可以在一定程度上抵御DDoS攻击。

nginx访问频率限制

配置范例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 白名单
# geo $remote_addr $limited
geo $limited
{
default 1;
10.0.0.0/8 0;
123.207.144.100/32 0;
123.123.123.248/30 0;
}

map $limited $limit {
1 $binary_remote_addr;
0 "";
}

# nginx.conf 中的http模块中定义limit_req_zone
limit_req_zone $limit zone=reqzone1:10m rate=20r/s;

# server模块中的location规则中应用limit_req_zone(也可以直接应用到server或者http模块中)
server{
...

#limit_req zone=reqzone3 burst=20 nodelay;
limit_req zone=reqzone3 burst=20;
location xxx1 {
...
#limit_req zone=reqzone1 burst=20 nodelay;
limit_req zone=reqzone1 burst=20;
...
}
location xxx2 {
...
#limit_req zone=reqzone2 burst=20 nodelay;
limit_req zone=reqzone2 burst=20;
...
}

# 在http, server, location中均可定义limit_req_status code,默认503;

参数说明

  • geo

    • geo [$address] $variable { … } 定义从指定的变量获取客户端的IP地址。默认情况下,nginx从$remote_addr变量取得客户端IP地址,但也可以从其他变量获得。
  • map

    • map为一个变量设置的映射表,用来创建变量,映射表由两列组成,匹配模式和对应的值。但是仅在变量被接受的时候执行视图映射操作,对于处理没有引用变量的请求时,这个模块并没有性能上的缺失。
  • limit_req_zone

    • 第一个字段定义为key,限制对象。$binary_remote_addr(\x0A\x64\xCE\x10)是4字节的IPv4地址,或者16字节的IPv6地址,32位系统上占用32或64个字节,64位系统上占用128字节,占用空间比$remote_addr少64字节。10M大概可以保存160,000条记录。
      *limit_req_zone中如果key为””表示不对其进行频率限制,所以白名单将用户的key设置为””。
    • zone=reqzone1:10m,定义名为reqzone1大小为10M(漏桶算法桶的大小)的zone存储访问频率.共享内存空间被耗尽后则服务器将会对后续所有的请求返回503(Service Temporarily Unavailable)错误。
    • rate=20r/s,定义访问速率阈值,单位可以是r/s(次/秒)或者r/m(次/分钟)
  • limit_req

    • zone=reqzone1,选择应用的限制策略zone名称
    • burst=20,可选字段,缓冲请求数(特权令牌数,拥有特权令牌可以直接访问服务)
    • nodelay,可选字段,加入该字段后超出令牌数的请求直接返回503
  • burst和rate的关系

    • rate是限制的总并发数,burst是限制的并发用户数,如果rate=10r/s,burst=10,那么当某一秒钟有10个用户同时访问,一个用户在一秒内请求了10次,9个用户在一秒内请求了1次,则访问最多的那个用户的9个请求会被503

nginx限制并发连接数

1
2
3
4
5
6
7
8
9
10
11
12
13
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
...

server {

...

location /download/ {
limit_conn addr 1; # 限制统一客户端最大连接数为 1
}

参考