Среди прочих плюшек, которые предоставляет Cloudflare, есть возможность передачи заголовка с указанием страны, из которой пришёл посетитель.
После долгих и безуспешных попыток как-то адекватно настроить GeoIP v2 для NGINX, IP Geolocation от Cloudflare стал просто подарком.
Собственно, что хочется сделать:
- перенаправлять всех посетителей с российских IP на другой домен
- при этом фильтровать запросы от Yandex, и ему отдавать содержимое этого блога, что бы посетители из россии продолжали видеть этот блог в выдаче поисковика
Содержание
Cloudflare IP Geolocation и NGINX
Самая простая часть – это настроить фильтрацию по заголовку, который передаёт Cloudflare.
Для начала, включаем передачу самого заголовка CF-IPCountry.
Переходим в Cloudflare Dashboard > Network, активируем опцию – она бесплатна даже в базовом пакете:
Далее, в файле настроек виртуалхоста в блоке server {}
используем заголовок через proxy_set_header
:
... proxy_set_header CF-IPCountry $http_cf_ipcountry; ...
NGINX и “вложенные” if
А далее задача поинтереснее.
Нам надо проверить два условия:
- пришёл ли посетитель из россии
- пришёл ли простой посетитель – или бот Яндекса?
В NGINX мы не можем использовать вложенные if
, т.е. нельзя использовать конструкцию типа:
... if ($country_allowed = no) { if ($http_user_agent !~* (YandexBot) ) { rewrite ^ https://russki-voenny-korabl-idi-nahuy.com break; } } ...
Но что мы можем сделать – так это использовать переменные и несколько if
.
Включаем VPN, проверяем в какую локацию нас занесло, например через https://www.iplocation.net:
GB – Great Britain.
В nginx.conf
можно добавить расширенный формат access_log
:
... log_format main_ext '$time_local client: $remote_addr fwd_for: $http_x_forwarded_for ' 'status: $status user_agent: "$http_user_agent" ' 'server: "$server_name" country: $http_cf_ipcountry visitor: $visitor'; ...
Переходим к формированию условий для редиректа и тестированию. Когда всё проверим – изменим условия на RU и “если не равно” Yandex (см. Yandex robots in server logs).
Итак:
- создаём переменную
$http_cf_ipcountry
из заголовкаCF-IPCountry
; - в первом условии
if
проверяем$http_cf_ipcountry
: пока используем регион GB; создадим переменную$visitor
, в которую занесём значение rus, если регион == GB; - во втором условии
if
– проверяемUser-Agent
, и если он == Firefox – то добавляем к значению переменной$visitor
значение “redirect; - в третьем
if
проверяем значение$visitor
, и есло оно равно rusredirect, то выполняемrewrite
на домен russki-voenny-korabl-idi-nahuy.com;
Кроме того, можно включить опцию rewrite_log
в on, и error_log
установить на уровень notice, что бы увидеть срабатывание rewrite
.
Получается:
... rewrite_log on; access_log /var/log/nginx/rtfm.co.ua-access-ext.log main_ext; error_log /var/log/nginx/rtfm.co.ua-error.log notice; ... proxy_set_header CF-IPCountry $http_cf_ipcountry; if ($http_cf_ipcountry = GB) { set $visitor rus; } if ($http_user_agent ~* (Firefox) ) { set $visitor "${visitor}redirect"; } if ($visitor = "rusredirect") { rewrite ^ https://russki-voenny-korabl-idi-nahuy.com break; } ...
Проверяем корректность конфига, перезагружаем конфиги nginx
:
[simterm]
root@rtfm-do-production-d10:~# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful root@rtfm-do-production-d10:~# systemctl reload nginx
[/simterm]
И заходим на сам блог:
access_log:
[simterm]
root@rtfm-do-production-d10:~# tail -f /var/log/nginx/rtfm.co.ua-access-ext.log | grep GB 02/Apr/2022:06:22:29 +0000 client: 162.158.91.190 fwd_for: 146.70.46.20,146.70.46.20 status: 302 user_agent: "Mozilla/5.0 (X11; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/98.0" server: "rtfm.co.ua" country: GB visitor: rusredirect
[/simterm]
error_log:
[simterm]
root@rtfm-do-production-d10:~# tail -f /var/log/nginx/rtfm.co.ua-error.log | grep 'rewritten redirect' 2022/04/02 06:22:29 [notice] 21018#21018: *33766595 rewritten redirect: "https://russki-voenny-korabl-idi-nahuy.com", client: 162.158.91.190, server: rtfm.co.ua, request: "GET / HTTP/1.1", host: "rtfm.co.ua"
[/simterm]
Посетитель пришёл из country: GB
с user_agent: "Firefox"
, и получил redirect: "https://russki-voenny-korabl-idi-nahuy.com"
– всё работает.
Меняем условия:
- меняем регион –
if ($http_cf_ipcountry = RU)
- и меняем
~* (Firefox)
на не-равно, т.е.!~* (Yandex)
–if ($http_user_agent !~* (Yandex) )
:
... proxy_set_header CF-IPCountry $http_cf_ipcountry; if ($http_cf_ipcountry = RU) { set $visitor rus; } if ($http_user_agent !~* (Yandex) ) { set $visitor "${visitor}redirect"; } if ($visitor = "rusredirect") { rewrite_log on; rewrite ^ https://russki-voenny-korabl-idi-nahuy.com break; } ...
Готово.