镇远| 衡东| 安岳| 金寨| 宁城| 青田| 那坡| 河源| 台前| 全南| 沂水| 马关| 巢湖| 纳溪| 浦东新区| 辉县| 临猗| 荥经| 瓦房店| 阳春| 宣化区| 南山| 北流| 六盘水| 汉南| 绥化| 海晏| 乌兰察布| 宁德| 沁阳| 马祖| 金门| 临泉| 贺州| 新平| 曲水| 东山| 岳阳市| 饶阳| 兴仁| 大安| 高密| 皮山| 泸西| 满城| 金山屯| 南安| 砀山| 峡江| 滁州| 襄樊| 溧水| 怀远| 乌苏| 峨眉山| 武乡| 资中| 邯郸| 陕西| 达坂城| 农安| 李沧| 龙胜| 东港| 乳山| 成都| 临县| 嵩县| 滦县| 曲阜| 唐河| 叙永| 永顺| 炎陵| 安塞| 竹山| 遵义市| 内江| 呼图壁| 清苑| 垫江| 乌海| 安国| 吕梁| 织金| 阜阳| 五华| 阳西| 文县| 石门| 旺苍| 内丘| 富川| 福海| 绥化| 二连浩特| 营口| 独山| 黎平| 南城| 乌伊岭| 霍邱| 贾汪| 海城| 鄯善| 上蔡| 连山| 湖口| 盐津| 陇县| 永宁| 乾安| 曾母暗沙| 涞源| 太谷| 上饶县| 尖扎| 喀什| 建阳| 革吉| 崇明| 天柱| 南昌市| 龙海| 北仑| 涠洲岛| 柯坪| 台儿庄| 长治市| 金塔| 南召| 宁波| 临清| 海林| 斗门| 修文| 连云区| 江津| 淄博| 湘潭市| 龙岩| 安顺| 三水| 崇左| 湟源| 霍城| 梨树| 河曲| 肥西| 玉溪| 翁源| 潞城| 封丘| 望谟| 阜新蒙古族自治县| 双峰| 富川| 宁远| 畹町| 邹平| 通化县| 蒙城| 青田| 平房| 三亚| 绿春| 畹町| 平塘| 海南| 城口| 乡城| 惠阳| 武穴| 高邑| 满城| 玉田| 灞桥| 阜新市| 聂拉木| 泽州| 萧县| 仪征| 太白| 龙山| 潮州| 孟连| 长治县| 徐州| 康乐| 唐山| 沈丘| 贵州| 开封县| 铅山| 田林| 青河| 沁阳| 泸州| 连平| 大余| 仁怀| 城固| 武鸣| 九台| 钦州| 北戴河| 上蔡| 猇亭| 孙吴| 畹町| 苏尼特右旗| 察隅| 呼兰| 常德| 叶城| 洮南| 临猗| 阿拉尔| 太湖| 大田| 南华| 镶黄旗| 和政| 兰西| 拉孜| 南山| 罗平| 景泰| 普宁| 金州| 扎鲁特旗| 下花园| 三门| 长岭| 临湘| 盐城| 康乐| 同德| 高州| 久治| 衢江| 彭山| 万荣| 塔什库尔干| 通城| 宣化区| 射洪| 郏县| 泽普| 景洪| 定襄| 聂拉木| 正宁| 吉利| 曲沃| 武山| 枝江| 兴隆| 盐都| 周至| 沂水| 通许| 临淄| 盱眙| 六合论坛
|
|
51CTO旗下网站
|
|
移动端

服务器如何获取真实客户端 IP

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

作者:测试账号来源:键盘侠之路|2018-12-19 10:31

 0x01 先查个问题

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

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

  • getenv('HTTP_CLIENT_IP')
  • getenv('HTTP_X_FORWARDED_FOR')
  • getenv('REMOTE_ADDR')
  • filter_var($remote_ip, FILTER_VALIDATE_IP)
  • 已经依次获取并过滤
  • 固程序没有任何问题,往上发散

2.是否反向代理

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

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

  1. # 本机IPifconfig | grep -A 1 "en" | grep broadcast | cut -d " " -f 2 
  2. # 外网IPcurl --silent http://icanhazip.com.jianshenfang.net 
  3. 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/16 段 在nginx处打印$remote_addr,并在server_name添加当前机器ip,分别以负载均衡IP与本地IP做测试,最终确定问题出现在负载均衡服务器出现异常

检查与80端口建立连接目标都有谁

先拿到我本地内网外网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

  1. 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路径如下:

  1. 192.168.0.1 (用户) –>  
  2.   192.168.0.1/116.1.2.3 (路由器的局域网ip及路由器得到的电信公网ip)–>  119.110.0.0/16 (负载均衡服务器)–>  10.168.0.0/32  (业务处理服务器) 

这种情况下,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。请求路径则可能如下:

  1. 192.168.0.1 (用户) –>  
  2.   192.168.0.1/10.0.1.2(路由器的局域网ip及路由器得到的运营商内网ip)–>  211.162.78.1  (网络运营商长城宽带的公网ip) 
  3.   119.110.0.0/16 (负载均衡服务器)–>  10.168.0.0/32  (业务处理服务器) 

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

3.手机2g上网

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

  1. 手机(手机上没法查看到ip)–>  
  2.   10.0.0.172(cmwap代理服务器ip)–>  10.0.1.2(移动运营商内网ip)–>  202.96.75.1(移动运营商的公网ip)–>  119.110.0.0/16 (负载均衡服务器)–>  10.168.0.0/32  (业务处理服务器) 

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

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

0x04 NAT [Network Address Translation]

中文意思是网络地址转换,它允许一个整体机构以一个公用IP地址出现在Internet上。顾名思义,它是一种把内部私有网络地址(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

0x05 IPV6 来了?

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

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

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

不过不用担心,前面提到的 NAT地址交换技术,让 IPv4 公网 IP 哪怕用完了也能凑合过。

【编辑推荐】

  1. 为什么说Kubernetes是新的应用服务器?
  2. 游戏服务器开发如何组织业务逻辑的处理结构?
  3. Spring Boot-实现Undertow服务器同时支持HTTP2、HTTPS
  4. Python 绝技 —— TCP 服务器与客户端
  5. 实战讲解:如何用Python搭建一个服务器
【责任编辑:武晓燕 TEL:(010)68476606】


点赞 0
分享:
大家都在看
猜你喜欢
24H热文
一周话题
本月最赞

读 书 +更多

SQL应用与开发标准教程

本书主要介绍了SQL的数据库应用和开发技术,内容涉及关系数据库和SQL概述,SQL环境,SQL对于数据表的操作,数据库查询知识,SQL数据的修改...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊
派镇 郭庄子齐家胡同 山嘴头 獐獏乡 蕃后街
牟定 晓月苑小区 大尚屯镇 莲溪市场 外环北路
澳门威尼斯人网站 PC蛋蛋 葡京国际 葡京赌场注册 威尼斯人网上娱乐
新濠天地博彩 拉斯维加斯线上网址 葡京官网 威尼斯人注册 澳门银河场网址
拉斯维加斯线上网址 番摊游戏娱乐 澳门大富豪官网平台 澳门威尼斯人官网 澳门葡京国际
澳门威尼斯人备用网址 威尼斯人赌城网址 ag电子游戏哪个最会爆 轮盘娱乐 星际网址官网平台