Системное администрирование

индекс
199,95

Блокировка ботов и нежелательных пользователей на уровне вебсервера nginx

У меня, да и думаю у вас, логи веб-сервера частенько забиваются запросами вида:

62.193.233.148 - - [28/May/2009:18:20:27 +0600] "GET /roundcube/ HTTP/1.0" 404 208 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5"
62.193.233.148 - - [28/May/2009:18:20:28 +0600] "GET /webmail/ HTTP/1.0" 404 206 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5"
212.150.123.234 - - [29/May/2009:20:51:12 +0600] "GET /admin/main.php HTTP/1.0" 404 212 "-" "-"
212.150.123.234 - - [29/May/2009:20:51:12 +0600] "GET /phpmyadmin/main.php HTTP/1.0" 404 217 "-" "-"
212.150.123.234 - - [29/May/2009:20:51:12 +0600] "GET /phpMyAdmin/main.php HTTP/1.0" 404 217 "-" "-"
212.150.123.234 - - [29/May/2009:20:51:13 +0600] "GET /db/main.php HTTP/1.0" 404 209 "-" "-"
212.150.123.234 - - [29/May/2009:20:51:13 +0600] "GET /PMA/main.php HTTP/1.0" 404 210 "-" "-"
212.150.123.234 - - [29/May/2009:20:51:14 +0600] "GET /admin/main.php HTTP/1.0" 404 212 "-" "-"
212.150.123.234 - - [29/May/2009:20:51:14 +0600] "GET /mysql/main.php HTTP/1.0" 404 212 "-" "-"
212.150.123.234 - - [29/May/2009:20:51:15 +0600] "GET /myadmin/main.php HTTP/1.0" 404 214 "-" "-"
212.150.123.234 - - [29/May/2009:20:51:15 +0600] "GET /phpadmin/main.php HTTP/1.0" 404 215 "-" "-"
212.150.123.234 - - [29/May/2009:20:51:16 +0600] "GET /webadmin/main.php HTTP/1.0" 404 215 "-" "-"


В основном это боты, бывают и пользователи, которые сканируют сервер на наличие всяких папок, ищут уязвимости.
Так вот захотелось блокировать эти IP-адреса сразу после попытки сканирования сервера, средствами nginx.


На помощь приходит geo модуль нжинкса.

Сперва прописываем в секции location новый log_format вида «IP-адрес 1;», который поймет geo модуль:

log_format deny '$remote_addr 1;';


в http секции пишем:

geo $deny {
default 0;
include /www/logs/deny;
}



Это позволит считывать нам файл /www/logs/deny и брать список IP-адресов для блокирования.

Теперь в location секции описываем «плохие» ситуации, когда IP-адрес необходимо заблокировать, например:

set $ua $http_user_agent;

if ($ua ~* wget) {
access_log /www/logs/deny deny;
return 403;
}

if ($ua ~* curl) {
access_log /www/logs/deny deny;
return 403;
}

if ($request ~* "webadmin") {
access_log /www/logs/deny deny;
return 403;
}

if ($request ~* "\/admin\/main.php") {
access_log /www/logs/deny deny;
return 403;
}


В итоге плохие запросы и юзерагенты попадают в файл /www/logs/deny в виде «IP-адрес 1;», и при перечитывании конфигурации IP-адрес будет заблокирован.

Остается только закинуть в крон команду нжинксу раз в 1-5-10 минут(когда необходимо) перечитывать конфиг, и списку заблокированных IP-адресов будет запрещен доступ к серверу.

По Сысоеву это выглядит так:
kill –HUP `cat /var/log/nginx/nginx.pid`

Наполняйте список правил «плохими» запросами, и сам чёрт вам не брат!
+19
10 июня 2009, 10:51
78

комментарии (45)

+5
Roxis #
Зачем блокировать wget и curl?

и вместо if'ов есть location'ы
location ~* webadmin {}
location ~* /admin/main\.php {}
+17
arty #
да вообще всё банить, кроме эксплорера! ишь, выдумали, в моём интернете чем попало ковыряться!; )
–15
Neiro #
Билл? Гей? тсссс… :)
–8
Neiro #
Минусующим: сорри за флуд, но данную статью считаю полной ерундой! заминусуйтесь!
Да, кстати, забыл перед своей первой фразой поставить (с)…
+4
sadsanta #
Да, убивать надо таких параноиков.
Хорошо, что у wget есть флаг -U.

Да и в общем-то, когда мне надо сграбить какой-то сайт, первое что я делаю — это выставляю все заголовки курла аналогичными заголовкам IE.

В общем защита от дурака, помогающая админам-параноикам не наблюдать кучу ошибок 404 в логах, но усложняющая некоторым посетителям жизнь.
+2
point #
kill –HUP `/var/log/nginx/nginx.pid`
как-то подозрительно выглядит. Может быть так
kill –HUP `cat /var/log/nginx/nginx.pid`
0
myiworm #
спасибо, опечатался
+2
mstarrr #
Чтобы не опечатываться я nginx reload юзаю.
Эфект тот же.
–1
elfxf #
в Mac'ах не работает, кажись :(
0
niksite #
Ещё бы для апача что-либо сходное :o\
0
syndicut #
mod_security?
+6
mstarrr #
Банить нужно не хттп сервером, тем более не апачем. Ну какой смысл вместо 404 показывать forbidden тем же вебсервером?

Если уж банить айпишники — то фаерволом, чтобы до веба не доходили. А так это — ковыряние админа в песочнице, типа размяться от нечего делать.
+1
cyberzx #
есть такая замечательная программка fail2ban. хорошо подходит для данных целей

fail2ban.sourceforge.net
0
greyhard #
этож сколько регекспов появится в nginx, вагон и маленькая тележка, и если там не один хост ) а десяток, тут уж и лог до мега вырастет
+3
kns #
222.124.169.117 - - [07/Jun/2009:23:08:15 +0400] "GET /roundcube//bin/msgimport HTTP/1.1" 404 169 "-" "Toata dragostea mea pentru diavola"
86.34.172.222 - - [08/Jun/2009:14:31:27 +0400] "GET /user/soapCaller.bs HTTP/1.1" 404 169 "-" "Morfeus Fucking Scanner"


Вместо вгета с курлом я бы добавил вот этих. :)
+3
ooprizrakoo #
Проблема в том, что если сканят из большой подсети, то можно слишком много юзверей заблокировать таким образом. У моего провайдера порядка 1000 юзверей на одном гейтовом ипе сидят. И один «какир» может таким образом многих «подставить» многих людей — и юзверей, и администрацию сайта, который потеряет пользователей.

Как бы «поумнее» сделать защиту?..
0
bullgare #
может на время блокировать (по времени последнего обращения к плохой страничке)?
минут на 5.
а лучше на полминуты.
+5
sadsanta #
А нафига вообще блокировать?
Если это сканер обращающийся к несуществующим в большинстве своем страницам, то нагрузка на сервер должна быть минимальна.
Если это хакер, то он и без сканера дыры найдет.

А если ресурс позволяет выкладывать картинки пользователям (например блоги), то зная о таких методах «обороны» можно вообще добрую часть посетителей загнать в черный список… например, так: <img src="/admin/main.php" />
0
bullgare #
я просто предложил ответ на заданный вопрос.
без рассуждений о том «зачем это надо».
+1
sadsanta #
А я предложил порассуждать.
Не вам лично. Всем тем, кто спрашивает как блокировать несчастных пользователей.
0
SCoon #
Запостил ниже свой комментарий, не заметив Вашего. Sorry.
+1
myiworm #
Можно дописать модуль, который будет возвращать например хеш от IP+USERAGENT, этот хэш использовать при проверке, его же записывать в deny файл.
Раз в час очищать deny файл, а лучше брать последние X строк от deny файла, например даже 50% файла.
+1
SCoon #
Вы полагаете, для научения робота отдавать на каждый запрос уникальный USERAGENT требуется более 10 минут?

Признаться, я уже лет десять не видел роботов спорной этичности, которые бы использовали фиксированный USERAGENT. Такие еще остались в природе?

А при переменном USERAGENT хэш теряет практический смысл.
0
myiworm #
Вы знаете другой точечный способ различить одного клиента от другого с одного ip, если знаем о них только ip и юзерагент строку?
0
SCoon #
Такого способа не существует. Обращаю внимание: не я его не знаю. Его вообще нет.
0
myiworm #
Я знаю.
Поэтому в ситуации, когда не желательно банить целую сетку из-за одного бота, вариант с хешем хоть как то будет решением.
0
SovGVD #
Есть какой то более красивый способ блокировки «на лету» и/или по юзерагенту, определенным запросам?
0
brutaler #
помойму это больше подходит не для web-разработки, а для системного администрирования или же блога nginx
0
myiworm #
спасибо, перенёс
+11
SCoon #
Коллега, я надеюсь, что Вы осознаете, что заделав довольно спорной опасности дыру Вы одновременно создали новую, причем более опасную. Фактически, Вы сделали свой сайт уязвимым к DOS. Механика атаки проста: злоумышленник заходит на насколько десятков/сотен/тысяч — в соответствии со своей зловредностью — форумов, посетители которых являются и вашими потенциальными посетителями, и на каждом размещает нейтральное, не нарушающее правил сообщение в которое вставляет картинку с адресом из вашего волшебного списка. Результат: все посетители этих сайтов, которые прочтут сообщение, автоматически попадут в Ваш отказный список. Зачастую — целыми сетями.

