运营维护

使用Varnish Cache时,让Nginx获取访客真实IP

200

之前发表过一篇文章:Varnish(前)+Nginx(中)时,让Apache(后)获取用户真实IP(多重代理)

该方法能成功解决使用或者不使用CDN时,在Varnish前端,Nginx中端,Apache解析PHP文件的情况下让Apache获取访客真实IP。因为当时主要是利用Nginx进行缓存,没使用其他功能,旧没让Nginx也获取访客真实的IP。

其中Varnish处理XFF的关键代码:

也就是把客户的IP赋值给XFF。那样后端处理就方便多了。

昨天在为一台Varnish+Nginx+Apache的服务器添加并测试防轻量级CC的功能,使用的Nginx模块是limit_req。虽然访问网站时,能获取访客的正常IP,但是Nginx得到的却是Varnish所在的服务器的IP。

测试时发现,由于limit_req模块是在Nginx上的,那样受到CC攻击的话,Nginx就会误判断是Varnish服务器的IP发出的请求,就会Ban掉Varnish服务器的IP,再次遇到Varnish的IP时,就会返回403……

403

 

尝试了Nginx的realip_module,发现无任何效果。

于是在另一台空闲的VPS上安装了Ubuntu 12.04,安装了Varnish,Nginx,PHP5-FPM进行测试。

研究了下Varnish和Nginx的配置,于是写了和PHP程序,查看XFF等信息:

测试后发现,REMOTE_ADDR一直都是Varnish所在的服务器的IP,而limit_req获取的正是REMOTE_ADDR的内容,那就是Ban Varnish的IP的原因了。由于Varnish那设置了HTTP_X_FORWARDED_FOR的内容舍弃原有内容(例如CDN服务器传来的),并且只含有客户IP,因此该项正常且不会影响REMOTE_ADDR。X-Real-ip这项内容是空白的,使用realip_module时,会使用到real_ip_header X-Real-IP这代码,大概是告诉服务器X-Real-IP才是客户真正的IP吧。

这下目标明确,要么搞定REMOTE_ADDR的,要么让real_ip_header X-Real-IP的real_ip_header获取真实的IP。

在Varnish那尝试了几次把客户的IP赋值给REMOTE_ADDR,使用或者不使用CDN时,REMOTE_ADDR就出问题了,要么是客户IP,要么CDN服务器的IP。

想了想,既然Nginx的real_ip_header能让Nginx知道访客真实IP,而HTTP_X_FORWARDED_FOR只有访客IP,把HTTP_X_FORWARDED_FOR的内容赋值给real_ip_header不就可以了么?

于是在删除原来所有与real_ip_header有关的代码,在Nginx的网站配置的server层(注意是server不是location)加入如下代码:

果然立竿见影,再次访问那个PHP文件,不管前面有没有上CDN,REMOTE_ADDR都与XFF的内容一模一样,也就是说,Nginx能获取到访客真实IP了。

把刚刚的成果帮到LANVMP的服务器上,在本机上狂F5,返回403,这是预料之中的事情,关键是,别的访客是不是200。于是再次打开17ce进行检查,非常好,全部都是200状态:

200

 

虽然解决该问题花了很多时间去折腾,不过能完美解决,也值得了……

Comments are closed.