четверг, 1 декабря 2016 г.

IIS Request filtering против ddos-атаки

Лежим

Заказчик, чьи сайты я поддерживал ранее, обратился с тем, что сайт лежит и отдает 500 ошибку. У него стандартный сайт на ASP.NET WebForms, не скажу, что очень нагруженный, но бывали проблемы с производительностью базы данных (MS SQL Server на отдельном сервере). Недавно сервер БД поменяли и перенесли данные.
Этот сайт не основной бизнес заказчика, поэтому практически не обслуживался. У него не настроено никакого мониторинга  и сбора метрик и вообще за ним особо не следят.

Данные телеметрии

Какие аномалии бросились в глаза:
  1. Процесс w3wp использовал более 50% CPU (обычно сильно меньше).
  2. Количество потоков в этом процесс стабильно прирастало (сайт не успевал обслужить клиентов).
  3. Диск на сервере БД использовался на 100% (Active Time).
  4. Длина очереди обращений к диску с базами проекта была большой (обычно в районе нуля-единиц).
  5. Оперативная память на сервер БД использована полностью.
  6. Профайлер показал, что есть один горячий метод, который ходит в БД.

Тюнинг СУБД

Первая моя гипотеза была связана с неполадками на стороне сервера БД из-за его переноса: забыли что-то настроить, не отрабатывает джоб по сбору статистики и перестроению индекса и т.п.

Память - сразу стало ясно, что при переносе СУБД забыли ограничить использование оперативной памяти  на новом сервере - ограничиваем. По прошлому опыту этой конфигурации вполне хватало 24гб (из общих 32).

Проверям джобы - все норм. Запускаем Tuning Advisor и достраиваем недостающие индексы (среди них был и индекс для горячего запроса из профайлера).

Выхлоп близок к нулю: сайт лежит.

IIS

Захожу в логи и сразу все становится понятно - DDoS:


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

В логах видим около 200 запросов в секунду (обычные пользователи генерят до десяти в минуту по метрике).

Все запросы с разных IP, объединяет их только схожий user-agent:

GET/80101.200.177.82WordPress/4.2.2;+http://www.renwenqifei.com;+verifying+pingback+from+37.1.211.155503
GET/8054.69.1.242WordPress/4.2.10;+http://54.69.1.242;+verifying+pingback+from+37.1.211.155503
GET/80123.57.33.117WordPress/4.0;+http://www.phenomenon.net.cn;+verifying+pingback+from+37.1.211.155503
GET/8054.69.236.133WordPress/4.3.1;+http://www.the-call-button.com;+verifying+pingback+from+37.1.211.155503
GET/8052.19.227.86WordPress/4.3.6;+http://52.19.227.86;+verifying+pingback+from+37.1.211.155503
GET/8052.27.233.237WordPress/4.1.13;+http://52.27.233.237;+verifying+pingback+from+37.1.211.155503
GET/80202.244.241.54WordPress/3.5.1;+http://www.fm.geidai.ac.jp503
GET/8052.34.12.105WordPress/4.3.6;+http://52.34.12.105;+verifying+pingback+from+37.1.211.155503
GET/80128.199.195.155WordPress/4.3.6;+http://www.glamasia.com;+verifying+pingback+from+37.1.211.155503
GET/8061.194.65.94WordPress/4.2.10;+http://wpwewill.help;+verifying+pingback+from+37.1.211.155503
GET/8023.226.237.2WordPress/4.3.1;+http://hypergridder.com;+verifying+pingback+from+37.1.211.155503
GET/80104.239.228.203WordPress/4.2.5;+http://pjtpartners.com;+verifying+pingback+from+37.1.211.155503
GET/80104.239.168.88WordPress/4.2.10;+http://creatorinitiative.com;+verifying+pingback+from+37.1.211.155503
GET/80166.78.66.195WordPress/3.6;+http://remote.wisys.com/website503
GET/80212.34.236.214WordPress/3.5.1;+http://nuevavista.am503

Это известный тип атаки: WordPress сайт с включенным Pingback (включен по умолчанию), может использоваться в DDOS-атаке на другие сайты. Более подробная статья на Хабре.

Настраиваем фильтр запросов