DOS в чистом виде. Просто. Красиво.

P.S. Сразу уточню, что бороться с этим анализом HTTP_REFERER — бесполезно.
0
myiworm #
Список можно очищать раз в 30 минут, можно оставлять последние N адресов в период времени, я бы не назвал этот способ атаки простым:)
0
SCoon #
Отлично. А вот теперь вопрос: ОТ ЧЕГО мы защитимся при этом? Исходное решение позволяло — если забыть про все drawbacks — опознать вредоносный скрипт ДО того, как он найдет нашу реальную — и пока неизвестную нам — уязвимость. В варианте с очисткой это достоинство исчезает.

Ok. А что у нас тогда остается?
0
myiworm #
Я не видел процессов сканирования, которые бы затягивались больше чем на полчаса. Достаточно выхватить бота, дать ему 403(500, 666) ответ в течении получаса, и он останет. Никакой панацеи, никаких революции я не предлагал.
Ещё один сраный способ забанить бота, не более.
+3
recompileme #
В nginx есть возможность более простым способом защититься от сканеров, ботов и прочей нечисти.
1. В секции http прописываем зоны:

limit_zone na_xuy $binary_remote_addr 5m;
limit_req_zone $binary_remote_addr zone=v_pizdu:5m rate=30r/m;

2. В секции location — активируем нужные зоны:

limit_conn na_xuy 5;
limit_req zone=v_pizdu burst=5;

Только что мы поставили ограничение на 5 одновременно открытых сессий с одного айпи с лимитом ползапроса в секунду. При превышении пользователь будет временно заблокирован (регулируется параметром burst)
Параметры подробно описаны на сайте Сысоева.
+1
recompileme #
Ломается сканом через список анонимных проксей кстати. Я просто с другой стороны барикад смотрю, и могу ответственно заявить что такую защиту ломать геморней всего.
0
Odes #
Не хочу вас расстраивать но у меня опера в данный момент поддерживает до 128 одновременных соединений (а значит и сессий с одного айпи)
А по умолчанию там стоит параметр 8.
В общем придёт человек с быстрым каналом и всё бан тебе родимый по айпи. Уйдёт на другой «неглючащий» сайт. Селя ви.
0
recompileme #
Описанным мною образом разумные люди не весь сайт закрывают, а определенную зону, описанную в секцию location. Например, location /mp3/ {… }
Если поставить на весь сайт — конечно можно навредить.
0
Newton #
Я правильно понял, что айпишники у вас блокируются навсегда, и потом другие пользователи того же провайдера с динамическим айпи долго гадают, чего же они не могут попасть на ваш замечтательный сайт?
0
myiworm #
да нет же, tail -n 100 deny > deny раз в 30 минут вполне достаточно
–1
evil_random #
Какой-то корявый велосипедик получился.
Жалко вам что-ли 404 показать?
0
catap #
Чем вам мой is_bot не нравится? catap.ru/blog/2008/12/03/nginx-is_bot/
0
mobilz #
принцип расскажите, я слишком пьян, чтобы читать Си сейчас.
0
mobilz #
На личном опыте пришел к тому, что лишь боты и пользователи прокси не загружают картинок. + боты чаще юзают http 1.0, ибо он быстрее. А еще боты не видят JS, т.е. если все ссылки на странице имеют доп. параметр &bot=1, а JS его убирает, то лишь боты и пользователи без JS будут юзать этот параметр. А еще я пришел к выводу, что эффективнее всего «на лету» определять бота и блокировать его на время.
0
Odes #
А почему бы не использовать патерны?
«GET /admin/main.php HTTP/1.0»
«GET /phpmyadmin/main.php HTTP/1.0»
«GET /mysql/main.php HTTP/1.0»
0
Odes #
Хм что-то полкомента исчезло, как не было
Продолжим тут.
Если сканируют эти каталоги, то например можно при 1-2 такой попытке QoS для данного ip снизит до минимума.
При попытках более 10 — редирект на html страницу со всех страниц сервера «Вам ограничен доступ...» контактный e-mail, всё.
Вроде и железобетонно и никто кроме ботов не страдает.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.