Если вы поставили Cloudflare перед сайтом, то почти сразу сталкиваетесь с эффектом «все посетители с одного IP». В access.log вместо клиента — адреса узлов Cloudflare. Из‑за этого ломаются ограничения по IP (allow/deny), гео‑логика (GeoIP), лимиты (rate limit), анти‑брутфорс (fail2ban), а иногда и аналитика.
Ниже — практический гайд для Linux + Nginx: как корректно восстановить реальный адрес клиента двумя способами: через заголовки (CF-Connecting-IP/X-Forwarded-For) и через PROXY protocol. Параллельно разберём, как не открыть дыру, когда вы «доверяете» данным от прокси.
Почему Nginx видит не тот IP и чем это опасно
В типовой схеме Cloudflare работает как reverse proxy: клиент подключается к Cloudflare, а Cloudflare ходит на ваш origin (Nginx). На origin соединение приходит с IP Cloudflare. Реальный IP клиента Cloudflare передаёт отдельно:
- в HTTP‑заголовках:
CF-Connecting-IP,X-Forwarded-For(иногдаForwarded); - или на уровне TCP:
PROXY protocol(если он доступен и включён в Cloudflare/балансировщике и поддержан на входе в Nginx).
Если Nginx не «распакует» эти данные, то $remote_addr будет равен Cloudflare‑IP. Это влияет на:
- allow/deny — можно случайно разрешить доступ всем через Cloudflare или, наоборот, заблокировать легитимных клиентов;
- GeoIP — география определяется по узлам Cloudflare;
- rate limit — вы лимитируете весь трафик «как один клиент»;
- fail2ban — «бан» уходит в Cloudflare‑IP, что бесполезно и может навредить;
- аудит/расследования — логи теряют ценность.
Базовая идея realip в Nginx: кому можно доверять
Модуль realip в Nginx делает простую вещь: если запрос пришёл от доверенного прокси, то можно заменить «видимый» IP ($remote_addr) на IP из заголовка или из PROXY protocol.
Ключевое правило: никогда не принимайте X-Forwarded-For/CF-Connecting-IP/Forwarded «от всех». Эти заголовки легко подделывает любой клиент, если он может ходить к вам напрямую, минуя Cloudflare.
Сначала закройте origin так, чтобы к нему могли подключаться только IP Cloudflare (и ваши служебные адреса). И только затем включайте realip.
Если вы размещаете проект на VDS и держите Nginx как публичный вход, удобнее сразу заложить «жёсткую» сетевую политику (фаервол + allow/deny) под Cloudflare и отдельно — доступ для администрирования.
Вариант 1 (самый частый): Cloudflare real IP через заголовки
Для Cloudflare чаще всего используют CF-Connecting-IP или X-Forwarded-For. Практичный выбор:
CF-Connecting-IP— обычно один адрес клиента (без цепочки);X-Forwarded-For— цепочка IP (клиент, прокси…), нужно понимать порядок и правила доверия.

