使用 Nginx 抵御 DDOS 攻击

DDOS 是一种通过大流量的请求对目标进行轰炸式访问,导致提供服务的服务器资源耗尽进而无法继续提供服务的攻击手段。

一般情况下,攻击者通过大量请求与连接使服务器处于饱和状态,以至于无法接受新的请求或变得很慢。

应用层 DDOS 攻击的特征

应用层(七层 /HTTP 层)DDOS 攻击通常由木马程序发起,其可以通过设计更好的利用目标系统的脆弱点。例如,对于无法处理大量并发请求的系统,仅仅通过建立大量的连接,并周期性的发出少量数据包来保持会话就可以耗尽系统的资源,使其无法接受新的连接请求达到 DDOS 的目的。其他还有采用发送大量连接请求发送大数据包的请求进行攻击的形式。因为攻击是由木马程序发起,攻击者可以在很短时间内快速建立大量的连接,并发出大量的请求。

以下是一些 DDOS 的特证,我们可以据此特征来抵抗 DDOS(包括但不限于):

  • 攻击经常来源于一些相对固定的 IP 或 IP 段,每个 IP 都有远大于真实用户的连接数和请求数。

    备注:这并不表明这种请求都是代表着 DDOS 攻击。在很多使用 NAT 的网络架构中,很多的客户端使用网关的 IP 地址访问公网资源。但是,即便如此,这样的请求数和连接数也会远少于 DDOS 攻击。

  • 因为攻击是由木马发出且目的是使服务器超负荷,请求的频率会远远超过正常人的请求。

  • User-Agent 通常是一个非标准的值

  • Referer 有时是一个容易联想到攻击的值

使用 Nginx、Nginx Plus 抵抗 DDOS 攻击

结合上面提到的 DDOS 攻击的特征,Nginx、Nginx Plus 有很多的特性可以用来有效的防御 DDOS 攻击,可以从调整入口访问流量和控制反向代理到后端服务器的流量两个方面来达到抵御 DDOS 攻击的目的。

限制请求速度

设置 Nginx、Nginx Plus 的连接请求在一个真实用户请求的合理范围内。比如,如果你觉得一个正常用户每两秒可以请求一次登录页面,你就可以设置 Nginx 每两秒钟接收一个客户端 IP 的请求(大约等同于每分钟 30 个请求)。

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

server {

location /login.html {

limit_req zone=one;

}

}

limit_req_zone命令设置了一个叫 one 的共享内存区来存储请求状态的特定键值,在上面的例子中是客户端 IP($binaryremoteaddr)。location 块中的limit_req通过引用 one 共享内存区来实现限制访问 /login.html 的目的。

限制连接数量

设置 Nginx、Nginx Plus 的连接数在一个真实用户请求的合理范围内。比如,你可以设置每个客户端 IP 连接 /store 不可以超过 10 个。

limit_conn_zone $binaryremoteaddr zone=addr:10m;

server {

location /store/ {

limit_conn addr 10;

}

}

limit_conn_zone命令设置了一个叫 addr 的共享内存区来存储特定键值的状态,在上面的例子中是客户端 IP( $binaryremoteaddr)。location 块中limit_conn通过引用 addr 共享内存区来限制到 /store/ 的最大连接数为 10。

关闭慢连接

有一些 DDOS 攻击,比如 Slowlris,是通过建立大量的连接并周期性的发送一些数据包保持会话来达到攻击目的,这种周期通常会低于正常的请求。这种情况我们可以通过关闭慢连接来抵御攻击。

client_body_timeout命令用来定义读取客户端请求的超时时间,client_header_timeout命令用来定于读取客户端请求头的超时时间。这两个参数的默认值都是 60s,我们可以通过下面的命令将他们设置为 5s:

server {

client_body_timeout 5s;

client_header_timeout 5s;

}

设置 IP 黑名单

