Fork me on GitHub
Fork me on GitHub

Nginx、Nignx Plus减轻DDoS攻击(译)

DDoS攻击是一种对服务的攻击,一般是对网站的攻击,通过使用多台机器连续的流量轰炸目标服务器,以使得提供服务的主机因为资源用尽而不再能够提供有效地提供服务。

典型的,攻击者尝试通过大量的连接和请求使系统饱和,以使得目标主机无法再接收新的流量,或者响应变慢地不可用。

应用层DDoS攻击特征


应用层(Layer 7/HTTP) DDoS攻击是通过利用特定系统的脆弱点而特制的软件程序来完成。例如,对于不处理大量并发连接请求的系统,仅仅打开大量的连接,并且周期性地发送少量的流量来使得连接存活就会耗尽系统的性能以至于无法响应新连接。其他的攻击可采取发送大量的请求或非常大的请求的形式。因为这些攻击是通过肉鸡完成的,而不是通过真实的用户,攻击者可以轻松地、很快地打开大量数据的连接和发送大量的请求。
DDoS的攻击特征可以被用来帮助抵御它们,包括下面(这并不意味着以下列出来的是详尽无遗的):
  1.流量正常是来自一个特定的IP地址的集合,属于那么完成攻击的机器。所以,每一个ip地址负责发起许多连接,而不是你想象的它们来自一个真实用户。
  注意:不要认为这些流量情况总是代表一次DDoS攻击。代理服务器转发也会造成这种情况,因为代理服务器的ip地址被作为了所有真实客户端的ip地址。不管怎么样,来自于一个代理服务器转发的连接请求数要比真正DDoS攻击的请求数量少很多。
  2.因为流量是由于肉鸡产生的,而且是为了压垮目标服务器,流量的速率比一个真实用户能产生的要大的多。
  3.头部中的User-Agent有时候被设置为一个非标准值。
  4.头部中的Referer有时候被设置为某个值,使你能联想到这是攻击。

用Nginx和Nginx Plus抵御DDoS攻击


Nginx和Nginx Plus有许多特性——和上面提到的DDoS攻击的特性相结合——可以成为有效地防御DDoS攻击的一部分。因为它们是代理后端服务器,这些特性通过调节流量的进入和控制流量来防御DDoS攻击。

限制请求速率

你可以限制Nginx和Nginx Plus接收用户的请求速率为一个典型的真实用户请求的速率值。例如,你可以决定一个真正的用户每2秒只能访问登录页面一次。你可以配置Nginx和Nginx Plus允许一个ip地址每2秒可以尝试登录一次(相当于一分钟可以发起30次请求):

    
    limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;

    server {
        ...
        location /login.html {
            limit_req zone=one;
        ...
        }
    }
    

limit_req_zone指令配置一个名字为one的共享区域,用来存储指定的key的请求状态,这种情况下客户端ip地址用变量($binary_remote_addr)来表示。在location /login.html模块中的limit_req指令指定了用到的共享存储区域。

限制连接数

你可以限制一个客户端ip地址可以建立的连接数,指定为一个合适的值。例如,对于你网站的/store资源,你可以允许每个一个客户端ip地址打开不多于10个连接:

    
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    server {
        ...
        location /store/ {
           limit_conn addr 10;
        ...
        }
    }
    

limit_conn_zone指令配置了一个名为addr的共享区域,用来存储指定的key的请求状态,这种情况下客户端ip用变量$binary_remote_addr来表示。在location /store模块中的limit_conn指令指定了共享存储区域和设置一个客户端ip的最大连接数为10。

关闭慢连接

你可以把写数据非常少的连接关闭掉,这些连接尝试着保持连接尽可能长时间(那样会降低服务器接收新连接的能力)。Slowloris就是一个攻击的例子。client_body_timeout指令控制Nginx等待客户端的发送请求体的时间间隔,client_header_timeout指令控制Nginx等待客户端发送请求头的时间间隔。默认这两个指令设置的时间是60秒。下面的例子配置Nginx等待请求头和请求体的时间不超过5秒。

    
    server {
        client_body_timeout 5s;
        client_header_timeout 5s;
        ...
    }
    

把IP地址列入黑名单

如果你能够确认某个客户端ip地址是用来攻击的,你可以使用deny指令让Nginx和Nginx Plus不接受来自他们的连接或请求。例如,如果你确定攻击来自ip地址范围是123.123.123.1~123.123.123.16:

    
    location / {
        deny 123.123.123.0/28;
        ...
    }
    

