Многие сайты для защиты от DDoS-атак и в качестве CDN используют Cloudflare, который работает как обратный прокси для сайта. Когда пользователь заходит на сайт, то вы получаете IP адрес сетей CloudFlare, а не реальный IP адрес пользователя. В данной статье рассмотрим, как это исправить.

CloudFlare позволяет не только фильтровать трафик сайта и блокировать нежелательные атаки, но и ускорять сайт за счёт кэширования статических файлов.
Когда пользователь входит на сайт, который подключён к CloudFlare, то он обращается к IP сетям CloudFlare, а тот в свою очередь обращается к реальному IP вашего сервера и отдаёт пользователю содержимое сайта.

Схематично это выглядит примерно так: 

Запрос пользователя — CloudFlare — Ваш сервер — Ответ пользователю

То есть, настоящий IP адрес вашего сервера защищён и не виден пользователю. Все запросы идут непосредственно на CloudFlare, который обрабатывает их, а затем проксирует ваш реальный сервер. Поэтому получая IP адрес пользователя, например, с помощью $_SERVER['REMOTE_ADDR'], вы можете заметить, что там будет не реальный IP адрес пользователя, а IP сетей CloudFlare.

Рассмотрим несколько способов, как получить реальный IP адрес пользователя:

Реальный IP пользователя в PHP

Настоящий IP адрес пользователя CloudFlare будет передавать в специальном заголовке: CF-Connecting-IP.

Таким образом, вы можете получить IP на своём сайте с помощью следующего кода:

if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
}

Кроме этого возможно получить реальный IP пользователя из заголовка X-Forwarded-For, который может содержать несколько адресов разделённых запятой. Первый адрес, как правило, является реальным IP адресом пользователя, а остальные адреса сетей CloudFlare.

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
   $ipAddresses = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
   $ip = array_shift($ipAddresses;
}

Реальный IP адрес пользователя в NGINX

Но теперь представьте, если у вас большой сайт или веб-приложение. Изменять код в каждом месте, где используется IP может показаться сложным. Поэтому это можно сделать на уровне вашего сервера с помощью настроек NGINX. Для этого будет использоваться специальный модуль ngx_http_realip_module.

Откройте каталог /etc/nginx и создайте в нём файл cloudflare. Затем скопируйте следующие IP адреса сетей Cloudflare:

https://www.cloudflare.com/ips-v4/
https://www.cloudflare.com/ips-v6

И добавьте в файл следующим образом:

#Cloudflare ip addresses
# - IPv4
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;

# - IPv6
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 CF-Connecting-IP;
  • set_real_ip_from — определяет доверенные IP адреса, которые отправляют реальные адреса пользователя.
  • real_ip_header - определяет значение заголовка, из которого берётся реальный IP адрес пользователя.

Откройте файл /etc/nginx/nginx.conf и в уже имеющемся там разделе http { } подключите созданный файл cloudflare.

include /etc/nginx/cloudflare;

Чтобы изменения вступили в силу, следует перезапустить nginx:

sudo systemctl restart nginx

На этом, настройка закончена. Теперь вы знаете, как получить реальный IP адрес пользователя Cloudflare.