如果确定攻击来源于某些 IP 地址,我们可以将其加入黑名单,Nginx 就不会再接受他们的请求。比如,你已经确定攻击来自于从 123.123.123.1 到 123.123.123.16 的一段 IP 地址,你可以这样设置:

location / {

deny 123.123.123.0/28;

}

或者你确定攻击来源于 123.123.123.3、123.123.123.5、123.123.123.7 几个 IP,可以这样设置:

location / {

deny 123.123.123.3;

deny 123.123.123.5;

deny 123.123.123.7;

}

设置 IP 白名单

如果你的网站仅允许特定的 IP 或 IP 段访问,你可以结合使用 allow 和 deny 命令来限制仅允许你指定的 IP 地址访问你的网站。如下,你可以设置仅允许 192.168.1.0 段的内网用户访问:

location / {

allow 192.168.1.0/24;

deny all;

}

deny 命令会拒绝除了 allow 指定的 IP 段之外的所有其他 IP 的访问请求。

使用缓存进行流量削峰

通过打开 Nginx 的缓存功能并设置特定的缓存参数,可以削减来自攻击的流量,同时也可以减轻对后端服务器的请求压力。以下是一些有用的设置:

  • proxy_cache_use_stale的 updating 参数告诉 Nginx 什么时候该更新所缓存的对象。只需要到后端的一个更新请求,在缓存有效期间客户端对该对象的请求都无需访问后端服务器。当通过对一个文件的频繁请求来实施攻击时,缓存功能可极大的降低到后端服务器的请求。

  • proxy_cache_key命令定义的键值通常包含一些内嵌的变量(默认的键值 $scheme$proxyhost$requesturi 包含了三个变量)。如果键值包含$query_string变量,当攻击的请求字符串是随机的时候就会给 Nginx 代理过重的缓存负担,因此我们建议一般情况下不要包含$query_string变量。

屏蔽特定的请求

可以设置 Nginx、Nginx Plus 屏蔽一些类型的请求:

  • 针对特定 URL 的请求

  • 针对不是常见的 User-Agent 的请求

  • 针对 Referer 头中包含可以联想到攻击的值的请求

  • 针对其他请求头中包含可以联想到攻击的值的请求

比如,如果你判定攻击是针对一个特定的 URL:/foo.PHP,我们就可以屏蔽到这个页面的请求:

location /foo.php {

deny all;

}

或者你判定攻击请求的 User-Agent 中包含 foo 或 bar,我们也可以屏蔽这些请求:

location / {

if ($httpuseragent ~* foo|bar) {

return 403;

}

}

http_name 变量引用一个请求头,上述例子中是 User-Agent 头。可以针对其他的 http 头使用类似的方法来识别攻击。

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

一个 Nginx、Nginx Plus 实例可以处理比后端服务器多的多的并发请求。在 Nginx Plus 中,你可以限制到每一个后端服务器的连接数,比如可以设置 Nginx Plus 与 website upstream 中的每个后端服务器建立的连接数不得超过 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

优化 Nginx 性能

DDOS 攻击通常会带来高的负载压力,可以通过一些调优参数,提高 Nginx、Nginx Plus 处理性能,硬抗 DDOS 攻击,详细参考:Tuning NGINX for Performance

识别 DDOS 攻击

到目前为止,我们都是集中在如何是用 Nginx、Nginx Plus 来减轻 DDOS 攻击带来的影响。如何才能让 Nginx、Nginx Plus 帮助我们识别 DDOS 攻击呢?Nginx Plus Status module提供了到后端服务器流量的详细统计,可以用来识别异常的流量。Nginx Plus 提供一个当前服务状态的仪表盘页面,同时也可以在自定义系统或其他第三方系统中通过 API 的方式获取这些统计信息,并根据历史趋势分析识别非正常的流量进而发出告警。

总结

Nginx 和 Nginx Plus 可以作为抵御 DDOS 攻击的一个有力手段,而且 Nginx Plus 中提供了一些附加的特性来更好的抵御 DDOS 攻击并且当攻击发生时及时的识别到。