获取用户的真实ip

做网站时候经常会用到remote_addr和x_forwarded_for 这两个头信息来获取,客户端ip,然而当有反向代理或者CDN的情况下,这两个就不够准确了,需要调整一些配置

remote_addr:

remote_addr 代表客户端的ip,但它的值不是由客户端提供的,而是服务端根据服务端的ip指定的,

当你的浏览器访问某个网站时候,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等) 就会把remote_addr设为你的机器ip

如果你用了某代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到
网站,这样web服务器就会把remote_addr设为这台代理机器的IP

 

x_forwarded_for(XFF)

x_forwarded_for 是用来识别通过HTTP代理或者负载均衡的方式连接web服务器的客户端最原始的IP地址的HTTP请求头字段

正如上面所述,当你使用了代理时,web服务器就不知道客户端访问的的真实IP了,
为了避免这个情况,代理服务器通常会增加一个叫做x_forwarded_for的头信息,
把连接它的客户端IP(即你上网机器的IP)加到这个头信息里面,这样就能保证网站的web服务器能获取到客户端的真实IP

 

在反向代理架构中,不能通过REMOTE_ADDR来获取用户的真实ip!

一般的方式是这样:

nginx------->>(fastcgi方式)------->>php引擎

nginx把REMOTE_ADDR传递给了php。代表的是当前与nginx通信的客户端ip,一般情况下(非反向代理),这个客户就是用户的浏览器,所以得到的用户的ip。

 

假设做了反向代理架构,是下面这样子的:

用 户------->>服务器 a------->>nginx------->> (fastcgi方式通信)------->>php引擎

用户访问一个域名,实际上是通过服务器a做了转发,转发到nginx去(反向代理架构经常会这样部署)

于是,当前与nginx通信的客户端,就是服务器a的地址, REMOTE_ADDR就是a服务器的地址了。

总结:在nginx作为反向代理的架构中,php的REMOTE_ADDR(其他语言也是类似的名称)拿到的将会是nginx代理的ip地址。

拿不到用户的真实ip,拿到是nginx反向代理服务器地址。

 

REMOTE_ADDR本意就是远程的地址,nginx是代理层,转发请求到php,php获取到的远程地址实际上是nginx反向代理服务器ip,这是符合协议规则的。

但是,可以让nginx帮助我们拿到用户的真实ip,写到一个环境变量中,然后转发给我们,只要按照某个约定的名称即可,比如约定名称为HTTP_X_FORWARD_FOR(也可以约定其他名称,关键看nginx中配置)

其实Nginx中有一个$http_x_forwarded_for变量,这个变量中保存的内容就是请求中的X-Forwarded-For信息。如果后端获得X-Forwarded-For信息的程序兼容性不好的话(没有考虑到X-Forwarded-For含有多个IP的情况),最好就不要将X-Forwarded-For设置为$proxy_add_x_forwarded_for应该设置为$http_x_forwarded_for或者干脆不设置!

nginx配置类似于这样:

fastcgi_param  HTTP_X_FORWARD_FOR  $remote_addr;

目的是,将HTTP_X_FORWARD_FOR的值设置为$remote_addr的值。也就是将用户真实的ip(或用户使用代理的ip)放到HTTP_X_FORWARD_FOR中去。

 $remote_addr是nginx的内置变量,这个变量它得到是用户真实的ip地址(用户使用了代理,则就是代理的ip地址)。

于是在php端通过getenv("HTTP_X_FORWARDED_FOR")就可以获取到nginx传递过来的值,是用户真实的ip地址。

 

posted @ 2017-03-31 14:07  joshua317  阅读(537)  评论(0编辑  收藏  举报