或者如果你确定攻击来自于客户端ip地址123.123.123.3,123.123.123.5和123.123.123.7:

    
    location / {
       deny 123.123.123.3;
       deny 123.123.123.5;
       deny 123.123.123.7;
       ...
    }
    

把IP地址列入白名单

如果仅允许来自某个或某些特定集合范围的客户端ip地址访问你的网站,你可以一起使用allow和deny指令只允许那些ip地址访问你的网站和应用。例如,你可以限定一个指定网络中的ip地址可以访问网站或应用:

    
    location / {
       allow 192.168.1.0/24;
       deny all;
       ...
    }
    

这里,deny指令阻止了所有的客户端ip地址的访问,除了allow指令指定的ip地址范围。

使用缓存来缓和流量峰值

你可以配置Nginx和Nginx Plus开启缓存和设置指定的缓存参数来吸收一次攻击中的流量峰值,为后端减轻请求压力。一些有帮助的设置有:

  1.proxy_cache_use_stale指令的updating参数告诉Nginx当它需要获取一个陈旧的缓存对象的更新时,它应该只用一个线程去更新缓存对象,并且在线程接收到后端服务器已更新通知的时间段内,所有线程仍然提供陈旧的对象给请求它们的客户端。当一次攻击中有重复请求同一个文件的,这将大大减少对后端服务器的请求数量。

  2.proxy_cache_key指令定义的key通常由嵌入的变量(默认的key有3个,$scheme$proxy_host$request_uri)。如果值中包含变量$query_string,那么一次攻击发送随机的查询字符串会导致过多的缓存。我们推荐不要在key中使用变量$query_string,除非你有特殊的理由。

阻塞请求

你可以配置Nginx和Nginx Plus去阻塞几种请求:

  1.请求一个似乎是目标的中指定URL
  2.请求中的User-Agent头部的值与正常客户端请求的值符合
  3.请求中的Referer头部的值被设置为了一个与攻击有关系的值
  4.请求中的其他头部有与攻击相关的值。

例如:如果你确定DDoS攻击是攻击目标URL /foo.php,你可以阻止对这个页面的所有请求:

    
    location /foo.php {
       deny all;
    }
    

或者如果你发现DDoS攻击请求中的User-Agent头部的值是foo或bar,你可以拒绝这些请求。

    
    location / {
       if ($http_user_agent ~* foo|bar) {
           return 403;
       }
       ...
    }
    

变量http_name引用一个请求头,在上面的例子中就是User-Agent头部。类似的方法可以用在其他的那些可能被用来标识一次攻击的头部上。

限制连入后端服务器的连接数

一个Nginx和Nginx Plus实例通常可以对付的并发数比它正在负载均衡的后端服务器要多。使用Nginx Plus,你可以限制每个后端服务器所接受的请求数。例如,如果你想通过Nginx Plus限制名字叫做website后端服务器组里的两个服务器中每个服务器接受不超过200个连接:

    
    upstream website {
       server 192.168.100.1:80 max_conns=200;
       server 192.168.100.2:80 max_conns=200;
       queue 10 timeout=30s;
    }
    

max_conns参数为每一个后端服务器指定Nginx Plus为它们打开的最大连接数。queue指令用于当在后端服务器组里的所有服务器都达到了它们的最大连接限制时,限制排队的请求数目。timeout参数指定了一个请求在队列中保留多久。

对付基于范围的攻击

攻击的一个方法就是发送一个具有非常大的值的范围头部,这可能会导致缓冲区溢出。关于如何使用NGINX和NGINX Plus以一种简单的方式减缓这种类型的攻击,见Using NGINX and NGINX Plus to Protect Against CVE-2015-1635

对付高负载

DDoS攻击通常会导致很高流量负载。关于调整NGINX或者NGINX Plus以及操作系统让系统能够处理更高的负载,见Tuning NGINX for Performance


标识DDoS攻击


到目前为主,我们主要关注可以利用NGINX和NGINX Plus减轻DDoS攻击的影响。但是NGINX或者NGINX是如何帮助你发现DDoS攻击?NGINX Plus状态模块提供了对被负载的后端服务器流量的详细度量,你可以使用这些指标发现不正常流量模式。NGINX Plus有一个web页面显示状态信息,生动地描绘了NGINX Plus系统当前的状态(示例见demo.nginx.com)。通过API的方式可以获得同样的指标度量,你可以将这些指标注入自定义或者第三方的监控系统,你可以做历史趋势分析去发现异常模式和启用报警。


总结


NGINX和NGINX Plus可以作为一个减轻DDoS攻击的重要组成部分,而且NGINX Plus提供额外的特性去抵御DDoS攻击,并且在它们发生时,帮助发现它们。



原文Mitigating DDoS Attacks