클라우드와 K8S 사용이 많아지면서 Load Balancer나 Proxy 를 사용하는 환경이 너무나 당연하게 되었다. 서비스에서 클라이언트의 IP 정보를 기반으로 비즈니스를 처리하고자 할 때, 클라이언트의 HTTP Request 가 네트워크 상의 수많은 게이트웨이와 LB, Proxy 서버들을 경유한 이후에야 서비스 서버로 수신되게 되고, 이 때 HTTP Header의 여러 필드값이 최초 발신지에서 보낸 값과 다르게 서버에 도착하게 된다.
다음은 nginx.conf 기본 설정값 중 log format과 관련된 항목을 발췌한 내용이다.
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
클라이언트의 IP가 remote_addr 에 저장되는데, LB 나 Proxy를 경유하게 되면서 remote_addr에는 Nginx에 Request를 전달하는 마지막 장비의 IP가 저장된다. 그러면 이 때 클라이언트 IP는 어디에 저장될까?
그것은 바로 X-Forwarded-For 헤더이다. 만일 X-Forwarded-For 헤더가 이미 값이 존재한다면 다음과 같이 ","를 추가하여 IP 주소를 덧붙인다.
X-Forwarded-For: 10.0.1.100, 20.0.2.200
Nginx의 기본 설정을 살펴보면 다음과 같은은 프록시 설정을 확인할 수 있고, 위 내용과 동일한 동작을 하게 된다.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_add_x_forwarded_for 이외에 http_x_forwarded_for 를 사용할 수도 있는데, 이 때는 클라이언IP 하나만 X-Forwarded-For 헤더에 설정된다.
결국 기본 설정인 proxy_add_x_forwarded_for 를 사용하게 되면 웹서비스에 사용자의 Request가 경유해 온 게이트웨이 목록을 포함하는 IP 정보 (10.0.0.1, 20.0.2.2, 192.168.21.4, 실제클라이언트아이피, nginxIP) 를 확인할 수 있게 된다.
만일 클라이언트IP 하나만 웹서비스로 전달하고자 할 경우, 다음과 같이 한다.
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
https://www.nginx.com/resources/wiki/start/topics/examples/full/
Nginx의 Forwarded 관련 다양한 설정에 대해 보다 더 자세히 확인하려면 다음 페이지를 참조할 수 있다.
https://www.nginx.com/nginx-wiki/build/dirhtml/start/topics/examples/forwarded/
이렇게 다양한 헤더 설정등을 활용하여 nginx 로깅시 활용법 예시는 다음과 같다.
https://zetawiki.com/wiki/Nginx_%EB%A1%9C%EA%B7%B8_%ED%98%95%EC%8B%9D
HTTP Request에서 client ip 정보를 가져오기 위한 서버 코드의 대표적인 예시는 다음과 같다.
주로 자바/스프링에서 사용하는 코드이다.
public static String getClientIP(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null) {
ip = request.getRemoteAddr();
}
return ip;
}
코드에서 보면 XFF 헤더를 우선 참조하고, 순서에 따라 수신된 헤더의 필드들을 확인한다.
따라서 통상적으로 Nginx에서도 XFF 의 설정을 먼저 해주면 될 것 같다.
방문해 주셔서 감사합니다!
정보가 도움이 되셨다면
로그인하지 않아도 누룰 수 있는
아래의 ♡ (하트) 를 꾹~ 눌러주세요 ♥♥♥
'IT > Infra Dev' 카테고리의 다른 글
리눅스 시스템과 컨테이너 리소스 모니터링 (1) | 2024.08.16 |
---|