서버의 인프라를 구성하는 방식은 정말 여러가지 방식이 있다. 단순히 포트만 열어두고 앱 서비스를 올리는 경우도 있지만, NGINX 및 AWS CloudFront 또는 Application Load Balancer 같이 앞단에 프록시 서버를 두는 경우가 있다.
(프록시 서버들)
이러한 경우 앱 서버 (WAS)는 유저가 즉각적으로 접속할 수 없고 리버스 프록시를 통해 접속하는데, 이 경우 서버서 찍히는 IP는 리버스 프록시 서버의 IP만 가져올 수밖에 없다.
이 문서에서는 관련 아이피를 어떻게 처리하고, 보안 방식에 대해서 알아보자.
이러한 문제를 해결하기 위해 사실상 표준해더인 X-Forwarded-For 만들게 된다.
(본 표준화된 해더는 Forwarded 이나 제대로 사용하지 않음.)
HTTP 헤더에 타고 있는 X-Forwarded-For를 통해 프록시 및 로드밸런서 아이피를 기록한다.
X-Forwarded-For: <client>, <proxy1>, <proxy2>
HTTP HEAD에 타고 있는 형태로 구성되며, client IP → Proxy Server1 → Proxy Server2 → … 순차적으로 추가되는 방식으로 구성된다.
이 설정은 각 프록시 서버별로 세팅이 필요하거나 자동으로 해더에 같이 넣어준다.
즉, 순차적으로 서버를 넘어갈때마다 서버에서 받은 아이피를 기록하는 해더가 있다보니 우리는 실제 아이피를 찾을 수 있다.
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 아이피를 아래와 같이 보낸다면?
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를 수집하는 행위는 매우 중요하다. 특히 보안 사고가 발생했을때 추적할 수 있는 키포인트 중 하나로 프록시 서버별 로그를 보관하더라도 결국 제대로된 아이피를 가지고 있는게 중요하다.
또한 각 인프라 세팅에 따라서도 서버에서 설정해주는 방식이 달라질 수 있으니 (왼쪽 또는 마지막 오른쪽) 으로 인프라 환경에 맞는 서비스 구축 방식이 중요하다.