Notice
Recent Posts
Recent Comments
Link
혜야의 코딩스토리
[Java] 클라이언트 IP 가져오기: Apache 웹서버와 리버스 프록시 환경에서 본문
1. 문제 발견
접속 IP에 따라 접근을 허용/차단하는 기능을 개발하면서 이상한 점을 발견했습니다.
✅ 초기 코드
import javax.servlet.http.HttpServletRequest;
request.getRemoteAddr();
❌ 예상과 다른 결과
어떤 IP로 접속하든 항상 같은 IP가 찍혔습니다. 예를 들어:
99.1.99.2 - - [07/Mar/2025:13:01:03 +0900] "HEAD / HTTP/1.1" 200 - "-" "-"
Apache 웹서버의 로그에서도 클라이언트 IP가 아닌 99.1.99.2만 기록되었습니다.
2. 원인 분석: 리버스 프록시와 로드 밸런서
현재 우리는 리버스 프록시와 로드 밸런서를 사용 중이므로, 요청이 여러 장비를 거쳐 들어옵니다.
🔍 원인
- 실제 클라이언트는 X-Forwarded-For 같은 헤더에 IP를 포함해서 요청을 보냅니다.
- 하지만 Apache 웹서버는 마지막으로 요청을 보낸 장비(리버스 프록시)의 IP만 기록합니다.
- 따라서, 99.1.99.2는 리버스 프록시의 내부 IP일 가능성이 큽니다.
❓ Apache는 왜 X-Forwarded-For을 로그에 기록하지 않을까?
기본적으로 Apache의 access_log는 클라이언트의 IP만 기록합니다. 따라서 설정을 변경하지 않으면 리버스 프록시의 IP만 남습니다.
✅ 해결 방법: LogFormat 수정
Apache 로그에 실제 클라이언트 IP를 남기려면 LogFormat을 수정해야 합니다.
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
이렇게 설정하면 X-Forwarded-For 값이 로그에 기록됩니다.
3. 해결 방법: 클라이언트 IP 가져오기
✅ 수정된 코드
public static String getRemoteAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.isEmpty()) {
ip = request.getRemoteAddr();
} else {
// X-Forwarded-For에 여러 개의 IP가 있을 수 있으므로 첫 번째 IP를 선택
String[] remoteAddrArray = ip.split(",");
ip = remoteAddrArray[0].trim();
// 포트번호가 포함되어 있으면 제거
if (ip.contains(":")) {
ip = ip.split(":")[0];
}
}
return ip;
}
⚠️ 주의할 점
이 방식은 리버스 프록시나 로드 밸런서가 X-Forwarded-For 헤더를 올바르게 설정한 경우에만 정상적으로 동작합니다.
예를 들어, X-Forwarded-For 값이 다음과 같이 들어올 수 있습니다:
192.168.0.1, 99.1.99.2
이 경우, 첫 번째 IP(192.168.0.1)가 실제 클라이언트 IP이므로 이를 추출해야 합니다.
4. 결론
- 리버스 프록시나 로드 밸런서를 사용하면 request.getRemoteAddr()는 실제 클라이언트가 아니라 프록시 서버의 IP를 반환함.
- 클라이언트 IP를 정확하게 가져오려면 X-Forwarded-For 헤더를 확인해야 함.
- Apache 로그에도 클라이언트 IP를 기록하려면 LogFormat 설정을 수정해야 함.
'꿈 : 멋진 개발자 🧸 > Java' 카테고리의 다른 글
[Spring] JMeter 사용법 - JMeter란?, 테스트 사용법 (0) | 2023.11.01 |
---|---|
[Spring] spring MVC redirect시 https -> http로 요청되는 문제 (0) | 2023.10.17 |
[Spring] Interceptor 인터셉터 (로그인 세션 체크 Interceptor로 처리하기) (0) | 2022.10.04 |
[Spring] @RequestBody / @ResponseBody 어노테이션이란? (0) | 2022.10.01 |
[Spring] AOP 관점 지향 프로그래밍 (0) | 2022.09.30 |