Post

Client IP 구하기 - X-Forwarded-For와 X-Real-IP

Proxy / VPN

X-Real-IP는 바로 직전 client의 IP를 나타낸다.

1
2
3
4
5
6
proxy\_set\_header X-Real-IP $remote\_addr; 설정에서 $remote\_addr이, nginx가 수신한 client IP를 의미한다.


User - Nginx - Tomcat 일 때, X-Real-IP는 User IP 가 된다.
User - Proxy - Nginx - Tomcat 일 때, X-Real-IP는 Proxy IP가 된다.

X-Forwarded-For는 3.3.3.3, 1.1.1.1 포맷이다

LB, Proxy, Cache Server 등을 거치면 srcIp가 변경되기 때문에 원래의 Client IP를 가져오기 위한 방법이 필요하다.

이를 위해 X-Forwarded-For 필드가 존재하며,

경로를 지날 때 마다 우측 끝에 하나 씩 IP를 추가 하여 Origin src IP를 확인할 수 있도록 하는 “사실상의” 표준 헤더다.

1
2
3
4
5
6
7
8
9
User(1.1.1.1)
ㄴ Proxy(2.2.2.2) - X-Forwarded-For: 1.1.1.1
ㄴ Nginx(3.3.3.3) - X-Forwarded-For: 2.2.2.2, 1.1.1.1
ㄴ Tomcat 에서 수신하는 값은
ㄴ X-Forwarded-For는 2.2.2.2, 1.1.1.1
ㄴ X-Real-IP는 2.2.2.2
ㄴ RemoteIp(별도 설정 없는 경우)는 3.3.3.3

tomcat에서 받을 때는, 보통 XFF 맨 앞에 있는 IP를 클라이언트로 가져오게 된다. (우측으로 확장되니 맨 좌측의 IP가 클라IP 일거라는 가정)

이러한 기능을 제대로 표준화한 헤더 Forwarded 이나 잘 쓰이지 않는다. XFF가 de-facto standar

X-Real-IP와 X-Forwarded-For 둘 다 변조 가능하다

case X-Real-IP:

그냥 Proxy 타면, Proxy의 IP로 set 된다.

case X-Forwarded-For:

유저가 임의로 헤더를 조작할 수 있으므로, 원래는 없어야하는 X-Forwarded-For 헤더를 추가하고 3.3.3.3을 지정해서 보내는 경우라면?

1
2
3
4
5
6
7
8
User - X-Forwarded-For: 3.3.3.3을 헤더에 추가하여 보낸다.
Proxy - X-Forwarded-For: 3.3.3.3, {User의 실제 IP}
Nginx
-
X-Forwarded-For: 3.3.3.3, {User의 실제 IP}, {Proxy의 IP}
Tomcat
ㄴ X-Forwarded-For의 맨 앞을 가져와 사용한다면 3.3.3.3을 client IP로 인식하게 됨.

참고) tomcat 에서 remoteIp를 읽어올 헤더를 변경하는 설정

1
2
3
Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="x-real-ip"/>
설정하게 되면 request.getRemoteAddr() 했을 때 X-REAL-IP 헤더에 있는 값을 읽어오게 된다.

https://tomcat.apache.org/tomcat-8.5-doc/api/org/apache/catalina/valves/RemoteIpValve.html

This post is licensed under CC BY 4.0 by the author.