В этой статье я расскажу как заблокировать доступ к сайту из нежелательных стран, но при этом сохранить возможность посещения сайта отдельными пользователями из заблокированной страны. Блокировать неугодные страны будем с помощью GeoIP модуля для сервера Nginx.
В предыдущей статье я рассмотрел добавление GeoIP модуля в сборку Nginx, с его дальнейшей настройкой, которая позволяет блокировать страны, исключая их из списка разрешенных. Данный способ подразумевает полный запрет посещения сайта со всех адресов принадлежащих заблокированной стране, не оставляя никаких лазеек. Ну разве что, кроме VPN, TOR-а и прочих средств обхода блокировок.
Один из посетителей сайта прочитав вышеуказанную статью, задал очень интересный вопрос. Суть вопроса состояла в том, что если заблокировать доступ к сайту из США, то будет ли сайт доступен для поисковых роботов Google-а, имеющих американские диапазоны ip-адресов.
Я не знаю зачем человеку понадобилось блокировать пользователей из США, ведь обычно блокируют китайских товарищей, но это не мое дело. Может он является ярым патриотом, и таким образом показывает американцам их место, ну или отвечает на санкции, ведь запрещали же вход Бараку Обаме, отчего же не запретить вход остальным американцам?
В таком случае мне непонятна обеспокоенность за американский поисковик, ведь если отказываешься от американского, то нужно отказываться сразу от всего. Но это не важно, главное что сам вопрос интересный, причем настолько, что я решил написать отдельную статью.
Представьте себе что есть некий сайт и есть друг уехавший в Китай. Ввиду повышенной активности китайских ботов, доступ к сайту для Китая у нас закрыт. Но друг очень любит посещать сайт и жить не может без фотографий котиков, которые вы там выкладываете. Как сделать так, чтобы ваш друг находясь в Китае, имел возможность посещать сайт, а остальные китайцы такой возможности не имели?
Конечно же он может использовать TOR или VPN, чтобы попасть на ваш сайт, но давайте представим что такой возможности у него нет и все нужно сделать грамотно.
Контекст http {} файл nginx.conf
В конфигурацию сервера, у меня она устроена следующим образом, в контекст http {}, должны быть включены GeoIP-базы. У меня они находятся в каталоге /etc/nginx/geoip.
# Подключение баз GeoIP geoip_country /etc/nginx/geoip/GeoIP.dat; geoip_city /etc/nginx/geoip/GeoLiteCity.dat;
Теперь с помощью директивы geo (ngx_http_geo_module - добавлять не нужно, т.к. входит в состав nginx), создадим переменную $friend (имя может быть любым, главное наличие "$" в начале), значение которой будет определять ip-адрес друга. По умолчанию переменная будет равна нулю, если определены ip-адрес или подсеть друга, то значение переменной будет равняться единице.
geo $friend { # Значение по умолчанию равно 0 default 0; # Значение если на сайт пришел друг равно 1 # IP-адрес друга (если адрес статический) XXX.XXX.XX.XXX 1; # Или подсеть друга (если адрес динамический) XXX.XXX.XX.XXX/19 1; }
Должно быть примерно так. Адресов и подсетей может быть столько, сколько нужно.
geo $friend { default 0; 192.168.100.51 1; 192.168.100.52 1; 192.168.100.53 1; 192.168.100.54 1; 192.168.100.55 1; 192.168.100.1/19 1; 192.168.50.2/18 1; }
Контекст server {} хост-файл
В конфигурацию хост-файла, в контекст server {}, добавляем переменную $block_china (имя может быть любым) и несколько условий для ее работы. Все вместе выглядит следующим образом.
set $block_china 0; if ($geoip_country_code = CN) { set $block_china 1; } if ($friend = 1){ set $block_china 0; } if ($block_china = 1){ return 403; }
Разберем написанное, чтобы понимать как все это работает.
Добавляем переменную $block_china и выставляем ее значение равным нулю.
set $block_china 0;
Пока $block_china равна нулю, доступ на сайт разрешен всем приходящим посетителям. Если определен китайский ip-адрес, то переменная $block_china становится равной единице и запрещает доступ.
if ($geoip_country_code = CN) { set $block_china 1; }
Если на сайт пришел ваш друг и переменная $friend равна единице, то $block_china становится равной нулю и разрешает посещение сайта.
if ($friend = 1){ set $block_china 0; }
Если $block_china равна единице, то для остальных китайских посетителей, не попадающих под действие предыдущего условия, доступ запрещен. Тогда клиенту отдается 403-й ответ (forbidden) или любой другой, например 444-ый (разрыв связи с клиентом).
if ($block_china = 1){ return 403; }
Если помимо Китая нужно заблокировать еще какую-либо страну, то в таком случае нужно немного изменить первое условие. Если страна одна, то достаточно добавить значение переменной $geoip_country_code = CN. Но если нужно добавить еще страны, то значение переменной $geoip_country_code будет выглядеть так !~ (CN|AF|BO). Стран может быть сколько угодно, главное записывать их внутри скобок, через разделитель "|", например !~ (CN|AF|BO|XX|XX|XX|XX).
В этом условии к Китаю я добавил Афганистан - AF и Боливию - BO.
if ($geoip_country_code !~ (CN|AF|BO)) { set $block_china 1; }
Для применения изменений проверяем правильность конфигурационных файлов и перечитываем конфиги.
nginx -t && systemctl reload nginx nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Проверить работу можно с помощью VPN или TOR-а. Подключитесь к VPN или TOR-у, посмотрите свою страну и ip-адрес, например вот тут. Быстренько набросайте конфигурацию GeoIP с запретом страны, разрешите вход со своего нового ip-адреса, перезагрузите сервер и зайдите на сайт. Если вас пустило на сайт, значит все работает.
Чтобы точно убедиться в правильности конфигурации, закомментируйте свой ip-адрес в значении переменной $friend директивы geo.
geo $friend { default 0; #192.168.100.51 1; }
Перечитайте конфиг сервера и перезагрузите страницу своего сайта. Если после этого вам отдан 403-й ответ, то все точно работает.
Вот таким простым образом и китайцы заблокированы и друг доволен. Ну а патриоты могут заблокировать на своих сайтах США, но при этом разрешить доступ для поисковых роботов Американской Корпорации Google. Список диапазонов адресов, с которых приходят роботы Google-а, я любезно прилагаю ниже.
64.68.80.0 – 64.68.87.255 (64.68.80.0/21) 64.233.160.0 – 64.233.175.255 (64.233.160.0/19) 66.102.0.0 – 66.102.15.255 (66.102.0.0/20) 66.249.64.0 – 66.249.95.255 (66.249.64.0/19) 72.14.192.0 – 72.14.255.255 (72.14.192.0/18) 209.85.128.0 – 209.85.255.255 (209.85.128.0/17) 216.239.32.0 – 216.239.63.255 (216.239.32.0/19)
Спасибо за внимание.