服务器获取真实客户端 IP

0x01 先查个问题

测试环境微信支付通道提示网络环境未能经过安全验证,请稍后再试,出现这种状况通常首要
想到多是双方网络交互中微信方验参与咱们出现不一致,翻了下手册肯定是这类问题开始排查环节html

  1. 可能获取真实IP方式错误nginx

    1. getenv('HTTP_CLIENT_IP')
    2. getenv('HTTP_X_FORWARDED_FOR')
    3. getenv('REMOTE_ADDR')
    4. filter_var($remote_ip, FILTER_VALIDATE_IP)
    5. 已经依次获取并过滤
    6. 固程序没有任何问题,往上发散
  2. 是否反向代理

    通过反向代理后,因为在客户端和web服务器之间增长了中间层,所以web服务器没法直接拿到客户端的ip,只能经过$remote_addr变量拿到的将是反向代理服务器的ip地址,检查不存在此类问题,再往上,擅长网络通讯工程的同窗表示毫不认输web

  3. 可能NAT分配出口IP,或负载均衡服务分发出现异常浏览器

    1. 先拿到我本地内网外网IP 方便以后问题排查缓存

      # 本机IP
      ifconfig | grep -A 1 "en" | grep broadcast | cut -d " " -f 2
      # 外网IP
      curl --silent http://icanhazip.com
    2. 检查与80端口创建链接目标都有谁安全

      netstat -tn|grep 80|akw '{print $5}'|awk -F '{print $1}' | grep [本地IP]

      这里出现问题,居然没有个人IP,再以nginx $remote_addr拿到的IP做为参考,这是nginx最后一次握手的IP,$remote_addr = 10.168.0.0/16bash

      nginx处打印$remote_addr,并在server_name添加当前机器ip,分别以负载均衡IP与本地IP作测试,最终肯定问题出如今负载均衡服务器出现异常服务器


0x02 LNMP栈拿真实IP

LNMP栈内PHP全部得到到的TCP操做信息都是由前面Nginx经过fastcgi传递给它的,就好比$_SERVER['REMOTE_ADDR']include fastcgi.conf;引进,其等于nginx$remote_addr微信

Nginx中的几个变量:网络

  • $remote_addr

    表明客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,icanhazip的原理也是这样, 当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器就会把remote_addr设为你在公网暴露的IP,若是你用了某个代理,那么你的浏览器会先访问这个代理,而后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP, 除非代理将你的IP附在请求header中一块儿转交给web服务器。

  • $proxy_add_x_forwarded_for

    $proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr两部分,他们之间用逗号分开。X-Forwarded-For(简称XFF),X-Forwarded-For 是一个 HTTP 扩展头部。RFC 2616 协议并无对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP。现在它已经成为事实上的标准,被各大HTTP 代理、负载均衡等转发服务普遍使用,并被写入 RFC 7239(Forwarded HTTP Extension` 标准之中。

  • $proxy_set_header

    已在排查问题中说明,可设置代理后 header

    proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
  • X-Real-IP

    通常好比X-Real-IP这一个自定义头部字段,一般被 HTTP 代理用来表示与它产生TCP 链接的设备 IP,这个设备多是其余代理,也多是真正的请求端,这个要看通过代理的层级次数或是是否始终将真实IP一路传下来。(牢记:任何客户端传上来的东西都是不可信的)

当多层代理或使用CDN时,若是代理服务器不把用户的真实IP传递下去,那么服务器将永远不可能获取到用户的真实IP。

0x03 用户的真实IP从何而来

  1. 宽带供应商提供独立IP
    好比家里电信宽带上网,电信给分配了公网ip,那么一个请求通过的ip路径以下:

    这种状况下,119.147.19.234 会把获得的116.1.2.3附加到头信息中传给10.168.0.0/32,所以这种状况下,咱们取得的用户ip则为:116.1.2.3
    若是119.110.0.0/16没有把116.1.2.3附加到头信息中传给业务服务器,业务服务器就只能取上上一级ip地址
  2. 宽带供应商不能提供独立IP

    宽带提供商没有足够的公网ip,分配的是个内网ip,好比长宽等小的isp。请求路径则可能以下:

    这种状况下获得的用户ip,就是211.162.78.1。 这种状况下,就可能出现一个ip对应有数十上百个用户的状况了

  3. 手机2g上网

    网络提供商无法直接提供ip给单个用户终端,以中国移动cmwap上网为例,所以请求路径可能为:

    这种状况下获得的用户ip,就是202.96.75.1。2008年的时候整个广东联通就三个手机上网的公网ip,所以这种状况下,同一ip出现数十万用户也是正常的。

  4. 有几万或数十万员工的公司
    这种也会出现来自同一ip的超多用户,可能达到几万人,但出口IP可能就那么几个。

0x04 NAT [Network Address Translation]

中文意思是网络地址转换,它容许一个总体机构以一个公用IP地址出如今Internet上。

NATOSI参考模型的网络层 (第3层), 它是一种把内部私有网络地址(IP地址)翻译成合法网络IP地址的技术。NAT可让那些使用私有地址的内部网络链接到Internet或其它IP网络上。NAT路由器在将内部网络的数据包发送到公用网络时,在IP包的报头把私有地址转换成合法的IP地址。

RFC1918 规定了三块专有的地址,做为私有的内部组网使用

  • A类:10.0.0.0 — 10.255.255.255 10.0.0.0/8
  • B类:172.16.0.0 — 172.31.255.255 172.16.0.0/12
  • C类:192.168.0.0 — 192.168.255.255 192.168.0.0/16

这三块私有地址自己是可路由的,只是公网上的路由器不会转发这三块私有地址的流量;当一个公司内部配置了这些私有地址后,内部的计算机在和外网通讯时,公司的边界路由会经过NAT或者PAT技术,将内部的私有地址转换成外网IP,外部看到的源地址是公司边界路由转换过的公网IP地址,这在某种意义上也增长了内部网络的安全性

这个过程是经过NAT中的本地址与全局地址映射条目来实现的,因此事先要在NAT路由器上配置这样的映射条目。


经过这种方式一个公网 IP 底下能够发私有的 IP 地址。


0x05 IPV6 来了?

写这篇文章的时候看到有个推送,表示阿里全面应用IPV6,这件事的意义还挺重大的

咱们知道,一段 IPv4 标准的 IP 地址,一共由 4 X 8 = 32 位二进制数字组成,理论上存在 2^32 个 IP 地址。等于 4,294,967,29642 亿多个 IPv4 的地址。

参考世界互联网用户统计报告,全球如今大概有4,208,571,287人在上网,也就是说已经快到ipv4地址设计的最大IP数了

不过不用担忧,前面提到的 NAT,让 IPv4 公网 IP 哪怕用完了也能凑合过。

到了 IPv6 ,相比 IPv4 最大的提高,就是位数大大增长,变成了 8 个 4 位的十六进制数字。也就是说有 2^128IPv6 地址。地球上的每粒沙子都分一个也管够

存储2^128字节理论上什么概念呢,在当今的量子水平下,假设计算设备可以操做在原子一级,每公斤质量可存储大约10的25次方bits,存储2的128次方的字节大约须要272 trillion = 2720000亿公斤

最后,周末愉快,北京联通已经支持ipv6了,我在望京测试,能够拿到 ipv6地址

相关文章
相关标签/搜索