Пример настройки: real_ip_header + set_real_ip_from
Добавьте в http {} (обычно /etc/nginx/nginx.conf) или в отдельный файл, подключаемый через include:
http {
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
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;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
}
Что здесь важно:
real_ip_header— какой заголовок считаем источником реального IP;set_real_ip_from— список доверенных сетей (только от них заголовку верим);real_ip_recursiveполезен при цепочке прокси, но включайте осознанно: чем сложнее цепочка, тем выше риск ошибиться в доверии.
Покупать и обновлять сертификаты удобнее централизованно: если вы используете коммерческие SSL-сертификаты для отдельных проектов или B2B‑контуров, заранее продумайте, где у вас терминация TLS (Cloudflare, Nginx, балансировщик) и как это повлияет на логи/диагностику.
Forwarded и X-Forwarded-For: когда пригодится
Иногда до Nginx стоит ещё один прокси/балансировщик, который формирует стандартный Forwarded (RFC 7239) или цепочку X-Forwarded-For. В реальности для Cloudflare чаще проще опираться на CF-Connecting-IP.
Если инфраструктура сложнее, удобная практика такая: на ближайшем к Nginx прокси вы приводите входящие данные к одному «каноническому» заголовку (например, выставляете X-Real-IP), а в Nginx уже указываете именно его в real_ip_header.
Как обновлять список сетей Cloudflare
Сети Cloudflare меняются. Если их «вписать и забыть», однажды получите плавающие проблемы: то realip перестанет работать, то вы начнёте отбрасывать легитимный трафик из новых диапазонов.
Практичный подход: держать отдельный файл (например, /etc/nginx/conf.d/cloudflare-realip.conf) и подключать его в http {}. Обновление — через конфигурационное управление (Ansible/Salt) или хотя бы регламент ручной проверки.
Вариант 2: PROXY protocol — когда нужен и как включать
PROXY protocol передаёт исходный IP/порт на уровне TCP ещё до HTTP. Это удобно, когда:
- у вас не HTTP, а TCP‑сервисы в
stream {}(например, TLS passthrough); - вы хотите меньше зависеть от HTTP‑заголовков;
- перед Nginx стоит L4‑балансировщик, который умеет PROXY protocol.
Нюанс: если включить приём PROXY protocol на слушающем сокете, а трафик придёт без него, Nginx не сможет распарсить начало соединения. Это проявится как ошибки рукопожатия или «мусор» вместо HTTP.
Nginx: listen ... proxy_protocol; и real_ip_header proxy_protocol
Пример для HTTPS‑виртуального хоста, где upstream приходит с PROXY protocol:
server {
listen 443 ssl http2 proxy_protocol;
real_ip_header proxy_protocol;
real_ip_recursive off;
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;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
Здесь real_ip_header proxy_protocol говорит Nginx брать адрес клиента не из HTTP, а из метаданных TCP‑соединения.
Смешивать ли заголовки и PROXY protocol
Лучше выбрать один «источник истины». Если upstream‑приложение ожидает X-Forwarded-For, вы можете выставить его при проксировании, уже опираясь на восстановленный $remote_addr:
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Forwarded "for=$remote_addr;proto=$scheme";
proxy_pass http://127.0.0.1:8080;
}
Так вы унифицируете поведение приложений и правил безопасности независимо от того, как именно пришёл реальный адрес.
Как правильно закрыть origin: фаервол и allow/deny
Настройка realip без ограничения доступа к origin — одна из самых частых ошибок. Если origin доступен напрямую из интернета, злоумышленник может прийти в обход Cloudflare и подставить любой CF-Connecting-IP или X-Forwarded-For.
Два уровня защиты:
- Сетевой: разрешить входящие 80/443 только с подсетей Cloudflare (и ваших служебных IP).
- На Nginx: дополнительный allow/deny на уровне
serverилиlocation.
Allow/deny в Nginx (как страховка)
server {
listen 80;
allow 173.245.48.0/20;
allow 103.21.244.0/22;
allow 103.22.200.0/22;
allow 103.31.4.0/22;
allow 141.101.64.0/18;
allow 108.162.192.0/18;
allow 190.93.240.0/20;
allow 188.114.96.0/20;
allow 197.234.240.0/22;
allow 198.41.128.0/17;
allow 162.158.0.0/15;
allow 104.16.0.0/13;
allow 104.24.0.0/14;
allow 172.64.0.0/13;
allow 131.0.72.0/22;
allow 2400:cb00::/32;
allow 2606:4700::/32;
allow 2803:f800::/32;
allow 2405:b500::/32;
allow 2405:8100::/32;
allow 2a06:98c0::/29;
allow 2c0f:f248::/32;
deny all;
location / {
return 200 "ok";
}
}
Этот подход полезен как «предохранитель», но не заменяет фаервол: проверка allow/deny происходит уже после установки TCP‑соединения.
Кстати, если вы планируете включать строгие заголовки безопасности и HSTS, полезно заранее продумать миграции сертификатов и редиректы. По теме — миграция домена: 301, HSTS и SSL без сюрпризов.

