Статистика DDoS-атак показывает неизменный рост и смещение вектора с сетевого уровня на уровень приложений.
![image](https://habrastorage.org/r/w780q1/getpro/habr/post_images/468/9b1/24e/4689b124e9c3bb94dce8c3d48ed104d9.jpg)
Если у Вас есть небольшой сайт на сервере с минимальными характеристиками, то положить его можно любым вполне легальным средством стресс-тестирования. (Не рекомендую этого никому делать т.к. IP-адрес легко вычисляется и экспериментатор может влететь на возмещение ущерба.) Поэтому сайт без защиты от DDoS очень скоро будет выглядеть так же дико, как компьютер с Windows-98 без анивирусника.
Первое, что можно и нужно сделать для защиты сайта — настроить брандмауэр iptables. Я использую почти без изменений настройки iptables из статьи на сайте одного из поставщиков защиты от DDoS-атак. Единственное что я поменял — увеличил число допустимых соединений в правилах #8 и #10.
Прежде чем запускать на выполнение скрипт, меняющий параметры iptables, нужно убедиться, что есть альтернативная возможность сбросить эти параметры в начальное состояние. Т.к. если правила заданы неверно, к серверу не сможет подключится никто, в том числе и администратор.
Брандмауэр iptables контролирует атаку на сетевом уровне. Следующее что необходимо настроить — это веб-сервер. В качестве веб-сервера, который открыт для доступа из интернет будем рассматривать nginx. В файле nginx.conf нужно увеличить лимиты на колчество файлов и открытых коннектов (пример взят из Википедии):
Далее настраиваем сервер по умолчанию, который будет запрещать доступ для тех устройств (например IoT), который будут обращаться по IP-адресу а не по доменному имени:
Так же в nginx можно настроить некоторые лимиты на количество обращений, но такая настройка будет не очень гибкой и совсем не избирательной. Наша цель сделать такую защиту на уровне веб-сервера, чтобы погасить запросы злоумышленников, но пропускать на сервер запросы добропорядочных пользователей.
Чтобы не пересказывать уже имеющийся на Хабре материал, предлагаю ознакомится с отличной статьей, а так же с модулем автора указаной статьи kyprizel/testcookie-nginx-module. То, что позволяет сделать этот модуль уже хорошо. Но если Вам понадобится модернизировать его — то сделать это будет непросто.
На сегодняшний день очень многие поставщики услуг защиты от DDoS используют сервер openresty (связка nginx + Lua от Taobao). Скорость выполнения хорошего кода на Lua немного уступает хорошему коду на С. Но разрабатывать на Lua быстрее и проще, и к тому же скрипты можно менять без перекомпиляции сервера. При следуюшем рестарте они будут прочитаны, скомпилированы LuaJIT, и это все что требуется.
Подробная инструкция как уcтановить optnresty. После установки продолжаем настраивать nginx. В разделе http определяем нужные параметры для работы скритов Lua:
Строка lua_shared_dict создает новый словарь (ключ-значение). Этот словарь будет единым для всех запросов, поэтому в нем удобно хранить белые и черные списки. Это словарь, кроме параметров ключ-значение, может иметь параметр time-to-live, который идеально подходит для хранения счетчиков, если нужно ограничить количество запросов в промежуток времени.
Строка lua_package_path задает пути для поиска модулей Lua, в котрый нужно включить каталог со скриптами. Две подряд точки с запятой в конце строки означают, что этот путь добавляется к текущему значению пути, а не полностью заменяет его.
Строка init_by_lua задает код, который будет выполнен один раз при старте сервера (а не при каждом новом запросе). В ней задается белый список IP-адресов. Второй праметр функции add — true — это просто значние которое потом используется в операторе if. Третий параметр time-to-live отсутсвует, поэтому значение будет храниться без ограничения по времени.
Строка access_by_lua_file задает путь к скрипту, который будет выполняться при каждом запросе к серверу (не только при старте сервера). В нем, собственно, и находится вся логика защиты.
Рассмотрим некоторые из проверок, которые можно сделать при помощи скрипта на Lua:
Язык Lua во многом похож (даже слишком) на JavaScript, поэтому код на Lua интуитивно понятен всем, кто пишет на JavaScript.
Глобальная переменная ngx служит для связи с контекстом сервера nginx. Оператор
Далее распознается атака, основанная на особенностей реализации CMS WordPress. Если атака выявлена то работа оканчивается специальным статусом 444 (характерен только для nginx):
И, наконец, мы даем «зеленую дорогу» поисковым ботам. Тут приходится использовать счетчик, т.к. под поискового бота часто подделываются злоумышленники — поэтому считаем количество обращений.
Дальнейшее распознавание ботов и злоумышленников может вестись по разным направлениям. Как было предложено в статье такое распознавание основано на проверках, поддерживает ли клиент редиректы, установку cookie и выполнения кода JavaScript. Ну или все, что можно еще придумать.
Как правило, такой веб-сервер используют в качестве прокси, а защищаемый веб-сервер размещают на другом IP-адресе.
Полезные ссылки
1. firstwiki.ru/index.php/%D0%9A%D1%80%D0%B0%D1%82%D0%BA%D0%BE%D0%B5_%D1%80%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE_%D0%BF%D0%BE_%D0%B1%D0%BE%D1%80%D1%8C%D0%B1%D0%B5_%D1%81_DDOS-%D0%B0%D1%82%D0%B0%D0%BA%D0%B0%D0%BC%D0%B8_%D0%BD%D0%B0_http-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80
2. habrahabr.ru/post/139931
3. javapipe.com/ddos/blog/iptables-ddos-protection
4. github.com/apapacy/ngx_lua_anticc/tree/v-0.0.1
apapacy@gmail.com
22 января 2018 года.
![image](https://habrastorage.org/getpro/habr/post_images/468/9b1/24e/4689b124e9c3bb94dce8c3d48ed104d9.jpg)
Если у Вас есть небольшой сайт на сервере с минимальными характеристиками, то положить его можно любым вполне легальным средством стресс-тестирования. (Не рекомендую этого никому делать т.к. IP-адрес легко вычисляется и экспериментатор может влететь на возмещение ущерба.) Поэтому сайт без защиты от DDoS очень скоро будет выглядеть так же дико, как компьютер с Windows-98 без анивирусника.
Первое, что можно и нужно сделать для защиты сайта — настроить брандмауэр iptables. Я использую почти без изменений настройки iptables из статьи на сайте одного из поставщиков защиты от DDoS-атак. Единственное что я поменял — увеличил число допустимых соединений в правилах #8 и #10.
Прежде чем запускать на выполнение скрипт, меняющий параметры iptables, нужно убедиться, что есть альтернативная возможность сбросить эти параметры в начальное состояние. Т.к. если правила заданы неверно, к серверу не сможет подключится никто, в том числе и администратор.
Брандмауэр iptables контролирует атаку на сетевом уровне. Следующее что необходимо настроить — это веб-сервер. В качестве веб-сервера, который открыт для доступа из интернет будем рассматривать nginx. В файле nginx.conf нужно увеличить лимиты на колчество файлов и открытых коннектов (пример взят из Википедии):
# Увеличение максимального количества используемых файлов
worker_rlimit_nofile 80000;
events {
# Увеличение максимального количества соединений
worker_connections 65536;
# Использование эффективного метода epoll для обработки соединений
...
}
Далее настраиваем сервер по умолчанию, который будет запрещать доступ для тех устройств (например IoT), который будут обращаться по IP-адресу а не по доменному имени:
# Default server configuration
#
server {
listen 80 default_server;
listen 443 ssl default_server;
deny all;
}
Так же в nginx можно настроить некоторые лимиты на количество обращений, но такая настройка будет не очень гибкой и совсем не избирательной. Наша цель сделать такую защиту на уровне веб-сервера, чтобы погасить запросы злоумышленников, но пропускать на сервер запросы добропорядочных пользователей.
Чтобы не пересказывать уже имеющийся на Хабре материал, предлагаю ознакомится с отличной статьей, а так же с модулем автора указаной статьи kyprizel/testcookie-nginx-module. То, что позволяет сделать этот модуль уже хорошо. Но если Вам понадобится модернизировать его — то сделать это будет непросто.
На сегодняшний день очень многие поставщики услуг защиты от DDoS используют сервер openresty (связка nginx + Lua от Taobao). Скорость выполнения хорошего кода на Lua немного уступает хорошему коду на С. Но разрабатывать на Lua быстрее и проще, и к тому же скрипты можно менять без перекомпиляции сервера. При следуюшем рестарте они будут прочитаны, скомпилированы LuaJIT, и это все что требуется.
Подробная инструкция как уcтановить optnresty. После установки продолжаем настраивать nginx. В разделе http определяем нужные параметры для работы скритов Lua:
lua_shared_dict whitelist 10m;
lua_shared_dict banlist 100m;
lua_package_path '/home/username/antiddos/?.lua;;';
init_by_lua '
local whitelist = ngx.shared.whitelist
whitelist:add("1.2.3.4", true)
whitelist:add("5.6.7.8", true)
';
access_by_lua_file /home/username/antiddos/main.lua;
Строка lua_shared_dict создает новый словарь (ключ-значение). Этот словарь будет единым для всех запросов, поэтому в нем удобно хранить белые и черные списки. Это словарь, кроме параметров ключ-значение, может иметь параметр time-to-live, который идеально подходит для хранения счетчиков, если нужно ограничить количество запросов в промежуток времени.
Строка lua_package_path задает пути для поиска модулей Lua, в котрый нужно включить каталог со скриптами. Две подряд точки с запятой в конце строки означают, что этот путь добавляется к текущему значению пути, а не полностью заменяет его.
Строка init_by_lua задает код, который будет выполнен один раз при старте сервера (а не при каждом новом запросе). В ней задается белый список IP-адресов. Второй праметр функции add — true — это просто значние которое потом используется в операторе if. Третий параметр time-to-live отсутсвует, поэтому значение будет храниться без ограничения по времени.
Строка access_by_lua_file задает путь к скрипту, который будет выполняться при каждом запросе к серверу (не только при старте сервера). В нем, собственно, и находится вся логика защиты.
Рассмотрим некоторые из проверок, которые можно сделать при помощи скрипта на Lua:
-- if client IP is in whitelist, pass
local whitelist = ngx.shared.whitelist
in_whitelist = whitelist:get(ngx.var.remote_addr)
if in_whitelist then
return
end
-- HTTP headers
local headers = ngx.req.get_headers();
-- wp ddos
if type(headers["User-Agent"]) ~= "string"
or headers["User-Agent"] == ""
or ngx.re.find(headers["User-Agent"], "^WordPress", "ioj") then
ngx.log(ngx.ERR, "ddos")
ngx.exit(444)
return
end
local banlist = ngx.shared.banlist
local search_bot = "search:bot:count:request:per:10:s"
if ngx.re.find(headers["User-Agent"], "Google Page Speed Insights|Googlebot|baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator", "ioj") then
local count, err = banlist:incr(search_bot, 1)
if not count then
banlist:set(search_bot, 1, 10)
count = 1
end
if count >= 50 then
if count == 50 then
ngx.log(ngx.ERR, "bot banned")
end
ngx.exit(444)
return
end
return
end
Язык Lua во многом похож (даже слишком) на JavaScript, поэтому код на Lua интуитивно понятен всем, кто пишет на JavaScript.
Глобальная переменная ngx служит для связи с контекстом сервера nginx. Оператор
return
вне тела функции означает возврат из модуля. В данном примере, если IP-адрес в белом списке, то работа скрипта оканчивается, и продолжается обычная обработка запроса nginx.Далее распознается атака, основанная на особенностей реализации CMS WordPress. Если атака выявлена то работа оканчивается специальным статусом 444 (характерен только для nginx):
ngx.exit(444)
.И, наконец, мы даем «зеленую дорогу» поисковым ботам. Тут приходится использовать счетчик, т.к. под поискового бота часто подделываются злоумышленники — поэтому считаем количество обращений.
banlist:set(search_bot, 1, 10)
инициализирует счетчик, который обнулится через 10 секунд после создания. banlist:incr(search_bot, 1)
прибавляет к текущему значению счетчика единицу.Дальнейшее распознавание ботов и злоумышленников может вестись по разным направлениям. Как было предложено в статье такое распознавание основано на проверках, поддерживает ли клиент редиректы, установку cookie и выполнения кода JavaScript. Ну или все, что можно еще придумать.
Как правило, такой веб-сервер используют в качестве прокси, а защищаемый веб-сервер размещают на другом IP-адресе.
Полезные ссылки
1. firstwiki.ru/index.php/%D0%9A%D1%80%D0%B0%D1%82%D0%BA%D0%BE%D0%B5_%D1%80%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE_%D0%BF%D0%BE_%D0%B1%D0%BE%D1%80%D1%8C%D0%B1%D0%B5_%D1%81_DDOS-%D0%B0%D1%82%D0%B0%D0%BA%D0%B0%D0%BC%D0%B8_%D0%BD%D0%B0_http-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80
2. habrahabr.ru/post/139931
3. javapipe.com/ddos/blog/iptables-ddos-protection
4. github.com/apapacy/ngx_lua_anticc/tree/v-0.0.1
apapacy@gmail.com
22 января 2018 года.