MAATRIX / Блог / UDP-амплификация с вашего IP: когда вы не жертва, а источник

UDP-амплификация с вашего IP: когда вы не жертва, а источник

MAATRIX

Абьюз-письмо от хостера с формулировкой «ваш сервер участвует в 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 resolver53/UDPРекурсивный резолвинг для любого IP, особенно с запросами типа ANYориентировочно в разы — точная цифра сильно зависит от типа запроса и настроек зоны
NTP123/UDPСтарые команды monlist/readvar, отдающие списки клиентов или переменные состоянияу monlist традиционно один из самых высоких коэффициентов среди распространённых UDP-сервисов
memcached11211/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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →