Мне довольно часто достают какие то боты непонятной природы, которые как саранча быстро наваливаются на сервер, качают все что можно в сотни потоков и так же быстро исчезают.
Решил написать простенькую банилку. Обращаю внимание, банилка простенькая, в качестве БД используется MySQL – не рекомендуется как защита от DDoS атак. Возможно позже переведу ее на Berkeley DB.
Платформа: Nginx + ipfw + MySQL + свой скрипт. Впрочем, подойдет любой другой веб сервер, который умеет выборочно писать логи, например, apache+mod_setenv_if
Nginx:
Нам нужно заставить вебсервер писать логи обращений к скриптам. Именно к скриптам, т.к. учитывать обращение к медиа файлам лучше не стоит ) В nginx это делается просто.
nginx.conf:
location ~* \.php$ {
log_format IP ‘[$time_local] $remote_addr’;
access_log /home/logs/nginx.ip.log IP;
….. # далее директивы proxy_pass
}
Таким образом в файл /home/logs/nginx.ip.log будут писаться айпишники и время доступа к скриптам. Осталось этот файл периодически анализировать.
Скрипт анализа я написал на пхп )) : nginx.ip.ban.php (требуемые расширения: Posix, MySQL). Запускается из командной строки, если ему дать права на запуск. Скрипт был написан под FreeBSD, на других системах … а на других системах нет ipfw
Настраиваемые переменные в скрипте:
$dir - путь к лог файлу
$logfile – вышеупомянутый лог файл
$email_to – высылать уведомление о бане айпи на емейл
$email_from – от кого слать письмо
$ipwhitelist – массив регекспов для айпи, которые будут игнорироваться (белый список)
$check_interval,$max_conn_per_interval,$ban_time – Если за $check_interval минут с одного айпи было $max_conn_per_interval коннектов, то забанить этот айпи на $ban_time секунд.
$keep_history – сколько дней хранить историю коннектов в мускуле
$mypidfile – файл с PID’ом процесса nginx.ip.ban.php
$pidfile – расположение PID файла nginx (чтобы корректно сбрасывать логи)
$db_host,$db_user,$db_pass,$db_name – параметры подключения к базе
Скрипт использует таблицы ipfw для бана айпи. Необходимо, чтобы модуль ipfw был уже установлен и настроен. Для функциональности нужно добавить правило ipfw:
# ipfw add 10 deny ip from table \(1\) to me
Так же позаботиться чтобы это правило не исчезало после ребута, прописав его в /etc/rc.local например.
MySQL:
Структура таблиц:
CREATE TABLE `stat` (
`ts` datetime NOT NULL,
`ip` int(11) NOT NULL,
KEY `idx` (`ts`,`ip`),
KEY `idx2` (`ip`,`ts`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
CREATE TABLE `ban` (
`ip` int(11) NOT NULL,
`ts` int(10) unsigned NOT NULL,
KEY `ip` (`ip`),
KEY `ts` (`ts`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci
В принципе все. Можно проверять работу скрипта, отстреливать баги ) В конце концов скрипт должен быть прописан в кроне от рута на выполнение каждую минуту:
/etc/crontab:
* * * * * root /root/scripts/nginx.ip.ban.php > /dev/null
Скрипт относительно умный и проверяет, не запущен ли процесс-клон. По этому беспокоиться за его размножение в памяти не стоит. Таблицы он чистит автоматически, логи тоже чистит. Следов за собой не оставляет.
Вся эта штука работает на 1 млн хитов в сутки и прекрасно себя чувствует, не позволяя китайцам взять мои сервера измором )
Посты
Большое спасибо автору. Возможно, в будущем я и правда реализую аналогичную идею.
Читал про это уже на каком то другом сайте, но у вас гораздо прикольней написано
http://www.pentarh.com/wp/wp-uploads/nginx.ip.ban.php.txt
- тут только:
#!/usr/local/bin/php
No pidfile