Nginx & Cloudflare 프록시 환경 IP 화이트리스트 적용

hbjs97·2025년 2월 20일
post-thumbnail

최근 PoC 단계의 서비스의 어드민 콘솔을 빠르게 배포하면서 유저 관리나 인증 같은 무거운 기능을 모두 제외하고 최소한의 기능만 남겼다. 빠르게 검증하기 위한 환경이라 최대한 가볍게 유지해야 했고, 가장 간단하면서도 효과적인 접근 제어 방식인 IP 화이트리스트를 적용하게 됐다.

이 과정에서 생각보다 IP 설정이 까다로웠던 부분이 있었고, 특히 Cloudflare Tunnel과 Nginx를 함께 쓰면서 겪었던 문제와 해결 과정을 정리해둔다.

환경 구성과 요구사항

어드민 콘솔 접근 경로는 다음과 같은 구조다.

Client → Cloudflare → [내부망] → Kubernetes → Cloudflare Tunnel → Nginx

Cloudflare Tunnel을 통해 내부망의 NGINX에 접근하는 구조다.

실제 클라이언트 IP 문제

처음에는 Cloudflare에서 제공하는 헤더인 CF-Connecting-IP를 사용하면 클라이언트 IP를 정확히 얻을 수 있다고 알고 있었다. 따라서 NGINX 설정에서 아래와 같이 구성했다.

real_ip_header CF-Connecting-IP;

하지만 위 설정 이후에도 외부에서 접근 제한이 정상적으로 동작하지 않는 문제가 발생했다.

로그 확인 결과

NGINX의 로그를 확인해보니 $remote_addr가 실제 클라이언트 IP가 아니라 직전 프록시(Cloudflared Tunnel Pod)의 IP가 찍혔다.

log_format main '$time_iso8601 $remote_addr $request\n'
                '\t\t[$status] $http_user_agent\n'
                '\t\t$http_x_forwarded_for\n';

  • $remote_addr: Cloudflared Tunnel Pod의 IP
  • $http_x_forwarded_for: 실제 클라이언트의 IP

원인과 해결 방법

NGINX에서 allow/deny 접근 제어는 $remote_addr를 기준으로 동작하기 때문에, 실제 클라이언트 IP가 $remote_addr로 잡혀야 정상적으로 접근 제어가 가능하다.

실험한 결과, NGINX의 set_real_ip_from 설정을 Cloudflare의 외부 IP 대역이 아닌, 내부망 IP 대역(proxy pod IP 포함)으로 설정하면 정상적으로 실제 클라이언트 IP를 얻을 수 있었다.

NGINX 설정 케이스별 테스트 결과

CaseNGINX 설정결과
1Cloudflare 외부 IP 대역 신뢰, real_ip_header CF-Connecting-IP;❌ Fail
2Cloudflare 외부 IP 대역 신뢰, real_ip_header CF-Connecting-IP; real_ip_recursive on;❌ Fail
3내부망 IP 대역 신뢰, real_ip_header CF-Connecting-IP; real_ip_recursive on;✅ Success
4내부망 IP 대역 신뢰, real_ip_header X-Forwarded-For; real_ip_recursive on;✅ Success
5내부망 IP 대역 신뢰, real_ip_header CF-Connecting-IP;✅ Success
6내부망 IP 대역 신뢰, real_ip_header X-Forwarded-For;✅ Success
  • 결론: Cloudflare Tunnel을 통해 접근하는 환경에서는 내부 프록시(IP: 내부망)를 신뢰(set_real_ip_from)하도록 설정해야 실제 클라이언트 IP를 얻을 수 있다.

최종 권장 NGINX 설정 예시

set_real_ip_from 192.168.0.0/16;  # 내부망 IP 대역
real_ip_header CF-Connecting-IP;
real_ip_recursive on;

위 설정을 통해 Cloudflare Tunnel 환경에서도 정상적으로 실제 클라이언트 IP를 얻어 접근 제어가 가능했다.


현재 어드민 콘솔의 IP 화이트리스트는 NGINX의 nginx.conf에 정적으로 설정해 관리하고 있다.
이 방식은 화이트리스트가 변경될 때마다 Dockerfile을 새로 빌드하고 재배포해야 하는 불편함이 있었다.

이러한 문제를 해결하기 위해 아래와 같은 방식을 시도한 적이 있다.

  • 화이트리스트 또는 nginx.conf 자체를 Kubernetes의 ConfigMap으로 분리하여 동적으로 관리
  • Cloudflare Tunnel이 아닌 Traefik 등 다른 Reverse Proxy를 통해 동적 접근 제어 적용

위 방식들도 실제 환경에서 적용해 본 경험이 있으나, 자세한 내용과 적용 방법은 추후 별도의 포스팅을 통해 다룰 예정이다.

0개의 댓글