`
kavy
  • 浏览: 888500 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java实现穿透代理获取客户端真实ip

 
阅读更多

 

  经过代理或者代理服务器以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的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地址:

 

[java] view plaincopy
 
  1. public String getIpAddr(HttpServletRequest request) {  
  2.          String ip = request.getHeader("x-forwarded-for");  
  3.          if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
  4.              ip = request.getHeader("Proxy-Client-IP");  
  5.          }  
  6.          if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
  7.              ip = request.getHeader("WL-Proxy-Client-IP");  
  8.          }  
  9.          if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
  10.             ip = request.getRemoteAddr();  
  11.         }  
  12.         return ip;  
  13.     }  



 


可是,如果通过了多级反向代理的话,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

程序实现如下:

 

[java] view plaincopy
 
  1. // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址  
  2.     public String getIpAddr(HttpServletRequest request) {  
  3.     String strClientIp = request.getHeader("x-forwarded-for");  
  4.     log.info("All the IP address string is: " + strClientIp);  
  5.     if(strClientIp == null || strClientIp.length() == 0 ||"unknown".equalsIgnoreCase(strClientIp))  
  6.     {  
  7.         strClientIp = request.getRemoteAddr();  
  8.     }else{  
  9.         StringList ipList = new StringList();  
  10.         BusiAcceptAction.SplitsString(strClientIp, ',' , ipList); // 拆分字符串,可直接用String.plit方法  
  11.         String strIp = new String();  
  12.         for(int index = 0; index < ipList.size(); index ++)  
  13.         {  
  14.             strIp = (String)ipList.get(index);  
  15.             if(!("unknown".equalsIgnoreCase(strIp)))  
  16.             {  
  17.                 strClientIp = strIp;  
  18.                 break;  
  19.             }  
  20.         }  
  21.     }  
  22.   
  23.     return strClientIp;  
  24.     }  

 

 

转自 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技术

    Java提供了一种方式来实现UDP NAT穿透,通过创建一个服务器端和客户端应用程序,可以协助位于NAT后的设备之间建立直接通信。以下是实现这一技术的一些关键知识点: 1. **STUN(Traversal Using Relays around NAT)...

    jsp获取客户端IP地址的方法.docx

    对于使用Java Server Pages (JSP) 的开发者来说,了解如何高效地获取客户端IP地址至关重要。本文将详细介绍几种在JSP环境中获取客户端IP地址的有效方法,并提供实际的代码示例。 #### 二、获取客户端IP地址的重要性...

    java实现tcp客户端发送服务端解析程序

    客户端创建`Socket`对象,指定服务器的IP地址和端口号,然后获取输出流以发送数据。一旦数据被写出,服务器端就需要接收并解析这些数据。 在服务器端,我们需要创建一个`ServerSocket`来监听特定端口上的连接请求:...

    HTTP代理穿透方法

    客户端通过向代理服务器发送包含完整URL的GET请求来获取资源。 - 示例请求: ```http GET http://example.com/index.html HTTP/1.1 Host: example.com ``` - 代理服务器接收到请求后,将请求转发给目标服务器...

    Net Java UDP穿透技术之路2.zip

    总之,Java UDP穿透技术是解决NAT环境下UDP通信问题的一种方法,它涉及到对网络环境的理解、UDP套接字的管理以及NAT穿透协议的实现。"Net Java UDP穿透技术之路2.zip"提供的资源对于想要深入研究这一领域的Java...

    NAT探测 使用stun协议 java和python版本

    Java中的"stun4j"库是一个用于STUN和TURN(Traversal Using Relays around NAT)服务的客户端库,提供了处理NAT穿透所需的基本功能。开发者可以使用stun4j来创建STUN请求,解析响应,从而获取到必要的网络信息。 ...

    STUN协议的java实现,stun4j

    Java实现的STUN客户端库,如stun4j,对于开发者来说是构建这类应用的关键工具。 **STUN协议工作原理** STUN协议通过向公共互联网上的STUN服务器发送请求,然后接收响应来工作。请求包含了源IP和端口信息,服务器会...

    Java NAT穿越

    Java中可以使用开源库如JSTUN来实现STUN客户端,通过发送请求到STUN服务器并接收响应,从而得到自身公网信息。 2. **TURN协议**:当STUN无法穿透某些NAT时,TURN服务器起到了中继的作用,允许设备通过服务器进行...

    真正好用的nat穿透源代码,附送STUN检测代码

    "P2PServer"和"P2PClient"则代表了P2P网络的服务器端和客户端程序,它们利用前面的NAT穿透技术实现在NAT环境下的直接通信。 "stund_0.96_Aug13.gz"是一个名为STUN Daemon的软件包,版本为0.96,发布于2013年8月。...

    STUN客户端服务器源代码,仅供参考

    STUN客户端是与STUN服务器交互的软件,用于获取关于自身网络连接的信息,如公网IP和端口。它发送请求到STUN服务器,然后服务器返回响应,包含客户端在NAT后面所映射的公网属性。这个过程称为“绑定请求”。 开源的...

    Java 穿越NAT方案 JSTUN.7z

    STUN是一种简单的网络协议,其目的是允许客户端检测自己所处的NAT类型,并获取NAT为它分配的公网IP和端口,从而实现穿透NAT。 **STUN协议工作原理:** 1. **请求(Request)**:客户端向STUN服务器发送请求,包含一...

    基于java的穿越NAT方案 JSTUN.zip

    JSTUN(Java Simple Traversal Understanding NAT)是一个开源库,它实现了STUN(Simple Traversal of User Datagram Protocol Through NAT,简单用户数据报协议穿越NAT)协议,以帮助Java应用穿透NAT进行P2P通信。...

    java抓包转发详细资料

    4. 数据代理:在某些特殊场景下,比如内网穿透,Java抓包转发可以用于构建数据通道,使得内网资源可以被外网访问。 总结,Java抓包转发技术是Java网络编程中的重要部分,它涉及到网络数据包的捕获、解析和定向传输...

    JAVA穿越NAT

    首先,STUN(Session Traversal Utilities for NAT)服务器是一种帮助客户端检测其NAT类型并获取其公网IP和端口的方法。Java中可以使用开源库如JStun或libjingle来实现STUN协议。客户端通过发送请求到STUN服务器,...

    UDP穿透NAT的原理与实现(附源代码).rar

    当两个位于不同NAT后的设备试图通过UDP进行通信时,由于每个NAT都会重写IP和端口信息,它们无法直接识别对方的真实地址。传统的TCP穿透NAT方法,如TCP三次握手,由于其顺序性和可预测性,可以通过建立连接请求来找到...

    服务端和客服端直接和客户端与客户端之间通信

    本文将深入探讨如何利用Java的Socket编程实现服务端(Server)和客户端(Client)之间的通信,以及客户端与客户端之间的直接交互。我们将重点关注Swing库如何用于创建用户界面,以便可视化地展示通信过程。 首先,...

    lanproxy是一个将局域网个人电脑服务器代理到公网的内网穿透工具

    lanproxy是一款专为解决内网穿透问题而设计的开源工具,尤其适合个人电脑或服务器在局域网环境下的公网访问需求。它利用TCP流量转发技术,使得任何基于TCP的上层协议,如HTTP、SSH、RDP(远程桌面)等,都能通过...

    udp 打洞示例代码 包含服务器 客户端

    UDP打洞技术是一种在NAT(网络地址转换)环境...在提供的"p2p"文件中,可能包含了实现上述功能的服务器和客户端程序,可能用C++、Python、Java等编程语言编写。分析这些代码可以帮助理解UDP打洞的具体实现步骤和逻辑。

    clientFtp.rar_FTP CLIENT_ftp java_java ftp

    在这个“clientFtp.rar”压缩包中,我们找到了一个名为“clientFtp”的项目,它是一个用Java实现的FTP客户端。这个客户端能够连接到FTP服务器,进行文件的上传、下载以及其他相关的操作。 在Java中实现FTP客户端,...

    基于Java的穿越NAT方案 JSTUN.zip

    3. **映射地址获取**:通过STUN服务器,客户端可以获取到其公网IP和端口,这是穿透NAT的关键步骤,因为私有网络内的设备无法直接用公网地址与其他设备通信。 4. **服务器端实现**:JSTUN库不仅包含客户端API,还...

Global site tag (gtag.js) - Google Analytics