Есть несколько уровней где можно фильтровать запросы. Первый - это файрвол. Грепаем ip - добавляем их в файрволл, по расписанию собираем вновь появившиеся. Плюсы - отличная скорость, нет мусорных запросов в логах. Минусы - надо писать скрипты и следить.

Второй уровень - сам IIS (из явных минусов - мусорные запросы попадают в логи). Третий уровень - написать модуль и использовать его. Это самый гибкий подход, но трудоемкий и имеет невысокую производительность.

Я остановился на втором уровне из соображений получить решение совершив минимум действий.

У IIS много возможностей по фильтрации запросов. В данном случае подходит Request Filtering. Более подробно об установке и настройке.

Выбираем сайт -> Request Filtering ->Rules -> Add filtering rules



И указываем, что мы хотим отфильтровать все запросы где в Header: User-Agent есть слово WordPress.



Или можно указать соответствующие настройки в файле web.config

<system.webServer>
    <security>
        <requestFiltering>
            <filteringRules>
                <filteringRule name="ddos" scanUrl="false" scanQueryString="false">
                    <scanHeaders>
                        <clear />
                        <add requestHeader="User-Agent" />
                    </scanHeaders>
                    <denyStrings>
                        <clear />
                        <add string="WordPress" />
                    </denyStrings>
                </filteringRule>
            </filteringRules>
        </requestFiltering>
    </security>
</system.webServer>

Сразу после применения этого фильтра сайт заработал. Все показатели вернулись к норме. Если бы я сразу проверил логи - на все ушло бы менее получаса.

Что еще умеет IIS?

IIS - очень крутой и производительный сервер для веб-приложений. Помимо передачи запроса в управляемую среду он много что умеет делать и по производительности сильно обыгрывает managed-решения.

В разделе Request Filtering вы можете настроить еще много различных фильтров: по методам, сегментам урла, query-параметрам, расширению и т.д. Можно запретить в asp.net проекте специфичные для PHP query-параметры (попытка получить доступ к htaccess или файлу с паролями). Можно запретить злонамеренные запросы, например, содержащие sql-инъекции. Это делается не как защита от этих атак, а в целях экономии ресурса сервера: IIS самостоятельно откинет эти запросы и сделает это быстро с минимальными затратами памяти и процессорного времени.

Еще один механизм называется IP Address and Domain Restrictions. Этот механизм позволяет составлять белые и черные списки IP-адресов для ограничения доступа к сайту. Вы можете заблокировать злобного парсера или наоборот открыть доступ на тестовый сайт или админку только с определенных IP. Более подробно читать в официальной документации.

И третий механизм, который может вам помочь противодействовать ддос-атакам и нежелательным парсерам -
Dynamic IP Address Restrictions. 
Не всегда мы можем следить за постоянно меняющимися ip-адресами злоумышленника. Но с помощью этого инструмента мы можем ограничить частоту запросов. Таким образом, IIS на аномально большое количество запросов с одного IP-адреса будет быстро отдавать 403 или 404. Будьте аккуратнее с поисковыми ботами. Официальная документация.

Выводы

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

вторник, 19 апреля 2016 г.

Как получить скрипт для всех джобов на MS SQL Server

Иногда случается, что надо перенести джобы с одного сервера на другой. Или сохранить джобы в качестве скрипта и положить в репозиторий. Если у нас всего два-три джоба, то можно использовать "Script Job As" >> "CREATE To" >> "...выберите куда...". Но что если у нас десятки джобов?

Решение


  1. Открываем Management Studio. 
  2. Выбираем SQL Server Agent - Jobs.
  3. Запускаем Object Explorer Details (нажмите F7 или в верхнем меню View - Object Explorer Details).
  4. Выделяем нужные джобы (или все, тогда просто нажимаем CTRL+A).
  5. Правой кнопкой мыши на выделенной строчке вызываем контекстное меню и далее привычный "Script Job As".



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







понедельник, 9 ноября 2015 г.

Коллекция Cookies в HttpResponse и HttpRequest

Как-то, просматривая вопросы на Stackoverflow, наткнулся на вопрос, связанный с коллекцией кук в запросе и ответе. Вкратце вопрос можно сформулировать так:
Почему после добавления куки "ABC" в Response.Cookies с новым значением в Request.Cookies["ABC"] остается лежать старое значение?
Первая же мысль - это же две различные коллекции , вот и не обновляется! Но не все так просто.


