应用获取客户端IP的3种形式
-
通过request.getRemoteAddr()
这是最官方的获取客户端IP的方法,但当请求经过代理服务器后,这个方法返回的是代理服务器的IP. 所以我们线上通过这个方法取到的是nginx的IP: 127.0.0.1request.getRemoteAddr()
-
通过X-Forwarded-For http头
X-Forwarded-For 不是在http协议里定义的,所以request的默认实现是不用X-Forwarded-For取IP的。最早是由Squid的开发引入的。 请求经过代理服务器后,代理服务器会把客户端IP和自己的IP放在X-Forwarded-For头中,并与逗号隔开。也就是说每经过一个代理服务器,这个头中会多加一个IP。 Web程序通过获取这个HTTP头来取得客户端的IP。 这是目前我们获取客户端IP的方法。也有一些代码服务器会用ORIG_CLIENT_IPpublic static String getRemoteIp(HttpServletRequest request) { String ip = null; if (request.getHeader("ORIG_CLIENT_IP") != null) { ip = request.getHeader("ORIG_CLIENT_IP"); } if (ip == null && request.getHeader("x-forwarded-for") != null) { ip = request.getHeader("x-forwarded-for"); if (ip != null) { ip = ip.split("\\s*,\\s*")[0]; } } if (ip == null) { ip = request.getRemoteAddr(); } return ip; }
-
通过程序来获取
并不是所有的代理服务器都会加X-Forwarded-For这个HTTP头。所以为了获取客户端真实的IP,有些网站会通过插件等形式来更准确的获取客户端IP。
webx中取客户端IP
-
为什么在webx中还是能通过request.getRemoteAddr()取到代理过的客户端IP?
在Webx中,当配置了ResourcesFilter后,在ResourcesFilter中会把request包装一下,并在包装类中重写了getRemoteAddr方法。重写后会加上从x-forwarded-for中取IP。
线上应用取不到IP的故障原因分析。
-
PE在改nginx时没有加x-forwarded-for的头,导致应用取不到客户端IP,取出来的是nginx代理机的IP,即127.0.0.1。 同时应用有对同一IP发送邮件数有限制,最后导致邮件发不出去。
-
当故障发生后,为什么内网绑转发平台无法重现问题?
内网绑转发平台后发出的请求,已经经过了代理服务器,并且该代理服务器已经为请求加上了x-forwarded-for的头,所以就算应用的nginx上没有加,应用取到的IP也不会是127.0.0.1。(虽然通过抓包工具看到转发平台加在x-forwarded-for头里的IP并不是真正客户端IP)
通过CSP引流模式做压测时,取客户端IP会受影响吗?
- CSP引渡压测只是通过proxy_pass把流量导到目标机上。而客户端IP只和x-forwarded-for头有关,所以引流压测不会影响取客户端IP。