Next.js
Cloudflare 프록시 뒤에서 실제 IP 로그가 모두 같아진 설정 노트
Cloudflare를 켠 뒤 Nginx 로그의 접속 IP가 프록시 주소로만 보일 때 확인한 헤더와 real_ip 설정 메모입니다.
이상했던 로그 한 줄
Cloudflare 프록시를 켠 뒤부터 Nginx access log에서 접속자가 거의 같은 대역으로만 보였다. 처음에는 봇 트래픽이 늘어난 줄 알았는데, 실제로는 서버가 사용자의 IP가 아니라 Cloudflare의 프록시 IP를 기록하고 있었다.
문제가 된 상황은 간단했다. 로그인 실패 횟수를 IP 기준으로 보려고 했는데 모든 요청이 비슷한 IP로 묶였다. 이 상태로 차단 규칙을 만들면 정상 사용자까지 같이 막을 수 있어서 설정을 멈췄다.
확인한 헤더
Cloudflare는 원래 접속자 IP를 CF-Connecting-IP 헤더에 담아 보낸다. 서버에서 바로 확인할 수 있다면 아래처럼 임시 로그 포맷을 추가해 봤다.
log_format with_cf '$remote_addr $http_cf_connecting_ip $request';
access_log /var/log/nginx/access_cf.log with_cf;
그리고 로그를 보면서 두 값이 어떻게 다른지 확인했다.
sudo tail -f /var/log/nginx/access_cf.log
$remote_addr는 Cloudflare 쪽 주소였고, $http_cf_connecting_ip에는 기대한 사용자 IP가 들어왔다.
Nginx real_ip 설정 기준
수정은 real_ip_header와 set_real_ip_from을 같이 넣는 방식으로 했다. 중요한 점은 아무 IP에서 온 헤더나 믿으면 안 된다는 것이다. 프록시 헤더는 신뢰할 수 있는 프록시에서 온 요청일 때만 사용해야 한다.
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
real_ip_header CF-Connecting-IP;
운영 서버에서는 Cloudflare가 공개한 IP 대역을 최신으로 관리해야 한다. 저는 일단 설정 파일에 주석으로 갱신 위치와 날짜를 남겼다.
적용 전에 검사한 것
설정 반영은 바로 reload하지 않고 문법 검사부터 했다.
sudo nginx -t
sudo systemctl reload nginx
그 다음에는 새 로그에서 $remote_addr가 실제 사용자 IP로 바뀌는지 확인했다.
sudo tail -n 20 /var/log/nginx/access.log
로그 기반 제한, 관리자 접근 제한, 보안 알림처럼 IP를 기준으로 삼는 기능은 이 설정 영향을 크게 받는다.
남겨 둔 메모
- 프록시를 켜면 서버가 보는 IP가 달라질 수 있다.
X-Forwarded-For를 무조건 믿지 않는다.- Cloudflare 대역에서 온 요청일 때만 원 IP 헤더를 신뢰한다.
- 설정 후에는 access log 한 줄을 실제로 보고 판단한다.
이번에는 로그 모양이 비슷해서 초반에 놓쳤다. 보안 설정을 붙이기 전에는 내가 기준으로 삼는 IP가 정말 사용자의 IP인지 먼저 확인하는 게 맞다.