понедельник, 22 декабря 2014 г.

Тезисы по мотивам ‪#‎agilekitchen‬ и ‪#‎leancoffee.

В декабре прошло сразу два мероприятия: ‪#‎agilekitchen‬ и ‪#‎leancoffee‬. Я попробовал сформулировать несколько тезисов по итогам обсуждений:

 1. Объективности не существует. У каждого в голове своя модель реальности. Чтобы понять решения руководства, надо определить, какую модель оно использует.

 2. У каждого есть персональные цели (внутренние и установленные извне). Бывает, что эти цели противоречат вашим целям и целям организации. Люди действуют согласно собственной модели реальности и персональных целей.

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

 4. Чтобы продать изменения, надо показать, что эти изменения помогут в достижении персональных целей.

 5. Если изменения не продаются подчиненным с ними можно расставаться. Если изменения не продаются начальству с ним тоже можно расстаться.

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

 7. Аджайл многими воспринимается как универсальное обезболивающее. У вас мало разработчиков, мудацкое начальство и легаси на коболе? Внедрите Аджайл и все пройдет.

 8. Аджайл и вот это всё очень часто не нужен вашему руководству, так как не соответствует их модели реальности и их целям.

вторник, 26 февраля 2013 г.

Оценка задач. Planning Poker

Два подхода к оценке.

Наш проект уже почти полгода живет в agile-стиле. Мы пробуем различные подходы и пытаемся применять все, что нам подходит и делает жизнь проще. К сожалению, никто из нашей команды ранее полноценно не работал с использованием гибких методологий. Процесс внедрения SCRUM идет медленно и не всегда эффективно: мы сами доходим до того, что описано в статьях-книгах.

Сейчас мы меняем подход к оценки задач из product backlog. Изначально мы интерпретировали story point как некоторый идеальный человеко-день. В дальнейшем мы поняли, что данное представление не совсем корректно. На наш взгляд (и он совпадает с мнением agile-сообщества) story point - это единица измерения объема работ, но не их длительности. Отличная аналогия - выкапывание ямы. Можно оценить в днях, а можно в кубометрах.

В чем же разница?

Во-первых, многие отмечают сложность абсолютных оценок и простоту относительных. То есть человеку сложно сказать на глаз, что длина этой кровати 2,5 метра, а другой 1,98. Но в то же время, если перед глазами стоит двухметровая кровать, достаточно легко сказать, первая больше эталона, а вторая примерно такая же. Так и с задачами: иногда бывает сложно оценить задачу, но достаточно легко сказать, что задача xxx примерно такая же как и zzz. Или что задача aaa значимо сложнее bbb.

Второе преимущество относительной оценки заключается в том, что мы можем наблюдать прогресс команды и обосновывать вложения в инфраструктуру. Развертование билд-машины, возврат технического долга не несут, на первый взгляд, бизнес-велью. Но если показать, что эти траты привели к тому, что команда за итерацию стала успевать делать 35 SP вместо 30, так как не надо руками выкладывать по полдня, не надо с бубном танцевать вокруг старого костыля, то продукт-менеджер примет затраты на погашение технического долга и развитие инфраструктуры. То же самое с прогрессом команды. Команда растет и за спринт успевает произвести большее количество работ (выкопать яму большего объема).

Список эталонных работ

Мы пока не дошли в полной мере до этого метода. Суть его проста: на планировании перед глазами держать список эталонных работ. Мы используем карты с числами Фибоначчи: 0, 0.5, 1, 2, 3, 5, 8... Задачи более 5 под запретом. Нам надо подготовить список для каждой оценки из верно оцененных задач прошлых спринтов. Таким образом, каждый участник при оценке может аргументировать свою оценку тем, что эта задача по сложности похожа на такую-то задачу из списка, поэтому я поставил эту оценку. Или, эта задача сложнее этой задачи. Если оценка падает между двух карт, то оцениваем в большую сторону.

понедельник, 31 декабря 2012 г.

SCRUM: четыре итерации спустя

SCRUM: четыре итерации спустя.

В октябре команда проекта Zarplata.ru перешла на скрам, предпосылки и ожидания я описал ранее. За прошедший квартал мы провели четыре спринта, старались следовать рекомендациям и общепринятым установкам. Наши договоренности остались в силе: все спринты были трехнедельными, был инженерный день, ретро и планирование.

