最近一直在帮一个购买了张戈博客付费服务的朋友作网站防御,为了简单抵挡一下竞争对手的DDoS攻击,他给网站开启了Incapsula的免费CDN服务。php
开启CDN以后,我以前给他写的Shell防御脚本也就宣告无效了,由于不论是正常访问仍是攻击访问,脚本拿到的IP都是CDN节点的,而我不可能把CDN的节点IP也给禁用了,那就都不能访问了。html
为了解决这个窘迫,我想到了之前看过的Nginx访问限制。经过查资料,让我拜读了一枚大神的神做,感受收获颇丰!因而转过来整理一下,分享给更多须要的人!node
Nginx 有2个模块用于控制访问“数量”和“速度”,简单的说,控制你最多同时有 多少个访问,而且控制你每秒钟最多访问多少次, 你的同时并发访问不能太多,也不能太快,否则就“杀无赦”。nginx
HttpLimitZoneModule 限制同时并发访问的数量git
HttpLimitReqModule 限制访问数据,每秒内最多几个请求github
什么叫普通配置?shell
普通配置就是针对【用户浏览器】→【网站服务器】这种常规模式的nginx配置。那么,若是我要对单IP作访问限制,绝大多数教程都是这样写的:浏览器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
## 用户的 IP 地址 $binary_remote_addr 做为 Key,每一个 IP 地址最多有 50 个并发链接
## 你想开 几千个链接 刷死我? 超过 50 个链接,直接返回 503 错误给你,根本不处理你的请求了
limit_conn_zone $binary_remote_addrzone=TotalConnLimitZone:10m;
limit_conn TotalConnLimitZone50;
limit_conn_log_level notice;
## 用户的 IP 地址 $binary_remote_addr 做为 Key,每一个 IP 地址每秒处理 10 个请求
## 你想用程序每秒几百次的刷我,没戏,再快了就不处理了,直接返回 503 错误给你
limit_req_zone $binary_remote_addrzone=ConnLimitZone:10mrate=10r/s;
limit_req_log_level notice;
## 具体服务器配置
server{
listen80;
location~\.php${
## 最多 5 个排队, 因为每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了
limit_req zone=ConnLimitZone burst=5nodelay;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
}
}
|
这样一个最简单的服务器安全限制访问就完成了,这个基本上你 Google 一搜索能搜索到 90% 的网站都是这个例子,并且还强调用“$binary_remote_addr”能够节省内存之类的云云。安全
目前国内已经争相出现了百度云加速、加速乐、360网站卫士以及安全宝等免费CDN。让咱们这些小网站也能免费享受之前高大上的CDN加速服务。服务器
用户浏览器 → CDN节点 → 网站源服务器
用户浏览器 → CDN节点(CDN入口、CC\DDoS攻击流量清洗等) → 阿里云盾 → 源服务器
能够看到,咱们的网站中间经历了好几层的透明加速和安全过滤, 这种状况下,咱们就不能用上面的“普通配置”。由于普通配置中基于【源IP的限制】的结果就是,咱们把【CDN节点】或者【阿里云盾】给限制了,由于这里“源IP”地址再也不是真实用户的IP,而是中间CDN节点的IP地址。
咱们须要限制的是最前面的真实用户,而不是中间为咱们作加速的加速服务器。
其实,当一个 CDN 或者透明代理服务器把用户的请求转到后面服务器的时候,这个 CDN 服务器会在 Http 的头中加入一个记录
X-Forwarded-For : 用户IP, 代理服务器IP
若是中间经历了不止一个代理服务器,这个记录会是这样
X-Forwarded-For : 用户IP, 代理服务器1-IP, 代理服务器2-IP, 代理服务器3-IP, ….
能够看到通过好多层代理以后, 用户的真实IP 在第一个位置, 后面会跟一串中间代理服务器的IP地址,从这里取到用户真实的IP地址,针对这个 IP 地址作限制就能够了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
## 这里取得原始用户的IP地址
map$http_x_forwarded_for$clientRealIp{
""$remote_addr;
~^(?P<firstAddr>[0-9\.]+),?.*$$firstAddr;
}
## 针对原始用户 IP 地址作限制
limit_conn_zone $clientRealIpzone=TotalConnLimitZone:20m;
limit_conn TotalConnLimitZone50;
limit_conn_log_level notice;
## 针对原始用户 IP 地址作限制
limit_req_zone $clientRealIpzone=ConnLimitZone:20mrate=10r/s;
#limit_req zone=ConnLimitZone burst=10 nodelay; #若是开启此条规则,burst=10的限制将会在nginx全局生效
limit_req_log_level notice;
## 具体Server:以下在监听php部分新增限制规则便可
server{
listen80;
location~\.php${
## 最多 5 个排队, 因为每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了
limit_req zone=ConnLimitZone burst=5nodelay;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
}
}
|
做者原文提到了nginx的一个echo模块,特地玩了下感受挺有意思的,下面贴一下简单集成步骤。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
cd/usr/local/src
#下载echo模块并解压:
wget https://github.com/openresty/echo-nginx-module/archive/v0.57.tar.gz
tar zxvf v0.57.tar.gz
#下载nginx并解压
wget http://nginx.org/download/nginx-1.6.0.tar.gz
tar-xzvf nginx-1.6.0.tar.gz
cdnginx-1.6.0/
#查看在用nginx的编译参数(若是是全新安装则省略)
/usr/local/nginx/sbin/nginx-V
nginx version:nginx/1.6.0
built by gcc4.4.720120313(Red Hat4.4.7-4)(GCC)#如下这行即为旧的编译参数:
configure arguments:--user=www--group=www--prefix=/usr/local/nginx--with-http_gzip_static_module
#在旧的编译参数基础上新增【--add-module=/echo模块的解压路径】参数,开始编译
./configure--prefix=/usr/local/nginx/nginx--add-module=/usr/local/src/echo-nginx-module-0.57
#make编译
make-j2
#平滑升级nginx (若是是全新安装请执行:make install)
mv/usr/local/nginx/sbin/nginx/usr/local/nginx/sbin/nginx.old
cp-fobjs/nginx/usr/local/nginx/sbin/
makeupgrade
|
其实就和shell的echo差很少,可否输出自定义信息。
好比,在nginx里面配置以下:
1
2
3
|
location/hello{
echo"hello, world!";
}
|
访问http://yourdomain.com/hello 就会在浏览器里面输出hello, world! 了(若是域名开了CDN可能会报404)。
又好比,测试本文提到的真实用户的IP,只要在本文第二步配置基础上,加上以下规则并reload便可:
1
2
3
4
5
6
7
8
9
10
|
server{
listen80;
server_name yourdomain.com;
## 如下是新增规则:
## 当用户访问 /realip 的时候,咱们输出 $clientRealIp 变量,看看这个变量
## 值是否是真的 用户源IP 地址
location/realip{
echo$clientRealIp;
}
}
|
生效后,访问http://yourdomain.com/realip 就能显示你所用电脑(宽带)的真实IP了(可在ip138查验准确性):
Ps:感兴趣又喜欢学习的童鞋能够看下相关wiki文档:http://wiki.nginx.org/HttpEchoModule
本文介绍到这就差很少结束了,也是在神做的基础上精简整理并测试的,若是看完还有些许疑问,请前往查看神做原文,也许仍是大神写的比较好理解(是不是原创我就不深究了,感受也是转来转去,都没留连接,悲哀的互联网)!
本文整理自【棒主妇开源】,原文地址:《网站安全配置(Nginx)防止网站被攻击》。