Ну смотрите, у нас не совсем классическая схема, валят в основном серверную площадку с клиентскими игровыми и web серверами, обычных юзеров не сильно трогают. Поэтому все усилия направлены на защиту именно этой площадки.
Самый простой метод DDOS - это udp трафик, всякие амплификейшены позволяют устроить проблемы даже если у вас нет ботнета под рукой, а есть просто список DNS или NTP серверов , которым от имени вашего узла можно задать запросы на выгрузку зоны, или на получение времени для всех временных зон. Такого трафика может налететь много гигабит. Вроде бы простое решение для операторов - не разрешать клиентам слать запросы не со своих адресов, часто не выполняется и поэтому всякие презервуары этим пользуются.
Для решения проблемы, на определенные сервера мы попросили аплинков полностью перекрыть UDP на некоторые особо дидосо опасные направления. У себя тоже режем это трафик на коммутаторах.
Далее, после того как дидоссеры поняли бесперспективность подобного вида ддоса, началась новая волна, связанная опять же с TCP запросами, тут конечно голь на выдумку очень бывает хитра. А главное, что от подобного трафика, даже на закрытые порты, даже просто не ack ответы, тот же Linux в своем роуткеше создает записи, и рано или поздно это приводит к падению сервера. Еще можно переполнить таблицы iptables hashlimit к примеру если от ддоса пытаются так защищаться, возможно переполнние таблицы коннекшен трекинга (65535 по умолчанию соединений), а то и просто постоянными коннектами к порту не дать на него подключиться легитимному пользователю, а часто на linux по умолчанию разрешено всего 1024 коннекта(ограничение по файловым декрипторам).
В общем проблема на лицо, и часть этих проблем мождно решить тюнинком стека tcp, уменьшение таймаутов на полуоткрытые соединения, увеличение таблиц конекшн трекинга и тд, и в ряде случаев этого бывает достаточно. И под нагрузкой обычного hping ваш сервис может летать. Даже если их запустить 5-6 штук.
Но дело в том, что производительности Linux хоста, обычно хвватает для отправки ну 200 тыс соединений в сек. Но с помощью использования технолгии netmap, когда все операции по созданию и копированию пакетов производится внутри буферов сетевух надод достигает скоростей порядка 14 миллионов пакетов в сек. На Храбре есть описания, подобных пакетодробилок.
Все это приводит к тому, что с подготовленных хакерских хостов выходящий PPS может значительно превышать тестовые 2 сотни тысяч пакетов секунду. И под таким напором любой сервер обслуживающий сокеты ложится.
Из вариантов поднимаем на linux роутере SYNPROXY - модуль для ядра linuх, делающий простую, но очень эффектную вещь, на запрос соединения с удаленного сайта, оно отсылает обратно куку и с таймстемпом и ждет ответа, если ответ получен - значит удаленный хост действительно соединение запросил, и только тогда пробрасывается соединение на реальный сервер. Иначе все дропается, и не попадает в таблицу соединений. После этого сервисам уже почти ничего не грозит, но даже для такой работы требуется мощности CPU на маршрутизаторе, у нас она упирается в полочку где-то при 600 тыс пакетов. Все 8 реальных процессоров заняты на 100% и начинаются проблемы. Поэтому такой PPS надо ограничивать, что мы и делаем на коммутаторах.
Итак техническая реализация на коммутаторе:
Код:
#создаем правило фильтрации UDP трафика заранее со всякими необходимым а дальнейшем полями, долгое время не знал что так можно, раньше создавал разные профили как дурак :(
create access_profile profile_id 1 profile_name udp_filter ip vlan source_ip_mask 255.255.255.255 destination_ip_mask 255.255.255.255 udp src_port_mask 0xFFFF dst_port_mask 0xFFFF
#разрешаем проходить на 1 адрес трафику на тимспик порт
config access_profile profile_id 1 add access_id 1 ip destination_ip 1.2.4.204 udp dst_port 9987 port 3,25,26 permit counter enable urpf_state_check disable priority 5 replace_dscp_with 40
#на входящих портах с аплинков разрешаем с доверенного stratum-1 NTP сервера получать трафик на один наш хост 1.2.4.5, на этот хост настроен перехват всего трафика запроса времени от всех пользователей. Хацкеры не знают это пару и поэтому они в обломе.
config access_profile profile_id 1 add access_id 4 ip vlan_id 528 source_ip 1.1.1.168 destination_ip 1.2.4.17 udp dst_port 123 port 3 permit counter enable urpf_state_check disable
config access_profile profile_id 1 add access_id 5 ip vlan_id 1203 source_ip 1.1.1.168 destination_ip 1.2.4.17 udp dst_port 123 port 25 permit counter enable urpf_state_check disable
config access_profile profile_id 1 add access_id 6 ip vlan_id 1323 source_ip 1.1.1.168 destination_ip 1.2.4.17 udp dst_port 123 port 26 permit counter enable urpf_state_check disable
#режем весь входящий трафик на 123 порт на всех аплинках, там могут быть арендованные виланы и много еще чего, поэтому строго ограничиваем правила виланами аплинков.
config access_profile profile_id 1 add access_id 128 ip vlan_id 528 udp dst_port 123 port 3 deny
config access_profile profile_id 1 add access_id 129 ip vlan_id 1203 udp dst_port 123 port 25 deny
config access_profile profile_id 1 add access_id 130 ip vlan_id 1323 udp dst_port 123 port 26 deny
#защищаем сервера подверженные DDOS от всего udp трафика
config access_profile profile_id 1 add access_id 150 ip destination_ip 1.2.4.1 udp port 3,25,26 deny
config access_profile profile_id 1 add access_id 151 ip destination_ip 1.2.4.4 udp port 3,25,26 deny
config access_profile profile_id 1 add access_id 152 ip destination_ip 1.2.4.7 udp port 3,25,26 deny
config access_profile profile_id 1 add access_id 153 ip destination_ip 1.2.4.8 udp port 3,25,26 deny
config access_profile profile_id 1 add access_id 154 ip destination_ip 1.2.4.9 udp port 3,25,26 deny
#Помечаем трафик UDP остальной как трафик повышенного приоритета, чтобы порадовать игроков, решение спорное - тестируем.
config access_profile profile_id 1 add access_id 200 ip vlan_id 528 udp port 3 permit counter disable urpf_state_check disable priority 5 replace_dscp_with 40
config access_profile profile_id 1 add access_id 201 ip vlan_id 1203 udp port 25 permit counter disable urpf_state_check disable priority 5 replace_dscp_with 40
config access_profile profile_id 1 add access_id 202 ip vlan_id 1323 udp port 26 permit counter disable urpf_state_check disable priority 5 replace_dscp_with 40
#Создаем универсальное правило фильтрации по tcp, с учетом нужных адресов, портов и флагов.
create access_profile profile_id 2 profile_name tcp_filter ip vlan source_ip_mask 255.255.255.255 destination_ip_mask 255.255.255.255 tcp src_port_mask 0xFFFF dst_port_mask 0xFFFF flag_mask urg ack psh rst syn fin
#тут отлавливаем SYN запросы извне, и помечаем их приоритетом поменьше, в дальнейшем будем ограничивать это поток через flow_meter
config access_profile profile_id 2 add access_id 32 ip vlan_id 528 tcp flag syn port 3 permit counter enable urpf_state_check disable priority 0 replace_dscp_with 14
config access_profile profile_id 2 add access_id 33 ip vlan_id 1203 tcp flag syn port 25 permit counter enable urpf_state_check disable priority 0 replace_dscp_with 14
config access_profile profile_id 2 add access_id 34 ip vlan_id 1323 tcp flag syn port 26 permit counter enable urpf_state_check disable priority 0 replace_dscp_with 14
#На серверную площадку разрешаем только нужные порты, внимание ответы со старших портов, приходит на эти сервера не будут, интернет работать не будет, на серверах потребуется использовать прокси, к примеру.
config access_profile profile_id 2 add access_id 64 ip destination_ip 1.2.4.22 tcp dst_port 80 port 3,25,26 permit counter disable urpf_state_check disable priority 4 replace_dscp_with 32
config access_profile profile_id 2 add access_id 65 ip destination_ip 1.2.4.22 tcp dst_port 443 port 3,25,26 permit counter disable urpf_state_check disable priority 4 replace_dscp_with 32
config access_profile profile_id 2 add access_id 66 ip destination_ip 1.2.4.22 tcp dst_port 22 port 3,25,26 permit counter disable urpf_state_check disable priority 4 replace_dscp_with 32
#режем все остальное на наш 22й сервер.
config access_profile profile_id 2 add access_id 67 ip destination_ip 1.2.4.22 tcp port 3,25,26 deny
#тоже действие для другого сервера с игровыми портами 1024 и 4096.
config access_profile profile_id 2 add access_id 68 ip destination_ip 1.2.4.1 tcp dst_port 1024 port 3,25,26 permit counter disable urpf_state_check disable priority 4 replace_dscp_with 32
config access_profile profile_id 2 add access_id 69 ip destination_ip 1.2.4.1 tcp dst_port 4096 port 3,25,26 permit counter disable urpf_state_check disable priority 4 replace_dscp_with 32
config access_profile profile_id 2 add access_id 70 ip destination_ip 1.2.4.1 tcp dst_port 22 port 3,25,26 permit counter disable urpf_state_check disable priority 4 replace_dscp_with 32
#режем все остальное на наш 10.2.4.1 сервер.
config access_profile profile_id 2 add access_id 71 ip destination_ip 1.2.4.1 tcp port 3,25,26 deny
...
#Помечаем трафик TCP средним приоритетом, выше его только IPTV, телефония и управление.
config access_profile profile_id 2 add access_id 4 ip vlan_id 528 tcp port 3 permit counter disable urpf_state_check disable priority 4 replace_dscp_with 32
config access_profile profile_id 2 add access_id 5 ip vlan_id 1203 tcp port 25 permit counter disable urpf_state_check disable priority 4 replace_dscp_with 32
config access_profile profile_id 2 add access_id 6 ip vlan_id 1323 tcp port 26 permit counter disable urpf_state_check disable priority 4 replace_dscp_with 32
#Ограничиваем наш трафик на тимспик сервер 20 мегабитами, да задосить сервис становится легко, но положить что-то еще при этом невозможно
config flow_meter profile_id 1 access_id 1 rate 20480 burst_size 1024 rate_exceed drop_packet
#Ограничиваем трафик по SYN запросам извне по 130 мегабит на каждый аплинк. В случае превышения извне, подключиться извне к сервисам внутри сети можно будет не с первого раза, но это ограничение позволяет нормально выживать при высоких syn flood нагрузках.
config flow_meter profile_id 2 access_id 32 rate 131072 burst_size 10240 rate_exceed drop_packet
config flow_meter profile_id 2 access_id 33 rate 131072 burst_size 10240 rate_exceed drop_packet
config flow_meter profile_id 2 access_id 34 rate 131072 burst_size 10240 rate_exceed drop_packet
Теперь что касается SYNPROXY:
для работы SYNPROXY обязательно надо добавить параметры в sysctl.conf, особо важно net.netfilter.nf_conntrack_tcp_loose выставить, иначе при правильной нстройке пакеты будут пролетать через конекшен трекин и легальный сервис будет сбрасывать такие соединения ресетом.
Цитата:
net.ipv4.conf.eth0.route_localnet=1
net.netfilter.nf_conntrack_tcp_loose = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_timestamps=1
Затем на сервере маршрутизации обязательно надо иметь полный стейтфул фаервол, которые будет остлеживать все подключения. Надо увеличить максимальное количество доступных записей о соединениях до 2-4х миллионов. А так же увеличить размер хеша поиска, для него
Цитата:
net.netfilter.nf_conntrack_buckets = 700416
net.netfilter.nf_conntrack_expect_max=87552
net.netfilter.nf_conntrack_max = 4194304
net.nf_conntrack_max = 4194304
net.ipv4.netfilter.ip_conntrack_max = 4194304
Тут тонкий момент размер хеш таблицы должен быть такой чтобы она полностью помещалась в кеш процессора если что, у меня он 6Мб, поэтому я беру 700416 записей, на каждую запись тратится насколько я помню 80 байт. Конекшен трекинг в современных ядрах работает действительно быстро. И позволяет решить много проблем с пропуском вредного трафика. Главное оружие - не пропускаем трафик нарушающий правильные порядок поступления пакетов.
Итак на linux роутере работает фаервол, выдержки из него привожу
Код:
#!/bin/bash
IPT="/sbin/iptables "
IPS="/sbin/ipset"
#чистим правило , если его нет - создаем.
$IPT -F TO_SYN_PROXY || $IPT -N TO_SYN_PROXY
#проверяем есть ли наш ipset список защищаемых ресурсов.
$IPS -L SRVDoS |grep "SRVDoS" || $IPS -N SRVDoS hash:ip,port
#описываем все хосты и порты которые мы хотим защищать с SYNPROXY
srvs_ddos_ips="1.2.4.1,1024 1.2.4.1,4096 1.2.4.1,22 1.2.4.22,80 1.2.4.22,22 1.2.4.22,443 "
#заполняем списоко ресурсами
for ip in $srvs_ddos_ips; do
$IPS -A SRVDoS $ip -q
done
#первые правила форвардинга - все что собирается выходить на интерфейс в сторону пользователей и что защищаем отправляем в правило TO_SYN_PROXY, остальной трафик ВНЕ зависимости от того куда и откуда он собирается маршрутизироваться - дропаем если его статус INVALID, да страшно но работает уже месяц и нареканий от пользователей нет.
$IPT -A FORWARD -o eth0.32 -p tcp -m set --match-set SRVDoS dst,dst -j TO_SYN_PROXY
$IPT -A FORWARD -m conntrack --ctstate INVALID -j DROP
#Правило разрешающее обмен трафиком по установленным соединениям, сразу ставим после вышестоящих правил, на самом деле у нас между неими есть еще и правила которые статистику собирают.
$IPT -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
#После этого правила можно набрасывать разные разрешения на прохождения трафика, точнее только на первый пакет, после этого будет работать уже вышестоящее правило разрешающее проход трафика по уже установленным подключениям. Пример
#проверяем есть ли список наших сетей, и создаем если нет
$IPS -L OUR_net |grep "OUR_net" || $IPS -N OUR_net hash:net
#заполняем список ipset, адресов с которых разрешено ходить юзерам.
our_nets="10.2.0.0/24 10.3.0.0/24 10.5.0.0/24 192.168.0/16"
for onet in $our_nets ; do
$IPS test OUR_net $onet || $IPS add OUR_net $onet
done
#разрешаем на внешние аплинки уходить с наших внутренних адресов
EXIF="eth0.1323 eth0.1203 eth0.528"
for iface in $EXIF ; do
$IPT -A FORWARD -o $iface -m set --match-set OUR_net src -m conntrack --ctstate NEW -j ACCEPT
done
#Правил синпрокси, все просто если мы сюда попали - пробуем установить установить подключение, заранее выбрав начальные параметры. Если не получилось - дропаем и забываем.
$IPT -A TO_SYN_PROXY -p tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
$IPT -A TO_SYN_PROXY -p tcp -m conntrack --ctstate INVALID -j DROP
#Не создаем автоматически конекшн трекинг записи для пакетов пришедших на защищаемые сервисы
for iface in $EXIF ; do
$IPT -t raw -A PREROUTING -i $iface -p tcp -m tcp --syn -m set --match-set SRVDoS dst,dst -j NOTRACK
done
В общем в таком варианте получается отчасти сдерживать гадских ддосеров, без каких либо глобальных затрат на покупку и поддержание дорогущего оборудования. Эффективность которого тоже не 100%.
=======================
для поиска: DDOS защита