nginx防止DDOS攻击
概述
信息安全的三要素:“保密性”、“完整性”和“可用性”中,DoS(Denial of Service),即拒绝服务攻击,针对的目标正是“可用性”。该攻击方式利用目标系统网络服务功能缺陷或者直接消耗其系统资源,使得该目标系统无法提供正常的服务。
DDoS:Distributed Denial of Service,即分布式拒绝服务攻击。借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDoS攻击,从而成倍地提高拒绝服务攻击的威力。通常,攻击者使用一个偷窃帐号将DDoS主控程序安装在一个计算机上,在一个设定的时间主控程序将与大量代理程序通讯,代理程序已经被安装在网络上的许多计算机上。代理程序收到指令时就发动攻击。利用客户/服务器技术,主控程序能在几秒钟内激活成百上千次代理程序的运行。
比喻可以用一个比方来深入理解什么是DDOS。一群恶霸试图让对面那家有着竞争关系的商铺无法正常营业,他们会采取什么手段呢?恶霸们扮作普通客户一直拥挤在对手的商铺,赖着不走,真正的购物者却无法进入;或者总是和营业员有一搭没一搭的东扯西扯,让工作人员不能正常服务客户;也可以为商铺的经营者提供虚假信息,商铺的上上下下忙成一团之后却发现都是一场空,最终跑了真正的大客户,损失惨重。此外,恶霸们完成这些坏事有时凭单干难以完成,需要叫上很多人一起。嗯,网络安全领域中DoS和DDoS攻击就遵循着这些思路。
DDoS的攻击方式有很多种,最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应。单一的DoS攻击一般是采用一对一方式的,当攻击目标CPU速度低、内存小或者网络带宽小等等各项指标不高的性能,它的效果是明显的。随着计算机与网络技术的发展,计算机的处理能力迅速增长,内存大大增加,同时也出现了千兆级别的网络,这使得DoS攻击的困难程度加大了,目标对恶意攻击包的"消化能力"加强了不少。在此情况下,分布式的拒绝服务攻击手段(DDoS)就应运而生了。DDoS就是利用更多的“傀儡机”来发起进攻,以比从前更大的规模来进攻受害者,导致“可用性”坍塌、失效。
攻击手段
1、通过使网络过载来干扰甚至阻断正常的网络通讯。
2、通过向服务器提交大量请求,使服务器超负荷。
3、阻断某一用户访问服务器。
4、阻断某服务与特定系统或个人的通讯。
攻击方式
- SYN/ACK Flood攻击:
可通杀各种系统的网络服务,主要是通过向受害主机发送大量伪造源IP和源端口的SYN或ACK包,导致主机的缓存资源被耗尽或忙于发送回应包而造成拒绝服务,由于源都是伪造的故追踪起来比较困难,缺点是实施起来有一定难度,需要高带宽的僵尸主机支持。 - TCP全连接攻击
这种攻击是为了绕过常规防火墙的检查而设计的,一般情况下,常规防火墙对于正常的TCP连接是放过的,但是Web服务器能接受的TCP连接数是有限的,一旦有大量的TCP连接,即便是正常的,也会导致网站访问非常缓慢甚至无法访问,TCP全连接攻击就是通过许多僵尸主机不断地与受害服务器建立大量的TCP连接,直到服务器的内存等资源被耗尽而被拖跨,从而造成拒绝服务,这种攻击的特点是可绕过一般防火墙的防护而达到攻击目的,缺点是需要找很多僵尸主机,并且由于僵尸主机的IP是暴露的,因此此种DDOS攻击方式容易被追踪。 - 针对一些动态页面攻击力度最大,就是需要和数据库进行交互的,特征是和服务器建立正常的TCP连接,并不断的向脚本程序提交查询、列表等大量耗费数据库资源的调用,而服务器为处理此请求却可能要从上万条记录中去查出某个记录,这种处理过程对资源的耗费是很大的,而对于客户端来说轻而易举,常见的现象就是网站慢如蜗牛,缺点是对付只有静态页面的网站效果会大打折扣,并且可能会暴露攻击主机地址
配置
限制请求率
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;
server {
...
location /login.html {
limit_req zone=one;
...
}
}
//limit_req_zone:配置了一个名为one的共享内存
//zone:用来存储$binary_remote_addr的请求状态
//rate=30r/m:设置Nginx每两秒钟接收一个客户端IP的请求(大约等同于每分钟30个请求)
//location 块中 /login.html 的limit_req指令引用了共享内存zone
限制连接的数量
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
...
location /shopping/ {
limit_conn addr 10;
...
}
}
// 限制每一个 IP 对网站 /shopping 部分打开的连接数不超过 10 个.
//limit_conn指令引用了共享内存zone,并将最大连接数设置为 10.
关闭慢连接
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
client_body_timeout 5s;
client_header_timeout 5s;
...
}
//关闭那些一直保持打开同时写数据又特别频繁的连接
//client_body_timeout和client_header_timeout指令控制请求体或者请求头的超时时间,配置将等待时间控制在 5s 之内:
设置 IP 黑名单
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
deny 111.212.23.1;
deny 123.111.123.5;
deny 123.113.123.7;
...
}
//如果能识别攻击者所使用的客户端 IP 地址,那么通过deny指令将其屏蔽,可以通过脚本和计划任务自动检测
设置IP白名单
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
allow 192.122.1.0/24;
deny all;
...
}
//在互联网环境中不太容易实现,依据实际环境。
小站点解决方案
location /index/server/p/ {
if ($http_referer ~ ^$){
return 403;
}
if ($http_referer !~* mydomain) {
rewrite ^/(.*)$ http://127.0.0.1/ redirect;
#利用地址重写功能
}
if ($http_user_agent ~* (wget|curl|qdesk) ) {
return 403;
}
#若浏览器类型属于这几类,返回错误页面
}
nginx防止CC攻击
概述
CC攻击的原理是通过代理服务器或者大量肉鸡模拟多个用户访问目标网站的动态页面,制造大量的后台数据库查询动作,消耗目标CPU资源,造成拒绝服务
CC不像DDoS可以用硬件防火墙来过滤攻击,CC攻击本身的请求就是正常的请求。\
我们都知道网站的页面有静态和动态之分,动态网页是需要与后台数据库进行交互的,比如一些论坛用户登录的时候需要去数据库查询你的等级、权限等等,当你留言的时候又需要查询权限、同步数据等等,这就消耗很多CPU资源,造成静态网页能打开,但是需要和数据库交互的动态网页打开慢或者无法打开的现象。这种攻击方式相对于前两种实现要相对复杂一些,但是防御起来要简单的多,提供服务的企业只要尽量少用动态网页并且让一些操作提供验证码就能抵御一般的CC攻击。
这里能看出来DDoS和CC的区别,DDoS攻击打的是网站的服务器,而CC攻击是针对网站的页面攻击的,用术语来说就是,一个是WEB网络层拒绝服务攻击(DDoS),一个是WEB应用层拒绝服务攻击(CC)
主动抑制方法
- 为了让Nginx支持更多的并发连接数,根据实际情况对工作线程数和每个工作线程支持的最大连接数进行调整。例如设置“worker_processes 10”和“worker_connections 1024”,那这台服务器支持的最大连接数就是10×1024=10240。
worker_processes 10;
events {
use epoll;
worker_connections 10240;
}
- Nginx 0.7开始提供了2个限制用户连接的模块:NginxHttpLimitZoneModule和NginxHttpLimitReqModule。NginxHttpLimitZoneModule可以根据条件进行并发连接数控制。
http {
limit_zone my_zone $binary_remote_addr 10m;
server {
location /somedir/ {
limit_conn my_zone 1;
}
}
}
#其中“limit_zone my_zone $binary_remote_addr 10m”的意思是定义一个名称为my_zone的存储区域、my_zone中的内容为远程IP地址、my_zone的大小为10M;“location /somedir/”的意思是针对somedir目录应用规则;“limit_conn my_zone 1”的意思是针对上面定义的my_zone记录区记录的IP地址在指定的目录中只能建立一个连接。
- NginxHttpLimitReqModule可以根据条件进行请求频率的控制。例如可以定义以下代码:
http {
limit_req_zone $binary_remote_addr zone=my_req_zone:10m rate=1r/s;
...
server {
...
location /somedir/ {
limit_req_zone zone= my_req_zone burst=2;
}
#其中“limit_req_zone $binary_remote_addr zone=my_req_zone:10m rate=1r/s”的意思是定义一个名称为my_req_zone的存储区域,my_req_zone内容为远程IP地址,my_req_zone大小为10M,my_req_zone中的平均请求速率只能为1个每秒;“location /somedir/”的意思是针对somedir目录应用规则;“limit_req_zone zone= my_req_zone burst=2”的意思是针对上面定义的my_req_zone记录区记录的IP地址在请求指定的目录中的内容时最高2个每秒的突发请求速率。
#当有连接触发上诉规则时,Nginx会报“503 Service Temporarily Unavailable”的错误,停止用户请求。返回一个503,对服务器来说影响不大,只占用一个nginx的线程而已,相对来说还是很划算的。
为了测试效果,我将以上代码放入Nginx的配置文件,并编写了一个PHP文件显示phpinfo;另外还写了一个html文件,其中嵌入了多个iframe调用php文件。当我打开这个html文件了,可以看到只有一个iframe中的php文件正常显示了,其他的iframe都显示503错误。
应用举例(Discuz!)
Discuz!是使用比较多的一个php论坛程序。以Discuz!7.0为例,程序目录下有比较多的可以直接访问的php文件,但其中最容易受到攻击的一般有index.php(首页)、forumdisplay.php(板块显示)、viewthread.php(帖子显示)。攻击者一般会对这些页面发起大量的请求,导致HTTP服务器连接数耗尽、mysql数据库停止响应,最终导致服务器崩溃。为了防止上述页面被攻击,我们可以设定以下的规则进行防御:
http {
limit_zone myzone_bbs $binary_remote_addr 10m;
limit_req_zone $binary_remote_addr zone=bbs:10m rate=1r/s;
...
server {
...
location ~ ^/bbs/(index|forumdisplay|viewthread).php$ {
limit_conn myzone_bbs 3;
limit_req zone=bbs burst=2 nodelay;
root html;
fastcgi_pass unix:/dev/shm/php-cgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
}
}
//应用这条规则后,bbs目录下的index.php、forumdisplay.php和viewthread.php这些页面同一个IP只许建立3个连接,并且每秒只能有1个请求(突发请求可以达到2个)。虽然这样的规则一般来说对正常的用户不会产生影响(极少有人在1秒内打开3个页面),但是为了防止影响那些手快的用户访问,可以在nginx中自定义503页面,503页面对用户进行提示,然后自动刷新。在Nginx中自定义503页面:
error_page 503 /errpage/503.html;
//503页面的源代码:
[root@localhost ~]# vim /usr/local/nginx/html/503.html
<html>
< head>
< title>页面即将载入....</title>
< meta http-equiv=content-type c>
< META NAME="ROBOTS" C>
< /head>
< body bgcolor="#FFFFFF">
< table cellpadding="0" cellspacing="0" border="0" width="700" align="center" height="85%">
<tr align="center" valign="middle">
<td>
<table cellpadding="10" cellspacing="0" border="0" width="80%" align="center" style="font-family: Verdana, Tahoma; color: #666666; font-size: 11px">
<tr>
<td valign="middle" align="center" bgcolor="#EBEBEB">
<br /><b style="font-size: 16px">页面即将载入</b>
<br /><br />你刷新页面的速度过快。请少安毋躁,页面即将载入...
<br /><br />[<a href="javascript:window.location.reload();"><font color=#666666>立即重新载入</font></a>]
<br /><br />
</td>
</tr>
</table>
</td>
</tr>
< /table>
< /body>
< /html>
< SCRIPT language=javascript>
function update()
{
window.location.reload();
}
setTimeout("update()",2000);
< /script>
被动防御方法
- 虽然主动防御已经抵挡了大多数HTTP GET FLOOD攻击,但是道高一尺魔高一丈,攻击者会总会找到你薄弱的环节进行攻击。所以我们在这里也要介绍一下被动防御的一些方法。
拒绝IP地址
- 访问者通过浏览器正常访问网站,与服务器建立的连接一般不会超过20个,我们可以通过脚本禁止连接数过大的IP访问。以下脚本通过netstat命令列举所有连接,将连接数最高的一个IP如果连接数超过150,则通过 iptables阻止访问:
[root@localhost ~]# vim /opt/deny_ng.sh
#!/bin/sh
status=`netstat -na|awk '$5 ~ /[0-9]+:[0-9]+/ {print $5}' |awk -F ":" -- '{print $1}' |sort -n|uniq -c |sort -n|tail -n 1`
NUM=`echo $status|awk '{print $1}'`
IP=`echo $status|awk '{print $2}'`
result=`echo "$NUM > 150" | bc`
if [ $result = 1 ]
then
echo IP:$IP is over $NUM, BAN IT!
/sbin/iptables -I INPUT -s $IP -j DROP
fi
[root@localhost ~]# crontab -e
* * * * * /bin/bash /opt/deny_ng.sh
[root@localhost ~]# ab -n 1000 -c 100 http://www.xxx.com/bbs/index.php
//进行ab工具的测试
- 测试完成后,我们就可以看到系统中有IP被封的提示:
#tail /var/spool/mail/root
Content-Type: text/plain; charset=ANSI_X3.4-1968
Auto-Submitted: auto-generated
X-Cron-Env: <Shell=/bin/sh>
X-Cron-Env: <HOME=/root>
X-Cron-Env: <;PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>
IP:xx.xxx.xx.xx is over 1047, BAN IT!
至此,又一次HTTP GET FLOOD防御成功。
- 根据特征码屏蔽请求(对CC攻击效果较好)
一般同一种CC攻击工具发起的攻击请求包总是相同的,而且和正常请求有所差异。当服务器遭遇CC攻击时,我们可以快速查看日志,分析其请求的特征,比如User-agent。下面的是某一次CC攻击时的User-agent,Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; MyIE 3.01)Cache-Control: no-store, must-revalidate几乎没有正常的浏览器会在User-agent中带上“must-revalidate”这样的关键字。所以我们可以以这个为特征进行过滤,将User-agent中带有“must-revalidate”的请求全部拒绝访问:
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
if ($http_user_agent ~ must-revalidate) {
return 403;
}
预防爬虫攻击
概述
爬虫的比喻 如果我们把互联网比作一张大的蜘蛛网,那一台计算机上的资源便是蜘蛛网上的一个猎物,而爬虫程序就是一只小蜘蛛,沿着蜘蛛网抓取自己想要的猎物。
爬虫的定义 向网站发起请求,获取资源后分析并提取有用的程序。爬虫攻击事件利用网络漏洞对网站进行攻击,最终造成网站瘫痪!
利用http_user_agent
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.localhost.com;
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot")
{
return 403;
}
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 403;
}
//禁止非GET|HEAD|POST方式的抓取
利用Robots.txt
扩展了解
robots.txt是搜索引擎中访问网站的时候要查看的第一个文件。robots.txt文件告诉蜘蛛程序在服务器上什么文件是可以被查看的。
当一个搜索蜘蛛访问一个站点时,它会首先检查该站点根目录下是否存在robots.txt,如果存在,搜索机器人就会按照该文件中的内容来确定访问的范围;如果该文件不存在,所有的搜索蜘蛛将能够访问网站上所有没有被口令保护的页面。百度官方建议,仅当您的网站包含不希望被搜索引擎收录的内容时,才需要使用robots.txt文件。如果您希望搜索引擎收录网站上所有内容,请勿建立robots.txt文件。
Robots协议是国际互联网界通行的道德规范,基于以下原则建立:
1、搜索技术应服务于人类,同时尊重信息提供者的意愿,并维护其隐私权;
2、网站有义务保护其使用者的个人信息和隐私不被侵犯。
当然,如果搜索引擎不遵守约定的Robots协议,那么通过在网站下增加robots.txt也是不起作用的。(在正式环境中,可以适当允许搜索引擎抓取收录)
robots.txt文件生成地址
http://tool.chinaz.com/robots/