Что было хорошего?

После четырех спринтов можно провести ретроспективу. Две основные причины перехода: планирование и постановка. В решении данных проблем у нас огромный прогресс.
Планирование. Скрам устанавливает количество работ в спринте. Так как мы выбрали относительно небольшую длительность спринта - у нас не возникало тяжеловесных срочных задач. Были мелкие задачи, которые мы делали в промежутках, но их было немного.

Постановка задач. Мы тратим полдня на планирование спринта. Постановка задач на первую итерацию была очень некачественной, возникало огромное количество вопросов тестировщика и программистов. На первой ретроспективе основной темой обсуждения были постановка задач и уточнение требований. В итоге требования стали лучше, формат требований изменился и стал более конкретным. Мы на планировании обсуждаем зачем задача нужна, проговариваем сценарии использования, значимые моменты реализации. Все это позволяет нам лучше понимать задачу, точнее оценивать задачи.

Внедрение методологии привело к тому, что мы стали лучше понимать, что нам мешает быть более продуктивными, что может помочь повысить качество выпускаемого продукта. Был выявлен ряд проблем с тестированием. Тестирование, как и разработка велись без какой-либо внятной методологии. Сейчас мы пришли к тому, что необходимы тест-кейсы, автоматизированное тестирование, тестирование требований. В целом, роль тестировщика в agile-команде меняется. Мы стали чаще общаться с командой тестирования. Дальнейшие шаги будут направлены на внедрение приемочных тестов и их частичную автоматизацию.

Что надо улучшить?

Приемочные тесты - важная часть завершения задачи. Мы договорились, что к каждой задаче будем писать несколько ключевых сценариев использования в стиле BDD. Данные сценарии должны в дальнейшем лечь в основу автотестов и живой документации проекта. 

Как ни прискорбно, но у нас до сих пор нет юнит-тестирования. Надеюсь, что мы начнем использовать TDD или BDD при написании кода.

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

Технический долг, незакрытые баги. Необходимо закрыть все баги в TFS. Часть из них уже неактуальна, но тем не менее надо проверить, закрыть устаревшие, решить существующие. Данная мера позволит использовать баг-трекер более продуктивно. С техническим долгом также надо работать. В середине года мы начали работы по анализу 500 ошибок сайта. Также в коде было множество поглощаемых исключений. Каждое такое место мы начали логировать. Анализ логов также позволил закрыть ряд ошибок. В итоге количество 500 ошибок снизилось в несколько раз. Логи также не сильно пухнут от ошибок. Но эту работу необходимо продолжать.

Планирование на год. Есть идея завести несколько показателей и следить за их достижением в течение года. Количество пользователей, количество откликов, количество объявлений и т.д.

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

P.S. Так получается, что этот пост дописываю 31 декабря. С Новым годом! Новых вызовов, новых задач, новых достижений!

пятница, 28 сентября 2012 г.

Внедрение методологии SCRUM - первая итерация

Команда.

С первого октября 2012 года мы начинаем использовать скрам. Команда на первую итерацию: 1 тестировщик и два программиста. Верстка и дизайн за границами (почти не потребуется).

Наши договоренности.

Как мы договорились: трехнедельные спринты, последний день спринта - инженерный, DoD пока отсутствует, но я надеюсь, что мы придем к хорошему определению и зафиксируем его. Пока что, под "Выполнено" подразумевается все протестировано и выложено на боевой (если требуется),

Почему мы переходим на скрам? 

Мы использовали квартальные планы, но новые задачи постоянно пытались сломать наши планы. Поэтому первое, что я ожидаю - более точное планирование. Также спринт жестко очерчивает список работ над которыми мы работаем, каждый в команде знает над чем работать. Как результат, более гладкий график нагрузки, команда ритмично поставляет выполненные задания, отсутствуют завалы и свободные дни.

Другие причины.

Второй ожидаемый эффект: нормальная постановка задач и проработка требований на этапе планирования. Сейчас ставятся задачи на квартал, а потом специфицируются требования. Теперь задачи будут сразу с требованиями - не факт, что все будет заморожено на три недели, но все же добавляется уверенности в завтрашнем дне.

Пока все, отпишусь по итогам итерации.