grassbl8d
grassbl8d

Reputation: 2139

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

Is there any way that I could get the original IP address of the client coming to the server? I can use request.getRemoteAddr(), but I always seem to get the IP of the proxy or the web server.

I would want to know the IP address that the client is using to connect to me. Is there anyway that I could get it?

Upvotes: 77

Views: 91948

Answers (12)

Deepak Bajaj
Deepak Bajaj

Reputation: 240

This is the complete solution, Just copy paste and run the code


import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

@WebServlet("/ipaddress")
public class GetIpAddressServlet extends HttpServlet {
    
    /**
     * Author : Deepak Bajaj
     */

    public static final long serialVersionUID = 1L;

    // Below code is just to get the VALID IP Address headers
    public static final String[] VALID_IP_HEADER_CANDIDATES = { 
            "X-Forwarded-For",
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "HTTP_VIA",
            "REMOTE_ADDR" };

    // To get the client's IP Address
    
    public static String GetIpAddressServlet(HttpServletRequest request) throws IOException, ServletException {
        
        for (String header : VALID_IP_HEADER_CANDIDATES) {
            String ip = request.getHeader(header);
            if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            }
        }
        return request.getRemoteAddr();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // Get the client's IP address
        String clientIP = GetIpAddressServlet(request);

        // Print or use the client's IP address as needed
        System.out.println("Client IP Address: " + clientIP);

        // You can send the IP address as a response to the client if needed
        response.getWriter().write("Client IP Address: " + clientIP);
    }

NOTE :- Now just try to access your application over the remote client's machine http://IPofMachineWheretheCodeisHosted:PORT/ipaddress you will get the ip address of the remote client

Upvotes: 0

Dilip K
Dilip K

Reputation: 81

request.getHeader("True-Client-IP")

it will return the client IP address

Upvotes: 0

whitebrow
whitebrow

Reputation: 2005

Why don't use a more elegant solution like this?

private static final List<String> IP_HEADERS = Arrays.asList("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR");

public static String getClientIpAddr(HttpServletRequest request) {
    return IP_HEADERS.stream()
        .map(request::getHeader)
        .filter(Objects::nonNull)
        .filter(ip -> !ip.isEmpty() && !ip.equalsIgnoreCase("unknown"))
        .findFirst()
        .orElseGet(request::getRemoteAddr);
}

Deduplicate your code!

Upvotes: 11

puppylpg
puppylpg

Reputation: 1220

Why I think we should try to get IP from header 'X-Forwarded-For' first? If you get from request.getRemoteAddr(), it could be client's real ip or last proxy's ip which forwards the request. Thus we can't tell which condition it belongs to. However, if 'X-Forwarded-For' is set into the header, client ip is bound to be the left-most part of what you get from it.

    /**
     * Try to get real ip from request:
     * <ul>
     *     <li>try X-Forwarded-For</li>
     *     <li>try remote address</li>
     * </ul>
     *
     * @param request    request
     * @return real ip or ""
     */
    private String tryGetRealIp(HttpServletRequest request) {
        // X-Forwarded-For: <client>, <proxy1>, <proxy2>
        // If a request goes through multiple proxies, the IP addresses of each successive proxy is listed.
        // This means, the right-most IP address is the IP address of the most recent proxy and
        // the left-most IP address is the IP address of the originating client.
        String forwards = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotBlank(forwards)) {
            // The left-most IP must be client ip
            String ip = StringUtils.substringBefore(forwards, ",");
            return ip;
        } else if (StringUtils.isNotBlank(request.getRemoteAddr())) {
            // this could be real client ip or last proxy ip which forwards the request
            return request.getRemoteAddr();
        }
        return "";
    }

Upvotes: 0

Bozho
Bozho

Reputation: 597144

request.getRemoteAddr() is the way. It appears your proxy changes the source IP. When some proxies do that they add the original IP in some custom http header. Use request.getHeaderNames() and request.getHeaders(name) and print all of them to see if there isn't anything of interest. Like X-CLIENT-IP (made that one up, but they look like this)

Upvotes: 10

Nitesh Chourasia
Nitesh Chourasia

Reputation: 1

InetAddress inetAddress = InetAddress.getLocalHost();
String ip = inetAddress.getHostAddress();

Upvotes: -8

craigforster
craigforster

Reputation: 2669

As this is usually a deployment concern, rather than an application concern, another approach would be to configure the application container appropriately. Once configured, the container takes care of inspecting the appropriate header and your application continues to use request.getRemoteAddr().

For example, in Tomcat you can use the Remote IP Valve. I would assume most application servers have similar functionality.

The container could also take care of understanding if your front-end load balancer is terminating SSL connections, forwarding the request to the app server over HTTP. This is important when your application needs to generate URLs to itself.

Upvotes: 7

Ali Hashemi
Ali Hashemi

Reputation: 3378

The best solution I've ever used

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;      
} 

Upvotes: 6

Emilio
Emilio

Reputation: 1044

"x-forwarded-for" request header contains the original client IP if using a proxy or a load balancer. But I think not all proxies/lb adds this header.

Here some java code to parse the header: http://www.codereye.com/2010/01/get-real-ip-from-request-in-java.html

If this header is not present then I would proceed as @Bozho suggests

Upvotes: 1

Srinivasu
Srinivasu

Reputation: 1235

String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null) {
            ipAddress = request.getHeader("X_FORWARDED_FOR");
            if (ipAddress == null){
                ipAddress = request.getRemoteAddr();
            }
        }

Upvotes: 0

Fareed Alnamrouti
Fareed Alnamrouti

Reputation: 32154

try this:

public static String getClientIpAddr(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.getHeader("HTTP_CLIENT_IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getRemoteAddr();  
        }  
        return ip;  
    }  

Upvotes: 120

time4tea
time4tea

Reputation: 2197

You cannot do this in a meaningful way.

The proxy may or may not add a proxied-for header, but in many cases this will be an internal only address anyway, so it will be meaningless to you. Most proxies at the edge of an organization are configured to reveal as little as possible about the internals of the network anyway.

What are you intending to use this information for?

Upvotes: 4

Related Questions