经过代理或者代理服务器以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回 给客户端。但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息,用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址。 例如,当我们访问http://www.xxx.com/index.jsp/时,其实并不是我们浏览器真正访问到了服务器上的index.jsp文件,而是先由代理服务器去访问http://192.168.1.110:2046/index.jsp,代理服务器再将访问到的结果返回给我们的浏览器,因为是代理服务器去访问index.jsp的,所以index.jsp中通过request.getRemoteAddr()的方法获取的IP实际上是代理服务器的地址,并不是客户端的IP地址。
下面的方法在只有一级代理的情况下,可以保证获得客户端的真实IP地址:
- public String getIpAddr(HttpServletRequest request) {
- String ip = request.getHeader("x-forwarded-for");
- if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
- ip = request.getHeader("Proxy-Client-IP");
- }
- if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
- ip = request.getHeader("WL-Proxy-Client-IP");
- }
- if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
- ip = request.getRemoteAddr();
- }
- return ip;
- }
可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串Ip值,究竟哪个才是真正的用户端的真实IP呢?答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100
用户真实IP为: 192.168.1.110
程序实现如下:
- // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址
- public String getIpAddr(HttpServletRequest request) {
- String strClientIp = request.getHeader("x-forwarded-for");
- log.info("All the IP address string is: " + strClientIp);
- if(strClientIp == null || strClientIp.length() == 0 ||"unknown".equalsIgnoreCase(strClientIp))
- {
- strClientIp = request.getRemoteAddr();
- }else{
- StringList ipList = new StringList();
- BusiAcceptAction.SplitsString(strClientIp, ',' , ipList); // 拆分字符串,可直接用String.plit方法
- String strIp = new String();
- for(int index = 0; index < ipList.size(); index ++)
- {
- strIp = (String)ipList.get(index);
- if(!("unknown".equalsIgnoreCase(strIp)))
- {
- strClientIp = strIp;
- break;
- }
- }
- }
- return strClientIp;
- }
转自 http://blog.csdn.net/foamflower/archive/2009/10/29/4744862.aspx
像移动网关一样,iisforward这个ISAPI过滤器也会对request对象进行再包装,附加一些WLS要用的头信息。这种情况下,直接用request.getRemoteAddr()
是无法取到真正的客户IP的。
实际的iisforward附加头如下:
WL-Proxy-Client-IP=211.161.1.239
Proxy-Client-IP=211.161.1.239
X-Forwarded-For=211.161.1.239
WL-Proxy-Client-Keysize=
WL-Proxy-Client-Secretkeysize=
X-WebLogic-Request-ClusterInfo=true
X-WebLogic-KeepAliveSecs=30
X-WebLogic-Force-JVMID=-327089098
WL-Proxy-SSL=false
综上,正确作法如下:
private String getIpAddr() {
String ipAddress = null;
//ipAddress = this.getRequest().getRemoteAddr();
ipAddress = this.getRequest().getHeader("x-forwarded-for");
if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = this.getRequest().getHeader("Proxy-Client-IP");
}
if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = this.getRequest().getHeader("WL-Proxy-Client-IP");
}
if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = this.getRequest().getRemoteAddr();
if(ipAddress.equals("127.0.0.1")){
//根据网卡取本机配置的IP
InetAddress inet=null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress= inet.getHostAddress();
}
}
//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15
if(ipAddress.indexOf(",")>0){
ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));
}
}
return ipAddress;
}
相关推荐
Java提供了一种方式来实现UDP NAT穿透,通过创建一个服务器端和客户端应用程序,可以协助位于NAT后的设备之间建立直接通信。以下是实现这一技术的一些关键知识点: 1. **STUN(Traversal Using Relays around NAT)...
对于使用Java Server Pages (JSP) 的开发者来说,了解如何高效地获取客户端IP地址至关重要。本文将详细介绍几种在JSP环境中获取客户端IP地址的有效方法,并提供实际的代码示例。 #### 二、获取客户端IP地址的重要性...
客户端创建`Socket`对象,指定服务器的IP地址和端口号,然后获取输出流以发送数据。一旦数据被写出,服务器端就需要接收并解析这些数据。 在服务器端,我们需要创建一个`ServerSocket`来监听特定端口上的连接请求:...
客户端通过向代理服务器发送包含完整URL的GET请求来获取资源。 - 示例请求: ```http GET http://example.com/index.html HTTP/1.1 Host: example.com ``` - 代理服务器接收到请求后,将请求转发给目标服务器...
总之,Java UDP穿透技术是解决NAT环境下UDP通信问题的一种方法,它涉及到对网络环境的理解、UDP套接字的管理以及NAT穿透协议的实现。"Net Java UDP穿透技术之路2.zip"提供的资源对于想要深入研究这一领域的Java...
Java中的"stun4j"库是一个用于STUN和TURN(Traversal Using Relays around NAT)服务的客户端库,提供了处理NAT穿透所需的基本功能。开发者可以使用stun4j来创建STUN请求,解析响应,从而获取到必要的网络信息。 ...
Java实现的STUN客户端库,如stun4j,对于开发者来说是构建这类应用的关键工具。 **STUN协议工作原理** STUN协议通过向公共互联网上的STUN服务器发送请求,然后接收响应来工作。请求包含了源IP和端口信息,服务器会...
Java中可以使用开源库如JSTUN来实现STUN客户端,通过发送请求到STUN服务器并接收响应,从而得到自身公网信息。 2. **TURN协议**:当STUN无法穿透某些NAT时,TURN服务器起到了中继的作用,允许设备通过服务器进行...
"P2PServer"和"P2PClient"则代表了P2P网络的服务器端和客户端程序,它们利用前面的NAT穿透技术实现在NAT环境下的直接通信。 "stund_0.96_Aug13.gz"是一个名为STUN Daemon的软件包,版本为0.96,发布于2013年8月。...
STUN客户端是与STUN服务器交互的软件,用于获取关于自身网络连接的信息,如公网IP和端口。它发送请求到STUN服务器,然后服务器返回响应,包含客户端在NAT后面所映射的公网属性。这个过程称为“绑定请求”。 开源的...
STUN是一种简单的网络协议,其目的是允许客户端检测自己所处的NAT类型,并获取NAT为它分配的公网IP和端口,从而实现穿透NAT。 **STUN协议工作原理:** 1. **请求(Request)**:客户端向STUN服务器发送请求,包含一...
JSTUN(Java Simple Traversal Understanding NAT)是一个开源库,它实现了STUN(Simple Traversal of User Datagram Protocol Through NAT,简单用户数据报协议穿越NAT)协议,以帮助Java应用穿透NAT进行P2P通信。...
4. 数据代理:在某些特殊场景下,比如内网穿透,Java抓包转发可以用于构建数据通道,使得内网资源可以被外网访问。 总结,Java抓包转发技术是Java网络编程中的重要部分,它涉及到网络数据包的捕获、解析和定向传输...
首先,STUN(Session Traversal Utilities for NAT)服务器是一种帮助客户端检测其NAT类型并获取其公网IP和端口的方法。Java中可以使用开源库如JStun或libjingle来实现STUN协议。客户端通过发送请求到STUN服务器,...
当两个位于不同NAT后的设备试图通过UDP进行通信时,由于每个NAT都会重写IP和端口信息,它们无法直接识别对方的真实地址。传统的TCP穿透NAT方法,如TCP三次握手,由于其顺序性和可预测性,可以通过建立连接请求来找到...
本文将深入探讨如何利用Java的Socket编程实现服务端(Server)和客户端(Client)之间的通信,以及客户端与客户端之间的直接交互。我们将重点关注Swing库如何用于创建用户界面,以便可视化地展示通信过程。 首先,...
lanproxy是一款专为解决内网穿透问题而设计的开源工具,尤其适合个人电脑或服务器在局域网环境下的公网访问需求。它利用TCP流量转发技术,使得任何基于TCP的上层协议,如HTTP、SSH、RDP(远程桌面)等,都能通过...
UDP打洞技术是一种在NAT(网络地址转换)环境...在提供的"p2p"文件中,可能包含了实现上述功能的服务器和客户端程序,可能用C++、Python、Java等编程语言编写。分析这些代码可以帮助理解UDP打洞的具体实现步骤和逻辑。
在这个“clientFtp.rar”压缩包中,我们找到了一个名为“clientFtp”的项目,它是一个用Java实现的FTP客户端。这个客户端能够连接到FTP服务器,进行文件的上传、下载以及其他相关的操作。 在Java中实现FTP客户端,...
3. **映射地址获取**:通过STUN服务器,客户端可以获取到其公网IP和端口,这是穿透NAT的关键步骤,因为私有网络内的设备无法直接用公网地址与其他设备通信。 4. **服务器端实现**:JSTUN库不仅包含客户端API,还...