目前多数网站采取的访问模式有两种:
1、【用户浏览器】→【WAF】→【源站】的访问模式
2、【用户浏览器】→【CDN】→【源站】的访问模式
3、【用户浏览器】→【CDN[CDN入口、CC\DDoS攻击流量清洗等]】→ 【阿里云盾】→ 【源站】
通过$remote_addr
将获取到的IP
是WAF
或者CDN
的节点IP
而不是真实的用户IP
。为了解决此问题我们使用$http_x_forwarded_for
才能获取用户的真实IP
地址。哪么相关的策略都应该针对$http_x_forwarded_for
展开。
其实,当一个 CDN
或者透明代理服务器把用户的请求转到后面服务器的时候,这个 CDN
服务器会在Http
的头中加入一个记录:
X-Forwarded-For
:用户IP
, 代理服务器IP
如果中间经历了不止一个代理服务器,这个记录会是这样;
X-Forwarded-For
:用户IP
, 代理服务器1-IP
, 代理服务器2-IP
, 代理服务器3-IP
,……
。
## 用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址最多有 50 个并发连接 ## 你想开 几千个连接 刷死我? 超过 50 个连接,直接返回 503 错误给你,根本不处理你的请求了 limit_conn_zone $binary_remote_addr zone=TotalConnLimitZone:10m ; limit_conn TotalConnLimitZone 50; limit_conn_log_level notice; ## 用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址每秒处理 10 个请求 ## 你想用程序每秒几百次的刷我,没戏,再快了就不处理了,直接返回 503 错误给你 limit_req_zone $binary_remote_addr zone=ConnLimitZone:10m rate=10r/s; limit_req_log_level notice; ## 具体服务器配置 server { listen 80; location ~ \.php$ { ## 最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了 limit_req zone=ConnLimitZone burst=5 nodelay; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; } }
## 这里取得原始用户的IP地址 map $http_x_forwarded_for $clientRealIp { "" $remote_addr; ~^(?P[0-9\.]+),?.*$ $firstAddr; } ## 针对原始用户 IP 地址做限制 limit_conn_zone $clientRealIp zone=TotalConnLimitZone:20m ; limit_conn TotalConnLimitZone 50; limit_conn_log_level notice; ## 针对原始用户 IP 地址做限制 limit_req_zone $clientRealIp zone=ConnLimitZone:20m rate=10r/s; #limit_req zone=ConnLimitZone burst=10 nodelay; #如果开启此条规则,burst=10的限制将会在nginx全局生效 limit_req_log_level notice; ## 具体Server:如下在监听php部分新增限制规则即可 server { listen 80; location ~ \.php$ { ## 最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了 limit_req zone=ConnLimitZone burst=5 nodelay; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; } }
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 cd nginx-1.6.0/ #查看在用nginx的编译参数(如果是全新安装则省略) /usr/local/nginx/sbin/nginx -V nginx version: nginx/1.6.0 built by gcc 4.4.7 20120313 (Red Hat 4.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 -f objs/nginx /usr/local/nginx/sbin/ make upgrade
其实就和shell
的echo
差不多,能否输出自定义信息;比如:在Nginx
里面配置如下:
location /hello { echo "hello, world!"; }
访问http://yourdomain.com/hello
就会在浏览器里面输出hello, world!
了(如果域名开了CDN
可能会报404
)。
需要提到的真实用户的IP
,只要在本文第二步配置基础上,加上如下规则并reload
即可:
server { listen 80; server_name yourdomain.com; ## 以下是新增规则: ## 当用户访问 /realip 的时候,我们输出 $clientRealIp 变量,看看这个变量 ## 值是不是真的 用户源IP 地址 location /realip { echo $clientRealIp; } }
生效后访问http://yourdomain.com/realip
就能显示你所用电脑(宽带)的真实IP
了。(可在ip138
查验准确性):
本文由 podipod软库网 作者:DevOps 发表,转载请注明来源!