모든 접속 로그의 IP가 127.0.0.1로 찍힌 이유
문제 발생
접근 로그와 애플리케이션이 남기는 클라이언트 IP가 전부 같았습니다.
127.0.0.1 - - [.. ] "GET /posts HTTP/1.1" 200속도 제한과 어뷰징 차단이 모든 사용자를 한 IP로 취급해 무용지물이었습니다.
원인 분석
nginx가 보는 것은 실제 클라이언트가 아닙니다. 앞단에 CDN이나 로드밸런서가 있으면 TCP 연결의 상대는 그 프록시이고, 원래 클라이언트 주소는 X-Forwarded-For 같은 헤더 값으로만 전달됩니다.
nginx에는 이걸 위한 모듈이 있습니다 — ngx_http_realip_module은 클라이언트 주소와 선택적으로 포트를 지정된 헤더 필드로 전달된 값으로 바꾸는 데 사용됩니다.
다만 헤더는 클라이언트가 마음대로 보낼 수 있는 값입니다. 그래서 신뢰 목록이 함께 있습니다 — set_real_ip_from은 올바른 대체 주소를 보낸다고 알려진 신뢰하는 주소를 정의합니다. 이 목록에 있는 주소에서 온 요청에서만 헤더가 반영되므로, 아무나 X-Forwarded-For를 위조해 다른 사람 IP로 위장할 수 없습니다.
체인 처리 방식도 정해져 있습니다 — 재귀 검색이 꺼져 있으면 헤더의 마지막 주소로 대체하고, 켜져 있으면 마지막 비신뢰 주소로 대체합니다.
해결 방안
- 신뢰하는 프록시 대역과 헤더를 지정합니다.
set_real_ip_from 10.0.0.0/8; # 내부 로드밸런서
set_real_ip_from 172.18.0.0/16; # Docker 네트워크
real_ip_header X-Forwarded-For;
real_ip_recursive on;-
신뢰 목록을 넓히지 않습니다.
set_real_ip_from 0.0.0.0/0은 위조를 전면 허용하는 설정입니다 — 속도 제한·차단·감사 로그가 전부 무력해집니다. -
CDN을 쓴다면 그 대역만 신뢰합니다. 제공사가 공개하는 IP 목록을 주기적으로 갱신합니다.
-
애플리케이션도 같은 규칙을 씁니다. Node/Next 앱이
X-Forwarded-For를 직접 파싱한다면 nginx와 판단이 어긋날 수 있습니다 — nginx가 이미 바꿔준$remote_addr를X-Real-IP로 넘기고 앱은 그것만 믿는 편이 단순합니다. -
기본값을 확인합니다.
real_ip_header의 기본값은X-Real-IP이고real_ip_recursive는off입니다 — 설정을 생략하면 의도와 다르게 동작할 수 있습니다. -
로그로 검증합니다. 다른 네트워크에서 접속해 접근 로그에 그 IP가 찍히는지 확인합니다. 설정만 보고 넘어가면 이 문제는 사고가 난 뒤에 드러납니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.