UDP-амплификация с вашего IP: когда вы не жертва, а источник
Абьюз-письмо от хостера с формулировкой «ваш сервер участвует в DDoS-атаке» выбивает из колеи сильнее, чем обычная жалоба на спам: сервер ведь не взломан, никто не залил веб-шелл, права доступа не менялись. Дело в другом — на сервере открыт наружу UDP-сервис вроде DNS-резолвера, NTP-демона или memcached, и кто-то посторонний использует его как усилитель, чтобы обрушить трафик на третий адрес. Вы в этой схеме не жертва и не заказчик атаки, а невольный передаточный узел — и разбираться с этим всё равно придётся вам.
Содержание
Как работает amplification-атака
Механика amplification-атаки строится на трёх вещах: протоколе без проверки источника, ассиметричном ответе и подмене IP-адреса.
UDP — протокол без установления соединения. В отличие от TCP, где handshake (SYN/SYN-ACK/ACK) требует, чтобы у клиента был реальный доступ к обратному каналу, UDP-сервер просто получает пакет с заявленным source IP и отправляет ответ на этот адрес, не проверяя, действительно ли запрос пришёл оттуда. Атакующий подделывает (spoofing) IP отправителя в заголовке пакета, вписывая туда адрес жертвы вместо своего. Ваш сервер честно шлёт ответ — но не в сторону атакующего, а в сторону человека, которого атакующий выбрал целью.
Второй компонент — коэффициент усиления (amplification factor): отношение размера ответа к размеру запроса. Атакующему достаточно отправить короткий запрос в несколько десятков байт, чтобы получить ответ в сотни или тысячи байт. Умножьте это на ботнет из тысяч зомби-машин, рассылающих поддельные запросы на тысячи открытых резолверов и NTP-серверов по всему миру — и на стороне жертвы собирается трафик в десятки и сотни гигабит в секунду, хотя сам атакующий отправил в сотни раз меньше данных, чем жертва получила.
Из вашей точки зрения это выглядит как обычный всплеск запросов на порт 53, 123 или 11211: шквал коротких запросов с одинаковым паттерном и разными source IP, которые на самом деле принадлежат одной жертве. Сам сервер при этом может даже не заметить проблему — нагрузка на CPU обычно небольшая, страдает не он, а его исходящий канал и репутация IP.
Если вы уже оказались жертвой похожей атаки с другой стороны, как распознать её и что делать в первые минуты — разобрано в статье про первые действия при DDoS-атаке. Здесь ситуация зеркальная: сервер — источник, а не цель, и задача не пережить атаку, а не быть в ней использованным.
Какие сервисы чаще всего служат усилителями
Три условия делают протокол удобной мишенью для amplification: он работает по UDP, отвечает без обязательной авторизации и умеет отдавать ответ существенно больше запроса. Вот сервисы, которые чаще всего оказываются в этой роли на обычных VPS и выделенных серверах:
| Сервис | Порт | Что делает уязвимым | Типичный масштаб усиления |
|---|---|---|---|
| Open DNS resolver | 53/UDP | Рекурсивный резолвинг для любого IP, особенно с запросами типа ANY | ориентировочно в разы — точная цифра сильно зависит от типа запроса и настроек зоны |
| NTP | 123/UDP | Старые команды monlist/readvar, отдающие списки клиентов или переменные состояния | у monlist традиционно один из самых высоких коэффициентов среди распространённых UDP-сервисов |
| memcached | 11211/UDP | Сервис слушает 0.0.0.0 без аутентификации, отвечает на stats большим объёмом данных | у memcached исторически фиксировали одни из самых высоких коэффициентов усиления среди всех известных векторов |
| SSDP (UPnP) | 1900/UDP | Устройства и демоны отвечают на M-SEARCH всем подряд | умеренный, но масштаб атаки даёт количество устройств |
| CLDAP (Active Directory) | 389/UDP | Ответ на LDAP-поиск без авторизации | заметно выше единицы, конкретная величина сильно зависит от запроса |
Цифры в таблице — ориентир, а не гарантированное значение: реальный коэффициент зависит от версии ПО, конфигурации зоны/базы и типа запроса, которым воспользуется атакующий. Смысл не в точном числе, а в принципе — эти сервисы физически способны отдать ответ на порядок крупнее запроса.
Важный нюанс: сервис необязательно должен быть публичным намеренно. Частый сценарий — DNS-резолвер или memcached поднят «для внутренних нужд» (кэш приложения, локальный резолвинг для контейнеров), но по умолчанию слушает на всех интерфейсах 0.0.0.0, а firewall либо не настроен, либо разрешает UDP широко из-за отдельного правила для другого сервиса.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверКак проверить свой сервер на открытые UDP-сервисы
Проверку стоит делать с внешней машины — не с самого сервера, потому что локальные запросы обычно идут по loopback и не показывают, что видно снаружи. Удобно арендовать любой второй недорогой VPS или использовать личный компьютер с публичным IP.
DNS-резолвер. Проверка на открытую рекурсию:
dig @ваш_IP google.com A +short
dig @ваш_IP . NS +short
Если сервер не должен обслуживать сторонние DNS-запросы, а в ответ приходит что-то осмысленное (а не отказ или таймаут) — резолвинг открыт наружу. Отдельно стоит проверить запрос типа ANY — исторически он давал один из самых больших ответов и часто использовался как вектор атаки:
dig @ваш_IP isc.org ANY +short
NTP. Проверка на устаревшую команду monlist (актуальна для ntpd старых версий, в современных сборках обычно отключена по умолчанию, но конфиг мог унаследоваться с миграции):
ntpdc -c monlist ваш_IP
Если команда не заблокирована явно и возвращает список — это открытый вектор с одним из самых высоких коэффициентов усиления среди распространённых UDP-сервисов.
Memcached. Проверка командой stats через netcat:
echo -e "stats\r\n" | nc -u -w2 ваш_IP 11211
Любой осмысленный ответ вместо таймаута означает, что memcached слушает публично и без авторизации — критичная находка, требующая немедленного исправления.
Общее сканирование портов. Для быстрой инвентаризации, какие UDP-порты вообще открыты снаружи:
nmap -sU -p 53,123,161,389,1900,11211 --open ваш_IP
UDP-сканирование медленнее TCP и иногда даёт ложные "open|filtered" из-за особенностей протокола — на неоднозначный результат лучше смотреть точечными проверками выше, а не полагаться только на nmap.
Полезно прогонять эти проверки регулярно, а не один раз при установке — тот же принцип, что и общий чек-лист безопасности нового сервера: возвращаться к списку после каждого нового сервиса, поднятого на сервере.
Закрываем DNS-резолвер правильно
Если сервер не оказывает DNS-услугу сторонним клиентам намеренно, решение простое — резолвинг должен работать только для локальных процессов или доверенной подсети.
Для BIND9 в named.conf.options:
options {
listen-on { 127.0.0.1; 10.0.0.0/24; };
allow-recursion { 127.0.0.1; 10.0.0.0/24; };
recursion yes;
};
Ключевой параметр — allow-recursion. Даже если listen-on настроен широко (сервер обслуживает и авторитативные зоны для внешнего мира), рекурсивные запросы — то, чем пользуются для амплификации — должны быть ограничены доверенным списком.
Для unbound — аналогично, через access-control:
server:
interface: 127.0.0.1
interface: 10.0.0.0/24
access-control: 127.0.0.1/32 allow
access-control: 10.0.0.0/24 allow
access-control: 0.0.0.0/0 refuse
Если сервер работает как публичный авторитативный DNS для ваших собственных зон — рекурсия для внешних клиентов всё равно должна быть выключена: авторитативный ответ по своим зонам не требует рекурсивного резолвинга сторонних доменов.
Закрываем NTP, memcached и остальные
NTP. В современных версиях ntpd/chrony monlist по умолчанию отключён, но стоит явно проверить ntp.conf:
restrict default kod nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict ::1
restrict 10.0.0.0/24 nomodify notrap
Директива noquery в правиле по умолчанию запрещает посторонним запрашивать состояние сервера (в том числе через устаревшие mode 7 запросы, к которым относился monlist) — оставляя только синхронизацию времени. Если сервер работает как клиент времени, а не как NTP-сервер для чужих машин, проще всего вообще не открывать 123/UDP наружу — синхронизация исходящими запросами к пулу pool.ntp.org этого не требует.
Memcached. Самая частая причина уязвимости — сервис слушает 0.0.0.0 вместо loopback. В конфиге (/etc/memcached.conf на Debian/Ubuntu):
-l 127.0.0.1
Если memcached нужен нескольким серверам в приватной сети — указывайте конкретный внутренний IP, а не -l 0.0.0.0, и дополнительно закрывайте порт firewall’ом снаружи доверенной подсети. С версии 1.5.6 memcached по умолчанию отключил UDP именно из-за истории с амплификацией — если версия старая или явно включён -U 11211, отключите UDP, если он не нужен.
SSDP/UPnP. Обычно относится не к серверам, а к бытовым роутерам и IoT — но если на сервере поднят медиасервер или подобный демон с SSDP-откликом, его стоит либо отключить, либо ограничить интерфейсом, на котором он реально нужен.
Rate limiting и фильтрация на уровне firewall
Даже правильно сконфигурированный сервис стоит подстраховать ограничением на уровне сети — это защищает и от собственных ошибок конфигурации, и от новых уязвимостей, которые появятся в будущем.
Общий firewall на UFW или nftables — база, без которой остальные меры не имеют смысла; порядок настройки описан в статье про установку UFW на VPS. Поверх базового firewall для UDP-сервисов, которые всё же должны отвечать наружу, полезен rate limiting самих ответов — он не остановит единичный запрос, но не даст серверу превратиться в пушку, отвечающую на тысячи поддельных запросов в секунду.
Пример ограничения скорости UDP-трафика на 53 порту через nftables:
table inet filter {
chain input {
type filter hook input priority 0;
udp dport 53 limit rate 50/second burst 20 packets accept
udp dport 53 drop
}
}
Для DNS есть более точный инструмент — Response Rate Limiting (RRL), встроенный в BIND9 и знающий именно про эту угрозу (ограничивает не входящие запросы вообще, а одинаковые ответы одному и тому же адресу):
options {
rate-limit {
responses-per-second 10;
window 5;
};
};
RRL умнее плоского rate limiting на уровне firewall, потому что различает легитимный всплеск запросов от разных клиентов и подозрительно одинаковые ответы, летящие в сторону одного адреса — именно так выглядит DNS-сервер, участвующий в амплификации против конкретной жертвы.
Общий принцип: если сервис не обязан отвечать на произвольные внешние адреса — не разрешайте это на уровне firewall в принципе, а не полагайтесь только на rate limiting. Ограничение скорости — это защита на случай, если что-то всё равно осталось открытым, а не замена правильной настройки bind/allow-recursion/ACL.
BCP38 и фильтрация исходящего spoofing-трафика
Всё разобранное выше защищает от того, чтобы ваш сервер отвечал на поддельные запросы. Но есть и вторая сторона медали: если ваш сервер (или сеть, в которой он стоит) сам не фильтрует исходящий трафик, атакующий теоретически может использовать вашу инфраструктуру для отправки поддельных пакетов с чужим source IP — то есть не быть жертвой чужой амплификации, а самому стать точкой, откуда идёт spoofing.
BCP38 (Best Current Practice 38, RFC 2827) — рекомендация по фильтрации исходящего трафика на границе сети: провайдер или оператор сети должен пропускать наружу только пакеты, у которых source IP реально принадлежит этой сети. Если у вас в подсети только адреса 203.0.113.0/24, а наружу пытается уйти пакет с source IP 198.51.100.7 — такой пакет обязан быть отброшен на границе, потому что легитимно оказаться там он не может.
Проблема в том, что BCP38 — рекомендация, а не обязательный протокол, и соблюдают её не все сети одинаково строго. Именно поэтому spoofing вообще остаётся рабочим вектором: если бы каждая сеть фильтровала исходящий трафик по BCP38, amplification-атаки со спуфингом source IP физически не работали бы.
Что можно проверить и сделать на своей стороне:
- Уточнить у хостинг-провайдера, применяет ли он egress-фильтрацию (uRPF — Unicast Reverse Path Forwarding, типичная реализация на маршрутизаторах) для клиентских сетей. Это вопрос к провайдеру, а не то, что настраивается изнутри одной VPS.
- Если вы администрируете собственную сеть с несколькими IP-подсетями (физический сервер с VLAN или гипервизор с виртуальными машинами) — настроить фильтрацию исходящих пакетов по source IP на границе этой сети средствами iptables/nftables:
# разрешить исходящий трафик только с адресов своей подсети
iptables -A FORWARD -s 203.0.113.0/24 -j ACCEPT
iptables -A FORWARD -j DROP
- Включить uRPF в strict-режиме на маршрутизирующих узлах, где это применимо (
net.ipv4.conf.*.rp_filter = 1в sysctl на Linux — базовый эквивалент для отдельного хоста, хотя полноценный BCP38 реализуется на уровне сети/провайдера, а не одной машины).
Для обычного клиента одного VPS без собственной подсети главный практический вывод — не в том, что вы обязаны реализовать BCP38 сами (это ответственность провайдера на границе сети), а в том, что стоит выбирать инфраструктуру, где эта фильтрация в принципе включена. Спросить об этом у хостера при выборе — нормальная практика, особенно если вы размещаете что-то чувствительное к репутации IP.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Как узнать, что мой сервер уже используется как усилитель прямо сейчас?
Смотрите на исходящий UDP-трафик с портов 53/123/11211 в сторону множества разных адресов при отсутствии роста входящих легитимных запросов, либо на abuse-жалобу от хостера. Команда tcpdump -i eth0 udp and (port 53 or port 123 or port 11211) покажет характерный признак: короткие входящие запросы и заметно более крупные исходящие ответы на разные IP.
Хостер заблокировал мне порт из-за абьюз-жалобы — это навсегда?
Обычно нет: после жалобы хостер временно ограничивает трафик или порт, пока проблема не устранена. После того как вы закрыли уязвимый сервис и написали в поддержку с описанием исправления, доступ, как правило, восстанавливают. Похожая логика разобрана и для другого типа абьюза — когда сервер использовали для спам-рассылки.
Firewall уровня iptables/UFW достаточно, или обязательно нужно перенастраивать сам сервис?
Оба слоя нужны, и они не взаимозаменяемы. Firewall — это грубая сетевая граница (кто вообще может достучаться до порта), а allow-recursion/bind/ACL внутри самого сервиса — это его собственная логика, которая часто игнорирует внешний firewall при неверной настройке (например, если правило firewall написано для другого интерфейса или диапазона). Правильная защита — на обоих уровнях одновременно.
У меня VPS без собственной подсети — мне вообще нужно думать про BCP38?
Напрямую реализовать его вы не можете — это ответственность сети провайдера. Но полезно один раз спросить у хостера, применяется ли egress-фильтрация для клиентского трафика, и держать в уме этот критерий при выборе инфраструктуры — особенно если для вас важна репутация исходящего IP.
UDP вообще стоит держать открытым наружу, если можно перейти на TCP?
Не всегда возможно и не всегда нужно — у UDP есть законные причины быть быстрее и активно применяться там, где задержка важнее гарантии доставки. Задача не в отказе от UDP как такового, а в том, чтобы конкретный сервис отвечал только тем, кому должен, а не любому источнику в интернете.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →