Защита web сервера от программ для ddos атак

Thank you for reading this post, don't forget to subscribe!

есть сер­вер 2 ярда, 8 гигов опе­ра­ти­вы и ssd диск.

На сер­ве­ре раз­вер­нут wordpress сайт с неко­то­рым содер­жи­мым. И есть у нас вре­ди­тель, кото­рый на сво­ем сер­ве­ре запус­ка­ет про­стой тест от apache на про­из­во­ди­тель­ность веб сервера:

Все­го лишь 50 парал­лель­ных пото­ков. мы видим на сво­ем веб сер­ве­ре рос LA

Сер­вер загру­жен на 100%. И хотя он нор­маль­но обра­ба­ты­ва­ет запро­сы и в целом кор­рект­но рабо­та­ет. Даже не очень тор­мо­зит, но все рав­но это пло­хо. А если будет 3 сер­ве­ра и по 100 пото­ков на каж­дом? Нет ника­ких про­блем даже на тест взять у раз­ных хосте­ров по вир­ту­аль­ной машине и запус­кать на них подоб­ные шту­ки, ими­ти­руя ддос атаку.

В общем, если вы совсем не сде­ла­ли ника­кой защи­ты на сво­ем сер­ве­ре, то любой чело­век смо­жет вам без осо­бых про­блем доста­вить неко­то­рые неудоб­ства. Защи­тить­ся от такой «ата­ки» не слож­но. Даль­ше я рас­ска­жу как это сделать.

Защита от ddos с помощью iptables

Для защи­ты от про­стей­шей ата­ки мы будем исполь­зо­вать firewall — iptables, модуль ядра ipset для хра­не­ния боль­ших спис­ков ip и само­пис­ные скрип­ты. По фаер­во­лу смот­ри­те мою ста­тью — настрой­ка iptables. Здесь я не буду на этом останавливаться.

Вопрос настрой­ки ipset я подроб­но рас­смат­ри­вал в сво­ей ста­тье по бло­ки­ров­ке ботов по стра­нам. Сове­тую посмот­реть мате­ри­ал, так как он напря­мую свя­зан с этой ста­тьей и допол­ня­ет ее.

Итак, при­сту­пим к созда­нию нашей про­стой защи­ты от dos ата­ки с боль­шим коли­че­ством под­клю­че­ний с одно­го ip адре­са. Для нача­ла про­ве­рим коман­ду, кото­рая пока­жет нам коли­че­ство под­клю­че­ний с каж­до­го ip адреса:

У меня полу­ча­ет­ся при­мер­но так. Мно­го еди­нич­ных под­клю­че­ний. Идет штат­ная рабо­та веб сер­ве­ра, никто на него не ломит­ся десят­ка­ми под­клю­че­ний. Теперь нагру­зим наш сер­вер мно­же­ствен­ны­ми пара­зит­ны­ми запро­са­ми и еще раз посмот­рим вывод команды.

в самом низу выво­да этой коман­ды будет нару­ши­тель, пыта­ю­щий­ся орга­ни­зо­вать дос ата­ку на наш сер­вер. Теперь нари­су­ем скрипт, кото­рый будет бло­ки­ро­вать всех кто уста­нав­ли­ва­ет более 50-ти одно­вре­мен­ных соеди­не­ний с сайтом.

В прин­ци­пе, ком­мен­ти­ро­вать тут осо­бо нече­го. Берем спи­сок под­клю­че­ний, кото­рый толь­ко что выве­ли, в нем срав­ни­ва­ем первую колон­ку, если она боль­ше 50, то резуль­тат вто­рой колон­ки, где запи­сан ip адрес, пере­да­ем в файл.

Далее чита­ем этот файл и добав­ля­ем все ip адре­са из него в ipset спи­сок под назва­ни­ем much_conn. Пред­ва­ри­тель­но его надо создать. Подроб­но об этом я рас­ска­зы­вал в ста­тье, на кото­рую при­вел ссыл­ку выше, но повто­рю еще раз здесь:

Посмот­реть содер­жи­мое спис­ка мож­но командой:

Теперь нуж­но доба­вить в iptables пра­ви­ло, по кото­ро­му будут бло­ки­ро­вать­ся все под­клю­че­ния из ука­зан­но­го спис­ка ipset.

Все, мы забло­ки­ро­ва­ли всех, кто созда­ет мас­со­вый спам под­клю­че­ний к сер­ве­ру. Огра­ни­че­ние в 50 под­клю­че­ний може­те исправ­лять по месту, воз­мож­но его нуж­но будет умень­шить, если кто-то будет откры­вать мень­ше под­клю­че­ний с одно­го ip.

Един­ствен­ный момент, о кото­ром хочу ска­зать. Сам я не про­ве­рял, сколь­ко под­клю­че­ний откры­ва­ют поис­ко­вые боты, когда при­хо­дят на сайт. Я подо­зре­ваю, что явно не 50 и даже не 30, но навер­ня­ка я не про­ве­рял. В общем, будь­те акку­рат­ны, когда исполь­зу­е­те это средство.

Дан­ный скрипт мож­но засу­нуть в крон и запус­кать каж­дую мину­ту. Но лич­но я бы так не стал делать. Я реко­мен­дую мони­то­рить ресур­сы сер­ве­ра и запус­кать подоб­ные сред­ства, толь­ко если сер­вер рабо­та­ет на пре­де­ле сво­их воз­мож­но­стей и вы вруч­ную зашли и убе­ди­лись, что вас кто-то спа­мит под­клю­че­ни­я­ми. После это­го вру­бай­те на какое-то вре­мя дан­ный скрипт по кро­ну. Когда ddos пре­кра­тит­ся, отключайте.

Было бы непло­хо как-то авто­ма­ти­че­ски очи­щать спи­сок заба­нен­ных, уда­ляя отту­да тех, кто уже сут­ки к вам не под­клю­ча­ет­ся, но это силь­но услож­ня­ет зада­чу. Нуж­но как мини­мум вести лог по бло­ки­ру­ю­ще­му спис­ку, сохра­нять вре­мя послед­не­го обра­ще­ния. Обра­ба­ты­вать все это, высчи­ты­вать. В общем, зада­ча хоть и не силь­но слож­ная, но уже не три­ви­аль­ная. Мне не захо­те­лось этим заниматься.

Есть хоть и не очень изящ­ное, но про­стое реше­ние этой про­бле­мы. Создать спи­сок ipset с задан­ным вре­ме­нем жиз­ни запи­си с помо­щью timeout. Напри­мер вот так:

В дан­ном слу­чае запись с заба­нен­ным ip в спис­ке ipset будет хра­нить­ся в тече­нии 3600 секунд или 60 минут.

Нуж­но пони­мать, что в дан­ном при­ме­ре с 1 ip адре­сом исполь­зо­вать ipset нет ника­ко­го смыс­ла, мож­но сра­зу банить сред­ства­ми само­го iptables. Ipset нужен толь­ко тогда, когда этот спи­сок хотя бы в сот­ни строк. Если там несколь­ко десят­кой адре­сов, хва­тит и одно­го iptables.

Анализ лог файла web сервера для защиты от ddos

Рас­смот­рим еще один про­стой, но все же более слож­ный тип ддос ата­ки, когда идут типо­вые запро­сы с раз­ных IP. То есть про­стой бот­нет, может быть даже собран­ный рука­ми из несколь­ких деше­вых vds сер­ве­ров. Одно­вре­мен­ных под­клю­че­ний будет не мно­го, но если у вас тяже­лый сайт и зло­умыш­лен­ник най­дет его сла­бое место (напри­мер поиск), то это­го может быть доста­точ­но, что­бы поло­жить сайт.

Банить будем тоже через iptables, а спи­сок адре­сов для бана будем извле­кать из логов веб сер­ве­ра. Для это­го у вас долж­но быть вклю­че­но логи­ро­ва­ние запро­сов к веб сер­ве­ру. Напри­мер, в nginx за это отве­ча­ет такая настрой­ка вир­ту­аль­но­го хоста:

Мы не будем каж­дый раз ана­ли­зи­ро­вать весь лог файл. Эта опе­ра­ция сама по себе будет силь­но нагру­жать веб сер­вер. Возь­мем послед­ние 1000 строк из лог фай­ла и посчи­та­ем коли­че­ство под­клю­че­ний с одно­го ip с типо­вым содер­жи­мым, напри­мер запрос глав­ной стра­ни­цы по про­то­ко­лу http 1.0, «GET / HTTP/1.0». Если вы заме­ти­те дру­гой посто­ян­ный при­знак бот­не­та, кото­рый вас ата­ку­ет, исполь­зуй­те его. Это может быть один и тот же user agent или что-то еще. Допу­стим, если ата­ку­ю­щий будет дол­бить в уяз­ви­мое место, то это будет адрес этой страницы.

В дан­ном слу­чае я исполь­зо­вал немно­го дру­гое усло­вие и про­сто вывел спи­сок всех тех, кто сту­чал­ся на глав­ную стра­ни­цу. Но уже тут вид­но нару­ши­те­ля, кото­ро­го мож­но забанить.

Рису­ем похо­жий на преды­ду­щий скрипт для авто­ма­ти­че­ской бло­ки­ров­ки тех, кто отправ­ля­ет слиш­ком мно­го запро­сов на наш сайт и созда­ет про­бле­мы с про­из­во­ди­тель­но­стью. Повто­рюсь еще раз, если про­блем с про­из­во­ди­тель­но­стью нет, я не реко­мен­дую делать лиш­них движений.

Здесь дела­ем то же самое, что и рань­ше. Те, кто сде­ла­ли более 50-ти оди­на­ко­вых запро­сов по нашей мас­ке на послед­ние 1000 строк в лог фай­ле, отправ­ля­ют­ся в бан.

Не забудь­те создать отдель­ный спи­сок в ipset и доба­вить отдель­ное пра­ви­ло в ipables. Мож­но исполь­зо­вать уже суще­ству­ю­щий спи­сок и добав­лен­ное пра­ви­ло из преды­ду­ще­го при­ме­ра, но я реко­мен­дую все раз­де­лять. Так удоб­нее для после­ду­ю­ще­го анализа.

Во вре­мя ddos ата­ки добав­ля­е­те это пра­ви­ло в cron и выпол­ня­е­те каж­дую мину­ту. После завер­ше­ния ата­ки скрипт мож­но отклю­чить. В прин­ци­пе, мож­но и на посто­ян­ку остав­лять, но тут нуж­но хоро­шень­ко поду­мать и при­ки­нуть, как оно долж­но выгля­деть. Глав­ный прин­цип — не навредить.

Баним ботов с неправильным referer

Есть кате­го­рия про­стых ботов, кото­рые под­став­ля­ют в referrer либо мусор, либо кри­вые урлы без http или https в нача­ле. Напри­мер вот такие:

Кор­рект­ное поле referer долж­но содер­жать либо http, либо https, либо быть пустым. Все, что ина­че, мож­но сме­ло бло­ки­ро­вать или воз­вра­щать ста­тус ошиб­ки. Добав­ля­ем при­мер­но такую кон­струк­цию в кон­фи­гу­ра­цию вир­ту­аль­но­го хоста, в раз­дел server {}.

После это­го про­верь­те кон­фи­гу­ра­цию nginx и пере­чи­тай­те ее.

Если вас доста­ет какой-то бот с кон­крет­ным referer, мож­но заба­нить имен­но его. Для это­го мож­но допол­нить усло­вие, или изме­нить. Напри­мер, вот так:

В допол­не­ние, мож­но всех этих ботов с помо­щью про­сто­го скрип­та банить на iptables, как в при­ме­рах выше. К сло­ву ска­зать, их мож­но банить сра­зу, раз­би­рая http запро­сы еще до того, как они будут попа­дать к nginx, напри­мер, с помо­щью ngrep, но это более слож­ная зада­ча. Не все это уме­ют делать, там есть нюан­сы, а с nginx зна­ко­мы все. Не соста­вит боль­шо­го тру­да реа­ли­зо­вать дан­ный метод.

Защита от ддос с помощью модулей nginx — limit_conn и limit_req

Поде­люсь еще одним про­стым спо­со­бом сни­зить нагруз­ку на сер­вер и частич­но защи­тить­ся от ддос с помо­щью моду­лей nginx — limit_conn и limit_req. Настро­ить их не слож­но, частич­но резуль­тат рабо­ты пер­во­го моду­ля будет пере­се­кать­ся с пер­вы­ми дву­мя спо­со­ба­ми ddos защи­ты, опи­сан­ны­ми в нача­ле. Он более про­стой для настрой­ки, так что если не спра­ви­лись с теми спо­со­ба­ми, мож­но попро­бо­вать этот.

Смысл дан­ных моду­лей в том, что один может огра­ни­чить одно­вре­мен­ное коли­че­ство раз­ре­шен­ных соеди­не­ний с сай­том, а дру­гой коли­че­ство соеди­не­ний в еди­ни­цу времени.

Я огра­ни­чу в сво­ем при­ме­ре коли­че­ство одно­вре­мен­ных под­клю­че­ний к сай­ту с одно­го ip чис­лом 50, а коли­че­ство одно­вре­мен­ных запро­сов к дина­ми­че­ско­му кон­тен­ту не более 2-х в секун­ду. При этом будет раз­ре­шен всплеск (burst) запро­сов до 5-ти. Объ­яс­ню, как пони­мать этот всплеск, так как сам не сра­зу понял, что кон­крет­но он означает.

Если у нас идет пре­вы­ше­ние коли­че­ства уста­нов­лен­ных запро­сов в секун­ду, то их выпол­не­ние задер­жи­ва­ет­ся, и они выстра­и­ва­ют­ся в оче­редь на испол­не­ние с ука­зан­ной ско­ро­стью. Раз­мер этой оче­ре­ди и равен зна­че­нию всплес­ка. Все запро­сы, кото­рым не хва­тит места в оче­ре­ди, будут завер­ше­ны с ошиб­кой.  То есть, если запро­сов будет 4 в секун­ду, то 2 выпол­нят­ся сра­зу и еще 2 вста­нут в оче­редь. А если будет 10, то 2 выпол­нят­ся сра­зу, 5 вста­нут в оче­редь на выпол­не­ние по 2 шту­ки в секун­ду, а осталь­ные будут завер­ше­ны с ошибкой.

Исхо­дя из этих усло­вий, огра­ни­че­ние на под­клю­че­ния нуж­но уста­но­вить в кон­тек­сте server, а на доступ к дина­ми­че­ско­му кон­тен­ту в соот­вет­ству­ю­щем location. При этом опи­са­ние зон, кото­рые будут исполь­зо­вать дирек­ти­вы, нуж­но рас­по­ло­жить в http.

Вот при­мер кон­фи­га nginx для реа­ли­за­ции уста­нов­лен­ных огра­ни­че­ний с целью защи­ты от ддос атак.

После это­го пере­за­пу­сти­те nginx и про­верь­те как рабо­та­ют лими­ты. Огра­ни­че­ние на коли­че­ство выпол­ня­е­мых дина­ми­че­ских запро­сов мож­но уви­деть, про­сто нажи­мая очень быст­ро F5 в бра­у­зе­ре. Если буде­те доста­точ­но быст­ры, то ско­ро уви­ди­те кар­тин­ку с 503 ошибкой

и запись в логе с ошибками:

Лимит на коли­че­ство под­клю­че­ний може­те про­ве­рить той же ути­ли­той ab, о кото­рой я рас­ска­зал во введении.

Толь­ко не забы­вай­те, что тест нуж­но запус­кать не на кон­крет­ную стра­ни­цу, тогда вы попа­де­те на огра­ни­че­ние выпол­не­ния дина­ми­че­ско­го кон­тен­та, а на что-то дру­гое. Напри­мер, как в моем при­ме­ре, на картинку.

При выстав­ле­нии огра­ни­че­ний, не забудь­те про­кон­тро­ли­ро­вать, не попа­да­ют ли в эти огра­ни­че­ния поис­ко­вые боты. По-умол­ча­нию, они ста­ра­ют­ся не созда­вать повы­шен­ную нагруз­ку на сайт. При жела­нии, робо­ту яндек­са мож­но ука­зать через robots.txt, с какой ско­ро­стью ска­ни­ро­вать ваш сайт. А робо­ту гуг­ла то же самое мож­но сде­лать через webmaster.