Post

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

Proxy / VPN

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

1
2
3
4
5
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를 append 하여 Origin src IP를 확인할 수 있도록 하는 “사실상의” 표준 헤더다.

1
2
3
4
5
6
7
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: 1.1.1.1, 2.2.2.2
ㄴ Tomcat 에서 수신하는 값은
    ㄴ X-Forwarded-For: 1.1.1.1, 2.2.2.2
    ㄴ X-Real-IP: 2.2.2.2
    ㄴ RemoteIp: 3.3.3.3 (별도 설정 없는 경우)

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

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

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
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
<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.