linux

ddos攻击防御之使用nginx - use nginx to against ddos attack

ddos 攻击是最常见的web攻击了,原理非常简单,用自己的电脑模拟大量用户发送大量请求,apache 的 ab 压力测试工具就可以做到这一点,如果我这样做,而对方的服务器配置没有我电脑好,那么一会之后,对方的服务器就难以响应其他用户的请求,如果我控制了大量肉鸡并使用这些肉鸡发送请求,结果可想而知。

我假设你使用 nginx 或者其衍生版,那么,你可以通过简单的几行配置有效防御这种攻击,现在,我们步入正文,首先编辑 nginx.conf 在 http 里面添加下面两行,最终大致如下:

http {
    limit_req_zone $binary_remote_addr zone=blog:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=addr:10m;
}

这里我忽略了其他配置,第一行 limit_req_zone $binary_remote_addr zone=blog:10m rate=10r/s; 这里定义了一个名字为blog的会话区域,速度是10次每秒,你也可以使用600r/m 表示每分钟600次,但是没有每小时的限制哦,只有分钟与秒的限制,且为整数。但仅仅这样配置并不起作用,还需要在location里添加配置,如下:

location / {
    limit_conn addr 7;
    limit_req zone=blog burst=7 nodelay;
}

这里,burst 表示突发之意,blog 指定了要使用的请求会话区域,可以理解为平均每秒钟可以有10次请求,但是突发情况下允许每秒多增7个请求,且不延迟,超过7个则503,你也可以将nodelay删除,那么,如果你一秒内发送了20个请求过去,前10个是允许的,后面7个被延迟处理,最后的3个503,如果加了nodelay则是前17个立即处理,后面3个503,现在,我们来说下 limit_conn_zone $binary_remote_addr zone=addr:10m; 这行创建了10m的会话区域addr,存储的是连接数,不是请求数。limit_conn addr 7; 这句指定了使用addr 连接存储区域,且最多是7个。下面我举个栗子。

假设你们办公室公用一个IP,其实现在IP4即将枯竭,很多小区都是共享IP的,那么,addr 7表示,连接数不超过7,比如你们同时有7个设备访问这是OK的,但如果超过7台后被限制。而这7台设备每秒限制17次,超过就503,但是过一会就又可以继续访问,这种方案固然可以,但是实际作用也不够有力,假设某个IP一直请求,无视你的503,那么它就能一直继续请求下去,即使很明显这是攻击也无济于事,nginx的配置只能是过滤掉无用的请求,形成稳定的流量。如果你想一段时间内被限制超过了5次,就拉黑几分钟,那么可以看看这篇: fail2ban - 防御cc攻击利器,为什么要拉黑呢,因为nginx也是有压力的,比如这里的10m存储区域,另外,nginx返回503,请求不是没成功,只是没有转发给你的业务应用,nginx的压力依旧存在,大量请求过来,完全可能导致nginx瘫痪,这种限制只是保护了nginx后面的应用而已,当然nginx的并发性能很屌,这样处理也是OK的,但不代表nginx就不能被弄瘫痪,最好的办法是发现是明显攻击后将ip拉黑,可以动态的处理,比如拉黑几分钟、几十分钟、几小时等等。而这些fail2ban可以做到,你可以参考我之前给你的链接。

最后,我们讨论下这里的10M,你可以参考 nginx官方文档,文档最后面有这么几句话:

Here, the states are kept in a 10 megabyte zone “one”, and an average request processing rate for this zone cannot exceed 1 request per second.

A client IP address serves as a key. Note that instead of $remote_addr, the $binary_remote_addr variable is used here. The $binary_remote_addr variable’s size is always 4 bytes for IPv4 addresses or 16 bytes for IPv6 addresses. The stored state always occupies 64 bytes on 32-bit platforms and 128 bytes on 64-bit platforms. One megabyte zone can keep about 16 thousand 64-byte states or about 8 thousand 128-byte states.

If the zone storage is exhausted, the least recently used state is removed. Even if after that a new state cannot be created, the request is terminated with an error.

大致意思是:

这里状态保存在10M大的区域one里面,这个区域里平均请求处理速度不超过每秒1个请求。

客户端地址作为key键,请注意,这里并没有使用 $remote_addr 而是使用了 $binary_remote_addr 变量,一个ip4地址的$binary_remote_addr 变量的大小是4字节,ip6是16个字节。存储状态在32位操作系统上占用64个字节,在64位系统上占用128个字节,1M的区域大约可以存储16_000个64位的状态或者大约8_000个128位的状态。

如果区域存储空间耗尽,最近最少使用状态将被删除,即使在此之后无法创建新状态,该请求也会以错误终止。

综上述,64位系统1M大小的区域可以存储8千个IP,而32位是1万6千个,如果超过则会将最近最久未使用的删除,删除后如果还无法创建存储状态,这个请求也会以错误而终止,我的理解是这样。好了,但愿我们或者后代能生活在一个和平的网络世界,没有软文,没有恶意攻击,关注国事民生而不是明星娱乐,健康向上,而不是低俗无趣。

full-stack-trip

Share
Published by
full-stack-trip
Tags: ddosnginx

Recent Posts

Android 自定义 View 入门

说来惭愧,工作数年,连基本的自…

4 年 ago

retrofit 同时支持 xml 和 json

retrofit 解析 jso…

4 年 ago

mysql - 存储过程 从入门到放弃

最近有个报表的需求,于是乎用了…

4 年 ago

奶嘴战略 - 你不得不知道的扎心真相(一)

一句:英雄枯骨无人问,戏子家事…

4 年 ago

acme.sh 的简单使用

acme.sh 是纯 shel…

4 年 ago

wrk -更现代化的http压测工具

wrk 是一款更现代化的 ht…

4 年 ago