Server

[Network] X-Forwarded-For (XFF) 란 무엇일까?

lucy1215 2026. 3. 17. 15:58
728x90
반응형

 

이번 프로젝트를 진행하면서 통합 테스트 중 고객이 테스트를 하는 도중에 요청을 주셨다.

 

"제 로컬 PC로 접속했을 때랑 VPN을 연결해서 접속했을 때, 찍히는 IP 주소가 다른데 이게 정상인가요?
X-Forwarded-For 한번 확인 요청드립니다!"

 

 

 

이 요청을 보고 첫번째로 든 생각은 "VPN으로 접속했으면 IP 주소가 다른게 정상 아닌가?" 가 첫번째였고,

"근데 왜 정상이지?" 가 두번째였다.

 

나는 그냥 "VPN을 연결하면 VPN의 IP 주소로 접속되어서 IP 주소가 다르다" 만 알고있고

그 안에 자세한 내용, XFF 조차도 모르고 있었던 것이었다.

 

 

✅X-Forwarded-For (XFF) 란?

X-Forwarded-For 는 원래 요청을 보낸 클라이언트의 IP 주소를 전달하기 위한 HTTP 헤더이다.

 

보통 클라이언트와 서버 사이에 아래와 같은 중간 장비가 있을 때 사용된다. 

  • 프록시 서버
  • 로드밸런서
  • 리버스 프록시
  • VPN  게이트웨이
  • 웹 방화벽 (WAF)

이런 장비를 거쳐 서버에 요청이 들어오면,

서버 입장에서는 직접 연결한 대상이 최종 사용자가 아니라 중간 장비로 보일 수 있다.

 

이때 중간 장비가 원래 클라이언트 IP를 헤더에 담아서 넘겨주는데,

그 대표적인 값이 X-Forwarded-For 다.

 

 

✅소스코드

현재 IP를 구하는 코드가 이렇게 구현이 되어있다.

private String getIp() {
	HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
    	.getRequest();
    String ip = req.getHeader("X-FORWARDED-FOR");
    return ip == null ? req.getRemoteAddr() : ip;
}

 

 

코드 동작 방식

1. X-Forwarded-For 헤더가 있으면 그 값을 사용

2. 없으면 getRemoteAddr() 값을 사용

 

 

즉,

프록시나 VPN 같은 중간 장비가 실제 사용자 IP를 전달해주면 XFF를 사용하고,
그렇지 않으면 서버와 직접 연결된 클라이언트 주소를 사용하는 방식

 

 

 

getRemoteAddr() 만으로는 부족할 수 있는 이유

 

request.getRemoteAddr() 는 서버와 직접 TCP 연결을 맺은 상대의 IP를 반환한다.

 

중요한 점은 이 값이 항상 "실제 사용자 PC의 IP"를 뜻하지는 않는다는 것이다.

 

중간에 프록시나 VPN 장비가 있으면 서버는 그 장비와 통신하기 때문에,

getRemoteAddr() 는 사용자 IP가 아니라 중간 장비의 IP가 될 수 있다.

 

즉,

  • 중간 장비 없음 → getRemoteAddr() = 사용자 IP
  • 중간 장비 있음 → getRemoteAddr() = 프록시/VPN/게이트웨이 IP

 

 

✅로컬 접속과  VPN 접속에서 IP가 달라지는 이유

1. 로컬 PC에서 직접 접속하는 경우

사용자가 별도의 프록시나 VPN 없이 서버에 접속한다고 가정해보면,

사용자 PC    ---------------------->   서버

 

 

이 경우 서버가 직접 통신하는 대상은 사용자 PC 다.

 

따라서,

  • X-Forwarded-For 없음
  • getRemoteAddr() = 실제 접속한 사용자 IP

 

즉, 이 상황에서는 getRemoteAddr() 값이 곧 원격 사용자 IP라고 볼 수 있다.

 

 

2. VPN을 통해 접속하는 경우

이번에는 사용자가 VPN을 켠 상태에서 접속한다고 가정해보면,

 

사용자 PC   ---------------------------->   VPN  장비   --------------------------->   서버

 

 

이때 서버는 사용자 PC와 직접 통신하지 않는다.

서버가 직접 보는 대상은 VPN 장비다.

 

따라서,

  • getRemoteAddr() = VPN 게이트웨이 또는 내부 네트워크 장비 IP
  • X-Forwarded-For = 원래 사용자 ip가 전달될 수 있음

 

즉, VPN 환경에서는

서버 입장에서 "중간 장비를 통해 들어온 요청" 으로 보이기 때문에

직접 접속 때와 IP가 달라지는 것이 정상이다.

 

 

 

 

⚠️번외

1️⃣주의할 점 : X-Forwarded-For 를 무조건 믿으면 안된다.

 

여기서 중요한 포인트가 하나 있다.

 

X-Forwarded-ForHTTP 헤더이기 때문에,

신뢰할 수 없는 외부 요청에서는 클라이언트가 임의로 넣을 수도 있다.

 

즉, 모든 환경에서 무조건

req.getHeader("X-FORWARDED-FOR")

 

를 신뢰하면 안 된다.

 

 

신뢰 가능한 경우

  • 사내 프록시
  • 운영 중인 로드밸런서
  • 회사 VPN 게이트웨이
  • 신뢰 가능한 리버스 프록시

 

주의가 필요한 경우

  • 인터넷에서 직접 들어오는 요청
  • 프록시 신뢰 구간이 명확하지 않은 환경
  • 헤더 위변조 가능성이 있는 환경

 

실무에서는 보통

"신뢰할 수 있는 프록시가 추가한 XFF만 사용한다"

는 기준이 필요하다.

 

 

 

2️⃣X-Forwarded-For 에는 여러 IP가 들어올 수도 있다.

프록시를 여러 번 거치면 X-Forwarded-For 에는 IP가 하나만 들어오지 않을 수 있다.

 

X-Forwarded-For: client-ip, proxy1-ip, proxy2-ip

 

 

일반적으로는 맨 앞의 값이 원래 클라이언트 IP인 경우가 많다.

하지만 이것도 인프라 구성에 따라 다를 수 있으므로

운영 환경의 프록시 정책을 같이 확인해야 한다.

반응형