Nginx服务器有一个非常有用的限速功能, 这个功能用来限制用户在某些时间段内的HTTP请求数,主要是被应用于网络安全及带宽控制方面。比如减慢暴力密码破解的攻击,爬虫对网页的抓取,防止DDOS攻击等。

Nginx 提供三种限速方式:

限制连接数:

语法: limit_conn_zone key zone=name:size;

详细说明:https://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_conn_zone

例如:

http  {
    limit_conn_zone $binary_remote_addr zone=perip:10m;
    limit_conn_zone $server_name zone=perserver:10m;
    ...
    server  {
        ...
        # 限制每个IP能够最多建立10个连接
        limit_conn perip 10;
        # 限制每个网站最多接受100个连接
        limit_conn perserver 100;
    } 
}

限制请求速度:

语法:limit_req_zone key zone=name:size rate=rate [sync];

详细说明: https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone

限制请求速度可用于防止DDoS攻击,或防止上游服务器同时被太多请求淹没。

例如:

http  {
    limit_req_zone $binary_remote_addr zone=perip:10m rate=2r/s;
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    limit_req_zone $server_name zone=perserver:10m rate=10r/s;
    ...
    server {
        ...
        # 限制每个IP每秒不超过2个请求,突发不超过5个请求。
        limit_req zone=perip burst=5 nodelay;
        # 限制每个网站每秒不超过10个请求,突发不超过10个请求。
        limit_req zone=perserver burst=10;
        location /search/ {
            # 限制每个IP每秒不超过1个请求。
            limit_req zone=one;
        }
    }
}

限制带宽:

语法:limit_rate rate;

单位为:byte/s

详细说明: https://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate

该设置主要用于限制单个请求的下载速度,以为一个客户端可以建立多个请求,所以一般需要结合限制连接数使用,防止因为个别客户端而耗尽服务器带宽。

http {
    limit_conn_zone $binary_remote_address zone=perip:10m
    ...
    server {
        ...
        location /download/ {
            # 限制每个IP只能建立一个连接
            limit_conn perip 1;
            # 当请求的流量超500KB后进行限速
            limit_rate_after 500k;
            # 限速 50KB/s
            limit_rate 50k;
        }
    }
}

完整配置:

http  {
    # 限速IP白名单
    geo $limit {
        default 1;
        10.0.0.0/8 0;
        192.168.0.0/24 0;
        172.20.0.35 0;
    }
    
    # 白名单不限速,非白名单按照客户端IP限速
    map $limit $limit_key {
        0 "";
        1 $binary_remote_addr;
    }
    
    limit_conn_zone $server_name zone=perserver:10m;
    limit_req_zone $server_name zone=perserverreq:10m rate=10r/s;
    limit_conn_zone $limit_key zone=perip:10m;
    limit_req_zone $limit_key zone=two:10m rate=2r/s;
    limit_req_zone $limit_key zone=one:10m rate=1r/s;
    ...
    server  {
        ...
        # 限制每个网站每秒不超过10个请求,突发不超过10个请求。
        limit_req zone=perserverreq burst=10;
        # 限制每个网站最多接受100个请求
        limit_conn perserver 100;
        # 限制每个IP能够最多建立10个请求
        limit_conn perip 10;
        # 限制每个IP每秒不超过1个请求,突发不超过3个请求。
        limit_req zone=one burst=3 nodelay;
        
        location /search/ {
            # 限制每个IP每秒不超过1个请求。
            limit_req zone=one;
        }
        
        location /download/ {
            # 限制每个IP只能建立一个连接
            limit_conn perip 1;
            # 当请求的流量超500KB后进行限速
            limit_rate_after 500k;
            # 限速 50KB/s
            limit_rate 50k;
        }
    } 
}

备注:

需要注意的是客户端IP使用 $binary_remote_addr 变量,而不是 $remote_addr。
$remote_addr 是一个文本型变量,长度为7至15个字节之间。
$binary_remote_addr 是二进制的IP表达形式,对于IPv4地址,变量的大小始终为4个字节,对于IPv6地址,变量的大小始终为16个字节。
存储状态在32位平台上总是占用32或64字节,在64位平台上占用64字节。 1M的内存空间可以保留大约32000个32字节状态或16000个64位字节。例子中的10M的话换算下来可以保留16万个IP地址信息。当超出请求是服务器将返回错误。


原文链接地址:http://blog.exsvc.cn/article/nginx-limiting-access.html
转载请注明:转载自 易科博客 ,谢谢!

发表评论

电子邮件地址不会被公开。 必填项已用*标注