HTTP 请求的特征一般有两种:IP 地址和 User Agent 字段。比如,恶意请求都是从某个 IP 段发出的,那么把这个 IP 段封掉就行了。或者,它们的 User Agent 字段有特征(包含某个特定的词语),那就把带有这个词语的请求拦截。
拦截可以在三个层次做。
(1)专用硬件
Web 服务器的前面可以架设硬件防火墙,专门过滤请求。这种效果最好,但是价格也最贵。
(2)本机防火墙
操作系统都带有软件防火墙,Linux 服务器一般使用 iptables。比如,拦截 IP 地址1.2.3.4的请求,可以执行下面的命令。
$ iptables -A INPUT -s 1.2.3.4 -j DROP
iptables 比较复杂,我也不太会用。它对服务器性能有一定影响,也防不住大型攻击。
(3)Web 服务器
Web 服务器也可以过滤请求。拦截 IP 地址1.2.3.4,nginx 的写法如下。
location / {
deny 1.2.3.4;}
Apache 的写法是在.htaccess文件里面,加上下面一段。
<RequireAll>
Require all granted
Require not ip 1.2.3.4</RequireAll>
如果想要更精确的控制(比如自动识别并拦截那些频繁请求的 IP 地址),就要用到 WAF。这里就不详细介绍了,nginx 这方面的设置可以参考这里和这里。
Web 服务器的拦截非常消耗性能,尤其是 Apache。稍微大一点的攻击,这种方法就没用了。
五、带宽扩容
上一节的 HTTP 拦截有一个前提,就是请求必须有特征。但是,真正的 DDOS 攻击是没有特征的,它的请求看上去跟正常请求一样,而且来自不同的 IP 地址,所以没法拦截。这就是为什么 DDOS 特别难防的原因。