보안걱정 없이 제대로 Real IP 가져오기

CloudJun·2023년 9월 21일
1

서론

서버의 인프라를 구성하는 방식은 정말 여러가지 방식이 있다. 단순히 포트만 열어두고 앱 서비스를 올리는 경우도 있지만, NGINX 및 AWS CloudFront 또는 Application Load Balancer 같이 앞단에 프록시 서버를 두는 경우가 있다.

(프록시 서버들)

이러한 경우 앱 서버 (WAS)는 유저가 즉각적으로 접속할 수 없고 리버스 프록시를 통해 접속하는데, 이 경우 서버서 찍히는 IP는 리버스 프록시 서버의 IP만 가져올 수밖에 없다.

이 문서에서는 관련 아이피를 어떻게 처리하고, 보안 방식에 대해서 알아보자.

X-Forwarded-For , Real-IP

이러한 문제를 해결하기 위해 사실상 표준해더인 X-Forwarded-For 만들게 된다.
(본 표준화된 해더는 Forwarded 이나 제대로 사용하지 않음.)

HTTP 헤더에 타고 있는 X-Forwarded-For를 통해 프록시 및 로드밸런서 아이피를 기록한다.

구조

X-Forwarded-For: <client>, <proxy1>, <proxy2>

HTTP HEAD에 타고 있는 형태로 구성되며, client IP → Proxy Server1 → Proxy Server2 → … 순차적으로 추가되는 방식으로 구성된다.

이 설정은 각 프록시 서버별로 세팅이 필요하거나 자동으로 해더에 같이 넣어준다.

  • AWS ELB → 자동으로 X-Forwarded-For 헤더가 추가되거나 새롭게 생성
  • NGINX → config에서 세팅이 필요하다.

즉, 순차적으로 서버를 넘어갈때마다 서버에서 받은 아이피를 기록하는 해더가 있다보니 우리는 실제 아이피를 찾을 수 있다.

앱 내에서 가져오기

const ip = (req.headers['x-forwarded-for'] as string) || (req.connection.remoteAddress as string);
// [111.111.111.111, 222.222.222.222, 133.133.133.133]

const ipv4 = ip.split(':')[0];
// 111.111.111.111

그런데 이렇게 하면 보안 문제가 발생한다.


중간에 위조하거나 처음부터 유저가 x-forwarded-for를 보내버리면?

이 글을 쓰게 된 직접적인 이유

처음부터 X-Forwarded-For 아이피를 아래와 같이 보낸다면?

curl -X POST https://localhost.com -H "X-Forwarded-For: 1.2.3.4, 11.22.33.44"

아까전 앱 내에서 가져오는 코드에서는 가장 왼쪽에 있는 것을 클라이언트 IP로 판단하기 때문에 나오는건 아래와 같다.

1.2.3.4

이 경우 클라이언트에서 전달하는 IP는 무력화되고 믿을 수 없는 IP만 찍힐수밖에 없고,

로그 시스템의 구성에도 관련 아이피를 WAS에 저장한다면 공격자의 아이피도 파악할 수 없는 형태로 저장된다.

어떻게 해결해야하는가?

HTTP headers and Classic Load Balancers - Elastic Load Balancing

aws 경우 X-Forwarded-For가 이미 있다면 맨 마지막에 클라이언트 IP를 추가한다.

그렇기에 AWS ELB만 사용한다면 맨 마지막 아이피만 사용한다면 클라이언트의 고유 IP를 얻을 수 있다.

예시)

[111.111.111.111 (해킹목적), 222.222.222.222(해킹목적), 121.123.134.231(AWS추가)]

그땐 맨 뒤에 있는 아이피를 가져오면 된다.

그러나 NGINX까지 포함되면 X-Forwarded-For는 프록시 아이피를 뒤에 추가하게 되니, 아래와 같은 구조로 바뀐다

[111.111.111.111 (해킹목적), 222.222.222.222(해킹목적), 121.123.134.231(AWS추가), 133.133.133.133(NGINX)]

이때 맨 뒤에 있는 아이피 가져오면 NGINX의 아이피를 가져오게 되니 사실상 유저의 아이피를 얻을 수 없게 된다.

이런 문제를 해결하기 위해 NGINX에서는 set_real_ip_from 라는 세팅 옵션을 제공한다.

이 기능은 신뢰할 수 있는 프록시 서버 목록만 믿겠다는 의미로, 그 전 프록시 서버로 날라오는 아이피는 모두 무시한다.

예시)

set_real_ip_from 133.133.133.133

133.133.133.133 바로 앞에 있는 아이피만 믿는다.

[121.123.134.231(AWS추가), 133.133.133.133(NGINX)]

aws에서 얻은 아이피 재가공 끝.


결론

유저의 IP를 수집하는 행위는 매우 중요하다. 특히 보안 사고가 발생했을때 추적할 수 있는 키포인트 중 하나로 프록시 서버별 로그를 보관하더라도 결국 제대로된 아이피를 가지고 있는게 중요하다.

또한 각 인프라 세팅에 따라서도 서버에서 설정해주는 방식이 달라질 수 있으니 (왼쪽 또는 마지막 오른쪽) 으로 인프라 환경에 맞는 서비스 구축 방식이 중요하다.

profile
짧고 굵게 살아가는 백엔드 개발자

0개의 댓글