/ nginx

ddos

2018年5月15日 23:37 DDOS攻击 攻击规模为连接数:825
2018年5月16日 11:52 DDOS攻击 攻击规模为连接数:3711
2018年5月16日 15:57 DDOS攻击 攻击规模为连接数:2004
2018年5月16日 20:02 DDOS攻击 攻击规模为连接数:4292

Nginx 限流

Nginx 自带的两个模块:

  • 连接数限流模块 ngx_http_limit_conn_module
  • 漏桶算法实现的请求限流模块 ngx_http_limit_req_module

限制同一 IP 并发连接数:ngx_http_limit_conn_module

limit_conn 是对某个key 对应的总的网络连接数进行限流。

例如:按照 IP 限制并发连接数配置:

http {
    # 限流配置>>>
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    limit_conn_log_level error;
    limit_conn_status 503;
    # 限流配置<<<
    
    server /limit {
        # 限制同一时间内1个连接,超出的连接返回503 >>>
        limit_conn addr 1;
        # 限制同一时间内1个连接,超出的连接返回503 <<<
    }
}

limit_conn 的主要执行过程:

  1. 请求进入后首先判断 limit_conn_zone 中相应 key (这里就是 addr)的连接数是否超出了配置的最大连接数 1;
  2. 如果超过了 1,则被限流,返回 limit_conn_status 定义的错误状态码,也就是 503。否则 addr 加 1;
  3. 进行请求处理;
  4. 在结束请求阶段,将 addr 的连接数减 1;

使用 AB 测试工具进行测试,并发数为 5 个,总的请求书为 5 个:

ab -c 5 -n 5 http://localhost/limit

会发现有 3 个请求返回 503,其它两个请求正常 2xx。

error_log 显示为 limiting connections

如果每个请求为 100 ms,1 个并发,用户可以在 1 秒内请求 10 次。但是正常用户根本没有这么高的访问频率,每秒请求 1 次就够了。所以接下了要限制访问速率。

限制同一 IP 每秒请求数:ngx_http_limit_req_module

limit_req 是漏桶算法实现,用于对指定 key 对应的请求进行限流,比如,按照 IP 维度限制请求速率。

http {
    # 限速配置>>>
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    limit_conn_log_level error;
    limit_conn_status 503;
    # 限速配置<<<
    
    server /limit {
        # 限流配置,限制 IP 每秒1个请求 >>>
        limit_req zone=one burst=5 nodelay;
        # 限流配置,限制 IP 每秒1个请求 <<<
    }
}
  • limit_req_zone 命令设置了一个叫 one 的 10M 共享内存区来存储请求状态的特定键值,1m内存可以保存16000会话
  • burst 是爆发的意思,设置一个大小为5的缓冲区,当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内等待,但是这个等待区里的位置只有5个,超过的请求会直接报503的错误然后返回。
  • nodelay
    • 如果设置,会在瞬时提供处理(burst + rate)个请求的能力,请求超过(burst + rate)的时候就会直接返回503,永远不存在请求需要等待的情况。(这里的rate的单位是:r/s)
    • 如果没有设置,则所有请求会依次等待排队

error_log 显示为 limiting requests

综合配置

  • 每个 IP 的连接并发数为 1。
  • 每个正常用户每秒一个请求才是正常的。
http {
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    limit_conn_log_level error;
    limit_conn_status 503;
    
    server /limit {
        limit_conn addr 1;
        limit_req zone=one burst=5 nodelay;
    }
}

或者

http {
  limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
  limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

  server {
    limit_conn conn_limit_per_ip 10;
    limit_req zone=req_limit_per_ip burst=10 nodelay;
  }
} 

参考:https://stackoverflow.com/questions/12298541/config-of-nginx-to-filter-http-flood