본문 바로가기
프로그래밍/Java

Java로 Client IP 찾는 방법

by 더나개 블로그 2022. 5. 23.

Java로 개발을 하다 보면 로그인 이력을 남기거나 하는 상황에 Client IP를 데이터베이스에 Insert 하는 로직을 만들어야 하는 경우가 생길 수 있다.. 크게 2가지의 방법이 존재하는데 하나하나 설명해볼까 한다.


1. InetAddress

import java.net.InetAddress;
import java.net.UnknownHostException;

public static String getClientIP(HttpServletRequest req) throws UnknownHostException {
	InetAddress clientAddress = InetAddress.getLocalHost();
    	ip = clientAddress.getHostName() + "/" + address.getHostAddress();
    
    	return ip;
}

허나 위의 방식으로 개발을 하게 되면 로컬 서버에서 접속을 하였을 때 나의 Client IP는 잘 찾지만 서버에 배포하게 되면 Proxy 서버를 거치게 되면서 배포한 서버 IP가 Client로 잡혀 배포한 서버 IP가 나오게 된다.

 

위의 문제점에 대한 대안으로 Client IP를 구하는 표준

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

public static String getClientIp(HttpServletRequest req) {
	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.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
            ip = request.getHeader("X-RealIP"); 
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
            ip = request.getHeader("REMOTE_ADDR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
            ip = request.getRemoteAddr(); 
        }
        
        return ip;
}

사실상 Client IP를 구하는 표준이다. Client가 서버에 request를 보낼 때 request 헤더에 "X-Forwarded-For" 키로 

IP를 담아 보내게 된다.

 

이것도 문제점이라고 할 수도 있는... 한 가지 문제점이 존재하는데 서버에 배포된 서비스에서는 Client IP를 잘 찾지만 

로컬에서 접속을 하였을 때 IPv4 또는 IPv6으로 Client IP를 "0:0:0:0:0:0:0:1"을 잡게 되거나 "127.0.0.1"를 잡게 되는 상황이 생기게 된다.

그러므로 가장 이상적으로 IP를 찾는 방법은...

3. 혼합..

import java.net.InetAddress;
import java.net.UnknownHostException;

public static String getClientIp(HttpServletRequest request) throws UnknownHostException {
    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.getHeader("X-Real-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
        ip = request.getHeader("X-RealIP"); 
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
        ip = request.getHeader("REMOTE_ADDR");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
        ip = request.getRemoteAddr(); 
    }

    if(ip.equals("0:0:0:0:0:0:0:1") || ip.equals("127.0.0.1")) 
    {
        InetAddress address = InetAddress.getLocalHost();
        ip = address.getHostName() + "/" + address.getHostAddress();
    }

    return ip;
}

1번과 2번의 방법을 적절히 혼합하여 사용하는 방법이 될 수 있겠다.

 

3번과 같이 적절히 혼합하여 getClientIP라는 메서드로 모듈화 하여 사용하게 된다면 

로컬 서버로 접속하였을 때와 배포된 서버로 접속하였을 경우 적절하게 Client IP를 찾아올 수 있을 것이다...

댓글