200

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

之前发表过一篇文章: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

 

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

《使用Varnish Cache时,让Nginx获取访客真实IP》上有12条评论

  1. DirectAdmin 可以用 Nginx 做前端、也就意味着可以用 Tengine 做前端吧?

    那安装了 Nginx 做前端之后用那个平滑升级 TenGine 的方法可以不?

          1. 求问这个是什么原因 。。我用的一个什么 Nginx 自动安装的脚本咻的一下安装完然后 service httpd restart 的时候说 Nginx 什么什么 .pid 不存在好像是

    1. 主要问题出在Varnish上,client.ip这个变量他只能获取XFF的内容,如果是Nginx好办了,直接用remote_addr(不是http_remote_addr)……

评论已关闭。