Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get real client IP in a Servlet [duplicate]

I'm having some trouble with a simple problem. I would get the real client IP inside an HTTPServlet.

Since now I used:

request.getRemoteAddr()

But now it returns a false IP. eg: xxx.xxx.xxx.50 but my IP is something like xxx.xxx.xxx.159. (checked at http://whatismyipaddress.com/).

Now I tried to use:

request.getHeader("X-Forwarded-For")

It returns NULL.

I also took a probe with the following class:

public class IpUtils {

public static final String _255 = "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
public static final Pattern pattern = Pattern.compile("^(?:" + _255 + "\\.){3}" + _255 + "$");

public static String longToIpV4(long longIp) {
    int octet3 = (int) ((longIp >> 24) % 256);
    int octet2 = (int) ((longIp >> 16) % 256);
    int octet1 = (int) ((longIp >> 8) % 256);
    int octet0 = (int) ((longIp) % 256);

    return octet3 + "." + octet2 + "." + octet1 + "." + octet0;
}

public static long ipV4ToLong(String ip) {
    String[] octets = ip.split("\\.");
    return (Long.parseLong(octets[0]) << 24) + (Integer.parseInt(octets[1]) << 16)
            + (Integer.parseInt(octets[2]) << 8) + Integer.parseInt(octets[3]);
}

public static boolean isIPv4Private(String ip) {
    long longIp = ipV4ToLong(ip);
    return (longIp >= ipV4ToLong("10.0.0.0") && longIp <= ipV4ToLong("10.255.255.255"))
            || (longIp >= ipV4ToLong("172.16.0.0") && longIp <= ipV4ToLong("172.31.255.255"))
            || longIp >= ipV4ToLong("192.168.0.0") && longIp <= ipV4ToLong("192.168.255.255");
}

public static boolean isIPv4Valid(String ip) {
    return pattern.matcher(ip).matches();
}

public static String getIpFromRequest(HttpServletRequest request) {
    String ip;
    boolean found = false;
    if ((ip = request.getHeader("x-forwarded-for")) != null) {
        StringTokenizer tokenizer = new StringTokenizer(ip, ",");
        while (tokenizer.hasMoreTokens()) {
            ip = tokenizer.nextToken().trim();
            if (isIPv4Valid(ip) && !isIPv4Private(ip)) {
                found = true;
                break;
            }
        }
    }

    if (!found) {
        ip = request.getRemoteAddr();
    }

    return ip;
}
}

It also returned the xxx.xxx.xxx.50 IP. :(

Now I don't know how to get the real client IP. If somebody knows the solution please make an answer.

like image 383
TAR515 Avatar asked Apr 23 '13 07:04

TAR515


People also ask

How do we get the IP address of a client in a servlet?

In Java, you can use HttpServletRequest. getRemoteAddr() to get the client's IP address that's accessing your Java web application.

How do I get the remote address of a client in servlet?

Methods to get client IP address in a servlet They are as follows: HttpServletRequest. getRemoteAddr(): This method returns the internet address of the client sending the request. HttpServletRequestgetRemoteHost(): This returns the host name of the client sending the request.

How do you find out what client machine is making a request to your servlet?

How do you find out what client machine is making a request to your servlet ? The ServletRequest class has functions for finding out the IP address or host name of the client machine. getRemoteAddr() gets the IP address of the client machine and getRemoteHost() gets the host name of the client machine.


3 Answers

I suppose that your problem is that you are running server somewhere in local network, so you get your IP in that network. However when you are trying to use online service that discovers your IP address your IP is the IP of your service provider's router or something like this. Using request.getRemoteAddr() is correct. This is what such services do and they do not have other facilities.

like image 194
AlexR Avatar answered Oct 01 '22 11:10

AlexR


When you have NAT (Network Address Translation) device before your servlet container request.getRemoteAddr() returns the address of NAT , since it initiate a new connection.

To solve your problem you should configure you NAT to send in a header the IP of the original client. Then, to take the header from the request. In case you configure in NAT X-Forwarded-For header use this code: request.getHeader("X-Forwarded-For")

You function is correct, you can use it when you configure NAT.

like image 24
Michael Avatar answered Oct 01 '22 13:10

Michael


Java

String ip = request.getRemoteAddr();
if (ip.equalsIgnoreCase("0:0:0:0:0:0:0:1")) {
    InetAddress inetAddress = InetAddress.getLocalHost();
    String ipAddress = inetAddress.getHostAddress();
    ip = ipAddress;
}
model.addAttribute("IP", ip);

JSP <span><B>IP : <c:out value="${IP}" /></B></span> // Spring MAV

JSP

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"   pageEncoding="ISO-8859-1"%>
<%@ page import="java.net.InetAddress" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Displays Client IP Address</title>
</head>
<body>
<%
    // paste above java code 
out.println("<br><B>Clients IP : </B>"+ip);
%>
<span><br>Local Host  : <%= request.getRemoteAddr() %></span>
<span><br>ServerPort  : <%= request.getServerPort() %></span>
<span><br>Path        : <%= request.getRequestURI()%></span>
</span>
</body>
</html>

If the jsp is deployed in local server and accessing this jsp returns 0:0:0:0:0:0:0:1. If accessing the application locally with ip then it returns IP.

RESTful Web Services with Jersey

@javax.ws.rs.Path("/ip")
public class GetIPInfo {

    @GET    @Produces(MediaType.TEXT_PLAIN) 
    public Response getIP(@Context javax.servlet.http.HttpServletRequest request) throws UnknownHostException { 

        String remoteHost = request.getRemoteHost();
        String remoteAddr = request.getRemoteAddr();
        if (remoteAddr.equals("0:0:0:0:0:0:0:1")) {
            InetAddress localip = java.net.InetAddress.getLocalHost();
            remoteAddr = localip.getHostAddress();
            remoteHost = localip.getHostName();
        }
        int remotePort = request.getRemotePort();

        String msgoutput = remoteHost + " (" + remoteAddr + " : " + remotePort + ")";
        return Response.status(200).entity(msgoutput).build(); 
    }
}

using JavaScript to find IP

like image 35
Yash Avatar answered Oct 01 '22 12:10

Yash