Логи: как убедиться, что realip действительно работает
Проверка «на глаз» по $remote_addr не всегда удобна. На время диагностики расширьте формат логов и выведите несколько полей одновременно:
log_format realip_debug '$remote_addr - $realip_remote_addr - $proxy_protocol_addr - $http_cf_connecting_ip - $http_x_forwarded_for - $request';
access_log /var/log/nginx/access_realip_debug.log realip_debug;
Как читать:
$remote_addr— адрес «как видит Nginx после realip»;$realip_remote_addr— исходный адрес до подмены;$proxy_protocol_addr— адрес из PROXY protocol (если он включён);$http_cf_connecting_ipи$http_x_forwarded_for— что приехало в заголовках.
Rate limit по реальному IP: типовые грабли
Если ограничение задано по $binary_remote_addr, а realip не настроен, вы лимитируете Cloudflare, а не клиентов. После включения realip это исправится, но появляется другой нюанс: атаки могут «размазаться» по множеству IP, и лимит станет менее заметным. Обычно приходится комбинировать лимиты на edge‑уровне и в приложении.
Пример простого лимита на клиента:
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
server {
location /login {
limit_req zone=perip burst=20 nodelay;
proxy_pass http://127.0.0.1:8080;
}
}
Это и есть «rate limit по реальному IP»: ключ зоны должен соответствовать клиенту, а не прокси.
Fail2ban за прокси: как банить правильно, если есть realip
Fail2ban читает логи и банит IP, который нашёл в строке. Если у вас в логах Cloudflare‑IP, вы фактически баните Cloudflare и создаёте себе проблемы. Чтобы было осмысленно:
- в логах Nginx первым IP должен стоять уже восстановленный
$remote_addr; - origin должен быть закрыт от прямого доступа (иначе заголовок подделают и «подставят» чужой IP под бан);
- нужно понимать, где применять бан: на origin (часто бессмысленно для веб‑трафика через Cloudflare) или на edge/WAF‑уровне (обычно эффективнее).
Если вы баните на уровне origin‑фаервола, помните: реальный клиент физически не подключается к вашему серверу, подключается Cloudflare. Поэтому классические баны IP на origin часто не дают эффекта для сайта, если весь трафик идёт через Cloudflare. В таком сценарии fail2ban полезнее как сигнализация и для защиты сервисов, доступных напрямую (SSH, панели), а не как «анти‑бот» для HTTP.
GeoIP и «география по клиенту»: что поменяется после realip
Для GeoIP‑логики критично, чтобы Nginx уже знал реальный $remote_addr. После включения realip вы можете корректно использовать гео‑переменные для правил доступа, локализации или дополнительной аналитики.
Если вы используете гео‑ограничения (например, для админки), не делайте их единственной защитой. Комбинируйте с аутентификацией, ограничением по URI и при необходимости — allowlist по IP.
Чеклист: диагностика, если «реальный IP» не появляется
- Origin открыт напрямую: клиент приходит без Cloudflare, заголовки поддельные, а вы начинаете доверять им как истине. Закройте origin.
- Не добавлены все подсети в
set_real_ip_from: часть узлов Cloudflare не считается доверенной. - Выбрали не тот заголовок в
real_ip_header: проверьте в логах, что реально приезжает ($http_cf_connecting_ip,$http_x_forwarded_for). - Включили PROXY protocol на
listen, но upstream его не отправляет: получите ошибки и «битый» трафик. - Забыли IPv6: закрыли origin по IPv4, но оставили открытым по IPv6 (или наоборот).
Практическая рекомендация: заголовки vs PROXY protocol
Если у вас обычный веб‑сайт за Cloudflare и TLS терминируется на Nginx, начните с варианта через заголовки: real_ip_header + полный список set_real_ip_from + жёсткое ограничение доступа к origin. Это самый совместимый и предсказуемый путь.
PROXY protocol выбирайте, когда он действительно нужен по архитектуре: L4‑балансировка, stream {}, TLS passthrough или когда вы сознательно строите цепочку без доверия к HTTP‑заголовкам. Но включайте его только там, где вы точно гарантируете наличие PROXY protocol на входе.
Итог
Восстановление реального IP за Cloudflare — это не одна директива, а связка из трёх частей: (1) закрыть origin, (2) настроить доверенные сети через set_real_ip_from, (3) выбрать корректный источник (real_ip_header или proxy_protocol). После этого начинают «оживать» allow/deny, GeoIP, rate limit и нормальные логи, а инструменты вроде fail2ban перестают работать вслепую.
Если вы тюните кеширование и диапазонные запросы, учитывайте, что прокси‑слой и realip влияют на диагностику и разбор логов. В тему — настройка Range-запросов и кеша в Nginx/Apache.


