модуль nginx geoip, защита от ddos
Собственно зачем вообще запрещать доступ к сайту по географическому признаку ? Да просто 80% IP адресов участвующих в ddos атаке, как правило принадлежат странам, жители которых никогда не зайдут на данный сайт, естественно это сугубо индивидуально для каждого ресурса и если вы знаете что часть ваших посетителей приходит из Эфиопии или Чили, блокировать их, вы вряд-ли захотите. У большинства-же моих клиентов, географическое расположение посетителей, как правило ограничивается Европой и бывшим СССР, остальных можно смело игнорировать.
Описываемый способ блокировки неугодных стран с помощью веб сервера nginx и geoip модуля, в одиночку, и тем более целиком, проблему никак не решит, это лишь одна, из целого ряда всевозможных мер ( настройка ядра, фаервола, штатных сервисов, дополнительного софта ), по минимизации вреда, наносимого данным видом атаки серверу и сайтам, на нем расположенным.
Проекты, часто нуждающиеся в подобного рода защите, я по возможности стараюсь изначально поднимать без участия веб сервера apache, то есть на связке nginx - fastcgi.
Итак, ставить и настраивать все это хозяйство будем на сервере под управлением операционной системы FreeBSD 8.2 and64.
Что-бы модуль geoip заработал, потребуется дополнительная библиотека, ставим:
freebsd82 /usr/ports# make -C net/GeoIP install clean
Далее ставим nginx:
freebsd82 /usr/ports# make -C www/nginx install clean
в опциях сборки нужно включить geoip модуль nginx, поставив галку напротив пункта Enable http_geoip module.
Далее идем на страницу http://www.maxmind.com/app/geolitecountry и скачиваем latest GeoLite Country Binary Format, это бесплатный вариант базы стран и соответствующих им блоков IP адресов. Распаковываем архив и кидаем файл GeIP.dat в папку /usr/local/etc/nginx/conf/geo. Осталось отредактировать конфиги nginx.
Открываем nginx.conf, дописываем в секцию http следующий блок директив:
geoip_country /usr/local/etc/nginx/conf/geo/GeoIP.dat; # подключаем GeIP базу map $geoip_country_code $bad_country { # модуль map создает переменные, значения которых зависят от других переменных, очень полезная штука default 1; # значение по умолчанию include geo/good_countries; # инклудим файл, к нему вернемся чуть позже }
Этот блок map, означает, что все страны находящиеся в базе данных, являются запрещенными по умолчанию, а в файле good_countries, будут перечислены разрешенные страны. Если у вас например ситуация, когда разрешенных стран больше чем запрещенных, можно легко инвертировать данную логику и создать файл bad_countries со списком запрещенных стран, разрешив все остальные.
Теперь настройки хоста. Я предпочитаю держать хосты в отдельной папке, например hosts, каждый в своем файле.
server { listen IP:80; server_name testhost.com; if ($bad_country){ # если данная переменная установлена, то есть если страна не перечислена в файле good_countries return 444; # выдаем клиенту пустой ответ ( незачем отдавать 403 ошибку или еще какую-либо ) } ................. ................. }
Теперь вернемся к файлу good_countries. Тут все предельно просто, страны, которым разрешен доступ на сайт, перечислены в следующем формате:
TM 0; UA 0; UZ 0; RU 0; ....... ....... и т.д.
То есть, что-бы разрешить какую-либо страну, достаточно добавить ее двухбуквенный код и 0, после чего перезагрузить конфиг nginx:
freebsd82 /# nginx -s reload
Сами коды стран, на раз два, находятся через гугл.
Проверить, работает geoip модуль или нет, можно, удалив из списка разрешенных стран свою, и попробовав зайти на сайт.
Собственно такова общая схема использования geoip модуля nginx для защиты от ddos атак.
Естественно можно придумать массу других вариантов применения данного модуля для решения различных задач связанных с географическим расположением посетителя сайта.
Комментарии
Хорошая статья, но вот "FreeBSD 8.2 and64" порадовала :-)
ой, да, забавно получилось )))))
А если ДДОСят из России и сайт рассчитан, что основная масса пользователей из России, что тогда? Или обычно ддосят из за бугра?
тогда этот метод конечно не катит, но преимущественно лупят как раз с IP какого нить Катара. Филлипин и т.д.
ну во всяком случае на моей практике, это так
в этом плане способ не универсален, применительно именно к ддосу
ддос из России обойдется дороже чем заграничный, с большой вероятностью метод поможет
Спасибо! Хорошая статья! Очень помогло в решении некоторых вопросов :)
пожалуйста)
А не получится так что nginx занятый отдаванием ответа 444 на блокированные адреса (в случае ддоса) будет перегружен. Ведь на ответ сервера все равно требуются ресурсы системы. И сайт будет "лагать".
то есть, это пустышка, никаких данных клиенту не передается, соединение просто закрывается
во всяком случае я никогда не сталкивался с лагами nginx'а, связанными с отдачей ошибок
ааа, все понял. Просто я только начинаю осваивать nginx и поэтому таких тонкостей не знаю. Еще раз спасибо!
Супер вещь, попробовал, работает, только вопрос. Я оставил страну только RU , но в логах вижу айпишник гугл бота US и ещё несколько IP с US Как можно проверить эту реализацию на конкретный IP адрес ?
не уверен, правильно-ли я понял вопрос, тем не менее
можно проверить на себе, например внести RU в список запрещенных и попробовать зайти на сайт, ну или попросить знакомых из других стран )
а что-бы не блочить весь сайт, на время экспериментов можно закрыть доступ к конкретной локации, что-то типа:
Да, я так и сделал. Работает. Но в логах httpd access log вижу, что некоторые с IP из USA заходят. В частности Googlebot, хотя разрешения на US нет. Если я правильно понимаю, он должен был его сбросить и не пустить. Вопрос почему пропустил?
может БД не совсем актуальна ?
файл Geoip.dat скачал вчера новый. Может в бесплатной версии этого файла не вся база присутствует?
стоп, так запрос и должен светиться в акцесс логе, другой вопрос, что nginx отдает в ответ, например
DENY_IP_ADDR - - [09/Feb/2014:14:12:38 +0400] "GET /test HTTP/1.1" 444 .......
то есть сам запрос пришел, но ответ на него, 444-я ошибка
Да, точно... недосмотрел
Тогда следующий вопрос:
1) В настройках стоит показывать ошибку 444, а в access логе показывает 403 ошибку, так и должно быть?
2) Можно ли как то реализовать, чтобы google ботам было разрешение на доступ, при этом всей стране где он находится, нет. ?
1. не знаю, проверьте конфиг )
2. можно следующим макаром:
далее, перед проверкой переменной $bad_country, ставим проверку переменной $legal_ip
если инкрудить легальные ip из файла, файл должен иметь такой вид:
1.1.1.1 1;
2.2.2.2 1;
и т.д.
Ок. Сейчас попробую, отпишусь как получится.
я проверял на рабочей машине, так что должно все работать )
Да, отлично работает. Спасибо. А ещё вопрос, как сделать ограничение средствами nginx на количество одновременных соединений с одного ip адреса?
ну, и отлично)
почитайте тут
http://nginx.org/ru/docs/http/ngx_http_limit_conn_module.html
думаю поможет
Отправить комментарий