RSS
전체 글

Cloudflare Tunnel 환경에서 실제 방문자 IP를 처리하는 방법

Cloudflare Tunnel로 서비스를 노출하면 origin 서버가 보는 접속 IP가 실제 방문자 IP가 아닐 수 있습니다. 모든 요청이 터널 또는 프록시에서 온 것처럼 보이면 rate limit, 방문 통계, IP 차단 같은 기능이 부정확해집니다.

왜 실제 IP가 안 보이나

Cloudflare Tunnel 구조는 대략 다음과 같습니다.

[방문자]
  → [Cloudflare Edge]
  → [cloudflared Tunnel]
  → [origin server]

origin 서버 입장에서는 TCP 연결의 출발지가 방문자가 아니라 터널 또는 내부 프록시입니다. 실제 방문자 IP는 HTTP 헤더로 전달됩니다.

우선 확인할 헤더

Cloudflare는 실제 방문자 IP를 다음 헤더에 담아 전달합니다.

헤더 용도
CF-Connecting-IP Cloudflare가 전달하는 실제 방문자 IP. 가장 우선적으로 사용
X-Forwarded-For 여러 프록시를 거친 IP 체인
X-Real-IP 일부 프록시 환경에서 사용하는 단일 IP

Cloudflare를 신뢰할 수 있는 경로로만 origin에 접근하게 했다면 CF-Connecting-IP를 우선 사용하는 것이 가장 단순합니다.

애플리케이션에서 처리하기

Next.js 같은 앱에서는 요청 헤더에서 IP를 추출하는 공통 함수를 두는 것이 좋습니다.

export function clientIpFromHeaders(headers: Headers): string {
  const cf = headers.get('cf-connecting-ip');
  if (cf) return cf.trim();

  const forwarded = headers.get('x-forwarded-for');
  if (forwarded) return forwarded.split(',')[0].trim();

  return headers.get('x-real-ip') || 'unknown';
}

이 함수를 rate limit, 로그인 보호, 방문 통계 등 IP 기반 로직에서 일관되게 사용합니다.

nginx에서 처리하기

nginx 앞단에서 real_ip_header CF-Connecting-IP를 설정하면 애플리케이션은 remote_addr 기준으로 실제 IP를 볼 수 있습니다.

다만 이 방식은 신뢰할 프록시 범위를 정확히 지정해야 합니다. Cloudflare IP 대역과 내부 터널 네트워크를 과도하게 넓게 신뢰하면 헤더 위조 위험이 생길 수 있습니다.

운영 환경에서는 Cloudflare IP ranges를 정기적으로 확인하고, origin이 외부에서 직접 접근되지 않도록 제한하는 것이 좋습니다.

검증 방법

서로 다른 네트워크에서 방문자 IP 확인용 API를 호출해 봅니다.

  • 사무실 Wi-Fi
  • 휴대폰 LTE/5G
  • VPN 또는 다른 네트워크

각 요청이 서로 다른 IP로 기록되면 정상입니다. 모두 같은 내부 IP로 보인다면 아직 프록시 IP를 보고 있는 것입니다.

주의할 점

IP 기반 보안은 절대적인 인증 수단이 아닙니다. 특히 프록시 헤더는 신뢰 경계가 잘못 설정되면 위조될 수 있습니다. 따라서 IP는 rate limit과 보조 보안 신호로 사용하고, 인증·권한 검증을 대체해서는 안 됩니다.

듀오랩스가 보는 관점

Cloudflare Tunnel은 배포와 보안을 단순하게 만들어주지만, 프록시 구조를 이해하지 않으면 로그와 보안 정책이 왜곡될 수 있습니다. 실제 방문자 IP 처리 방식은 서비스 초기에 공통 유틸로 정리해두는 것이 좋습니다.