nginx可以通过limit_conn_zonelimit_req_zone两个组件来对客户端访问目录和文件的访问频率和次数进行限制,另外还可以善用进行服务安全加固,两个模块都能够对客户端访问进行限制,具体如何使用要结合公司业务环境进行配置。

如能善用此模块能够对 cc、ddos等此类的攻击进行有效的防御。

先来看下我们的配置文件

geo $addr_req_whitelist {
        ranges;
        default 0;
        111.206.171.51-111.206.171.51 1;     #360 bjmd proxy
        180.149.134.10-180.149.134.10 1;     #weibo.com verification peer
        
        # --- 百度免流IP段 2018-03-13 --- #
        180.97.106.0-180.97.106.255 1;
    }
    
    map $http_x_forwarded_for $clientRealIp {
        "" $remote_addr;
        ~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
    }
    
    map $clientRealIp $clientRealIp2C {
        ~^(?P<ip2c>[0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+$ $ip2c;
    }
    
    map $http_user_agent $dirtyUserAgent {
        default $msec;
        ~^.*(?P<userAgent>Mb2345Browser/9.0).*$ $userAgent;
        ~^.*(?P<userAgent>LieBaoFast/4.51.3).*$ $userAgent;
        ~^.*(?P<userAgent>OPPO\sA33\sBuild/LMY47V).*$ $userAgent;
        ~^.*(?P<userAgent>MicroMessenger/6.5.16).*$ $userAgent;
        ~^.*(?P<userAgent>UpdateRankQ0003).*$ $userAgent;
    }
    
    map $http_user_agent $test_map {
        default $clientRealIp;
        ~^.*(?P<userAgent>KHTML,\slike\sGecko).*$ $userAgent;
    }
    
    limit_req_whitelist geo_var_name=addr_req_whitelist geo_var_value=1;
    #这是白名单用户
    
    limit_conn_zone $clientRealIp zone=addr_conn_whitelist:10m;
    
    limit_req_zone $clientRealIp zone=addr_req_whitelist:10m rate=4r/s;
    #如果这个ip属于白名单里边那么可以执行 rate=4r/s(每秒4个请求)
    #定义一个名为 addr_req_whitelist 的limit_req_zone用来存储session,大小是10M内存, 
    #注释 zone=addr_req_whitelist  中的 addr_req_whitelist 和
  #1M能存储16000个状态,rete的值必须为整数,
     
    limit_req_zone $clientRealIp $request_uri zone=addr_request_uri_req_whitelist:10m rate=2r/s;
    
    limit_req_zone $clientRealIp2C zone=addr2c_req_whitelist:10m rate=4r/s;
    
    limit_req_zone $dirtyUserAgent zone=user_agent_req_whitelist:10m rate=3r/m;

然后找资料理解这段配置

nginx限速配置指令

指令 limit_zone

语法:limit_conn_zone $variable zone=name:size;

默认值:no

使用字段:http

指令描述会话状态存储区域。

会话的数目按照指定的变量来决定,它依赖于使用的变量大小和memory_max_size的值。

指令 limit_conn (和上边的limit_conn_zone合起来用)

语法:limit_conn zone_name(limit_conn_zone $variable zone=name:size;就是这个里边的 zone=name) max_clients_per_ip

默认值:no

使用字段:http, server, location

指令指定一个会话的最大同时连接数,超过这个数字的请求将被返回”Service unavailable” (503)代码。
对上边的总结
limit_zone: 是针对每个IP定义一个存储session状态的容器.这个示例中定义了一个10m的容器,按照32bytes/session, 可以处理320000个session。

limit_conn one 1:限制每个IP只能发起一个并发连接。

limit_rate 300k: 对每个连接都产生限速300k. 注意,这里是对连接限速,而不是对IP限速。如果一个IP允许两个并发连接,那么这个IP就是限速limit_rate×2。(这里就能理解百度云盘了,,他对每个链接限速<100k,你不买会员就只能是一个链接给你下载,你买会员了,哈哈,那就可以多给你分点链接,你就下载的快了)

nginx限制访问频率配置指令

http {
  limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
  server {
    ...
    location /search/ {
      limit_req zone=one burst=5;
        
        #限制每ip每秒不超过1个请求,漏桶数burst为5,也就是队列.
        #nodelay,如果不设置该选项,严格使用平均速率限制请求数,超过的请求被延时处理.
        #举个栗子:
        #设置rate=20r/s每秒请求数为20个,漏桶数burst为5个,
        #brust的意思就是,如果第1秒、2,3,4秒请求为19个,第5秒的请求为25个是被允许的,可以理解为20+5
        #但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误.
        #如果区域存储空间不足,服务器将返回503(服务临时不可用)错误 
        #速率在每秒请求中指定(r/s)。如果需要每秒少于一个请求的速率,则以每分钟的请求(r/m)指定。 
        #也可以这么,理解---上面的参数会让nginx 每个IP一秒钟只处理一个请求,但是仍然会有很多还在队列里面等待处理,这样也会占用很多tcp连接,从上面那条命令的结果中就能看得出来。如果加上nodelay就会立即丢弃 limit_req zone=one burst=10 nodelay;
    }

指令 limit_req_zone

语法:limit_req_zone $session_variable zone=name:size rate=rate

默认值:none

上下文:http

命令解析:为session会话状态分配一个大小为size的内存存储区,限制了每秒(分、小时)只接受rate个IP的频率。

指令 limit_req (和上边的limit_req_zone合起来用)

语法:limit_req zone=name burst=burst [nodelay]

默认值:none

使用字段:http、server、location

命令解析:该指令用于指定使用的内存存储区(zone)名称,以及最大的突发请求数(burse)。如果请求的速率超过了limit_req_zone指令中设置的速率,这些请求将被延迟处理,在这种情况下,请求获得服务不可用信息,返回503状态码。

指令 limit_conn_log_level

语法: limit_conn_log_level info | notice | warn | error

默认值: error

使用字段: http, server, location

指定当连接数超过设定的最大连接数,服务器限制连接时的日志等级。