Рассмотрим вариант защиты сервера, который работает на связке nginx + apache.
Когда атака "детская", то сервер с нормальными параметрами в принципе может и нормально её перенести, но когда вы используете VDS/VPS то обычно у вас не так много ресурсов чтобы держать даже такие "детские" атаки.
Меня тоже беспокоила данная проблема ибо сам владелец не собственного сервака, а VDS со скромными параметрами которых для моего сайта вполне хватает, а брать мощный сервер из-за флудеров как-то глупо.
Эксперименты с настройками апача на снижение количества процессов и прочего, в принципе не дали желаемого результата. Его было выбить сложнее, но не на столько сложно чтобы не справился даже "детский" флудер.
Во время атаки он съедал всю оперативку и nginx слал всем входящим на сайт ошибку 502 которая и говорит о том что целевой сервер лежит и не отвечает.
В поисках решения, наткнулся на интересный модуль для nginx.
Модуль называется Limit Requests. Включён в основной пакет с версии 0.7.20 так что если у вас nginx более старой версии, его нужно будет пересобрать или просто установить новый собранный.
Что же делает данный модуль?
Модуль ограничивает число запросов для заданной сессии или как правило для одного ip адреса.
Принцип основан на замедлении слишком частых запросов или полном отказе в обслуживании этих запросов. Вариант выбирается при настройке.
Не будем вдаваться в полные подробности работы, а пройдёмся поверхностно по тому, что именно нам необходимо.
Рассмотри следующий пример конфигурации модуля:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
...
server {
...
location / {
limit_req zone=one burst=5;
}
$binary_remote_addr - это наш ip который делает запросы.
zone=one:10m - задаём зону в которой хранятся все сессии и размер зоны.
rate=1r/s - этим самым мы задаём частоту запросов. В данном случае 1 запрос в секунду. Допускается установка значения в минутах.
rate=30r/m - Этот пример допускает 30 запросов в минуту.
Данная директива прописывается в основной конфигурационный файл nginx.conf
после http { как на примере.
Идём далее.
Рассмотрим следующую директиву: limit_req zone=one burst=5;
Она задаёт зону и максимально возможные всплески запросов.
Если скорость запросов превышает заданную в предыдущей директиве, то клиент замедляется так, чтобы обеспечить число запросов которое задано. Иными словами не даём превысить установленный лимит.
Все избыточные запросы держаться до тех пор пока не превысят заданное число всплесков. После превышения запрашивающему клиенту выдаётся ошибка 503 Service unavailable. Остальным же клиентам всё отдаётся нормально в прежнем режиме.
Директива допускает вариант без задержек: limit_req zone=one burst=5 nodelay;
В данном случае клиент не задерживается, а при всплесках сразу вываливается ошибка и запрос не обрабатывается.
Я не стал применять данный метод потому что он может негативно сказаться на поисковых роботах или роботах рекламных систем. Лучше их замедлить и тем самым не выдать ошибку на нормально работающую страницу.
Данную директиву необходимо прописывать для каждого домена.
Если настройки для доменов у вас хранятся в основном файле, то прописываем в раздел
location / {
limit_req zone=one burst=5;
}
для каждого сайта.
Если ваши настройки хранятся в отдельных файлах для каждого сайта, то так же просто прописываем в каждый файл для каждого сайта.
Не забываем перезапускать nginx после операций с конфигурационными файлами для вступления изменений в силу.
Ещё для запрета обхода nginx и прямых обращений к апачу необходимо закрыть прямой доступ к апачу.
Делаем это двумя вариантами:
1) Это перенастройка nginx и apache так, чтобы apache слушал только локальный ip.
2) Закрытие порта на котором висит apache.
Лично я воспользовался вторым вариантом ибо перепиливать все конфиги у меня не было желания.
Как делается второй вариант.
Делается он при помощи файрвола.
У меня стоит iptables, по этому команды для него. Для других ищите другие команды.
Команды:
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 8080 -j DROP
8080 - это порт на котором висит ваш apache.
На этом всё. Теперь обойти nginx и "завалить" apache не получится.