Защита сервера TeamSpeak 3 от DDoS-атак

Опубликовано 13 мин. чтения

Закройте порт Query, ужесточите Anti-Flood, задайте ограничение частоты: что на сервере TeamSpeak 3 вы можете защитить сами. И где эти меры заканчиваются, потому что канал забивается раньше сервера.

Для клана сервер TeamSpeak — это нервный центр. Тот, кто его выключает, обрывает не просто разговор, а тренировку, скрим или рейд. Именно поэтому голосовые серверы так часто попадают под удар, и чаще всего от людей из ближнего круга: проигранный раунд, бан, ссора двух кланов.

В этой статье разобрано, что вы можете защитить сами и без дополнительных расходов, где такие меры упираются в потолок и что остаётся после них. Команды рассчитаны на Debian 12, Debian 13, Ubuntu 22.04 LTS и Ubuntu 24.04 LTS. Там, где нужен root, это указано отдельно.

Почему под удар попадают именно голосовые серверы

Причин три, и ни одна из них не связана с размером вашего проекта.

Во-первых, голос в реальном времени ничего не прощает. Потерю двух процентов пакетов на сайте не заметит никто, потому что TCP отправит недостающие сегменты ещё раз. У голоса повтора нет: потерянный пакет — это дыра в звуке, и её сразу слышат все за столом. То есть атаке даже не нужно забивать ваш канал полностью, чтобы сделать его непригодным.

Во-вторых, голосовой канал работает без установления соединения. TeamSpeak передаёт голос по UDP. Никакого рукопожатия и никакого состояния до прихода первого пакета не существует. Адрес отправителя подделывается свободно, а ваш сервер обязан сначала посмотреть на каждый входящий пакет, чтобы затем его отбросить. Злоумышленнику не нужны ни доступ, ни пароль, достаточно вашего IP-адреса и номера порта. Что при этом происходит технически, разбирает статья Что такое DDoS-атака?.

В-третьих, именно этот адрес публичен. Он есть в Discord, на сайте и, если запись включена, в списке серверов TeamSpeak. Голосовой сервер, который никто не может найти, бесполезен. Поэтому анонимность не является стратегией защиты.

Порты TeamSpeak 3 по умолчанию

Прежде чем что-то защищать, стоит выяснить, что вообще открыто. Вот заводские настройки сервера TeamSpeak 3:

Порт Протокол Направление Назначение
9987 UDP входящий Передача голоса (default_voice_port)
30033 TCP входящий Передача файлов (аватары, иконки, файлы каналов)
10011 TCP входящий ServerQuery открытым текстом (raw)
10022 TCP входящий ServerQuery через SSH
10080 и 10443 TCP входящий ServerQuery через HTTP и HTTPS соответственно
41144 TCP входящий TSDNS, нужен только при собственном разрешении имён
2008 TCP исходящий Служба лицензирования и учёта TeamSpeak
2010 TCP исходящий Регистрация в публичном списке серверов

Самая важная строка этой таблицы: из интернета должен быть доступен единственный порт 9987/UDP. Всё остальное либо не обязательно, либо должно стоять за ограничением доступа.

Что вы можете сделать сами, прежде чем тратить деньги

Следующие десять шагов не стоят ничего и помогают против тех видов атак, которые достаются голосовому серверу чаще всего: флуд через Query, спам подключениями и небольшие UDP-флуды из нескольких источников.

1. Инвентаризация: что на самом деле слушает

Правила для служб, которых не существует, безобидны. А вот пропущенный открытый порт стоит вам вечера. Сначала получите общую картину, выполнив от root:

ss -lntup

Интересна колонка Local Address:Port. Если там стоит 0.0.0.0:10011 или [::]:10011, ваш доступ ServerQuery открыт из всего интернета. Если там 127.0.0.1:10011, обратиться к нему можно только локально, и отдельное правило файрвола ему уже не нужно.

2. Закройте всё, что не нужно

Основа — это файрвол с правилом по умолчанию «отбрасывать весь входящий трафик». Следите при этом за порядком команд, иначе закроете доступ самому себе. Полный порядок действий вместе с путём отхода описывает инструкция Настройка файрвола UFW без потери доступа к серверу. Для сервера TeamSpeak результат выглядит так:

ufw allow 22/tcp
ufw allow 9987/udp
ufw allow 30033/tcp
ufw default deny incoming
ufw default allow outgoing
ufw enable

Если доступ ServerQuery действительно нужен снаружи, откройте его только для вашего собственного адреса. Замените 203.0.113.10 на ваш реальный IP-адрес:

ufw allow from 203.0.113.10 to any port 10011 proto tcp

А вот исходящие соединения замуровывать полностью нельзя. Без доступа к службе лицензирования и учёта сервер TeamSpeak не запустится нормально.

3. Уберите порт ServerQuery из интернета

Доступ ServerQuery — самая недооценённая поверхность атаки на сервере TeamSpeak. Через порт 10011 можно перебирать учётные данные и отправлять команды каждую секунду. Это не объёмная атака, а очень экономная, и ботнет для неё не нужен.

Чище всего вообще не выпускать службу Query наружу. Откройте ts3server.ini в каталоге сервера и задайте:

query_ip=127.0.0.1
query_protocols=raw
query_ip_allowlist=query_ip_allowlist.txt
query_ip_denylist=query_ip_denylist.txt
logquerycommands=1

После этого служба Query слушает только на самом сервере, а при необходимости вы попадаете на неё через SSH-туннель. Важно, чтобы файл действительно читался при запуске. Параметр запуска для этого такой:

./ts3server_startscript.sh restart inifile=ts3server.ini

Файл query_ip_allowlist.txt содержит адреса, на которые не распространяется защита службы Query от флуда, а query_ip_denylist.txt содержит заблокированные. Так файлы называются начиная с версии сервера 3.12, более старые версии используют query_ip_whitelist.txt и query_ip_blacklist.txt. Вносите в allowlist только то, чему там место, обычно это 127.0.0.1. Каждый лишний адрес — это исключение из ровно той защиты, которую вы сейчас включаете.

4. Ужесточите защиту от флуда на уровне инстанса

У сервера есть собственный тормоз для ServerQuery. Войдите как serveradmin, не выбирая виртуальный сервер, и сначала посмотрите текущие значения:

instanceinfo

Затянуть их можно так:

instanceedit serverinstance_serverquery_flood_commands=10 serverinstance_serverquery_flood_time=3 serverinstance_serverquery_ban_time=600

Это разрешает десять команд за три секунды и после этого блокирует адрес на десять минут. Если ваша версия сервера показывает в выводе instanceinfo ещё и верхний предел одновременных Query-соединений на адрес, задайте и ему небольшое значение.

5. Никогда не запускайте Query-ботов под доступом serveradmin

Ranksystem, музыкальный бот, скрипт статистики: почти каждый из них работает с полными учётными данными serveradmin. Если бота скомпрометируют или его пароль окажется в публичном конфигурационном файле, сервер будет принадлежать уже не вам.

Вместо этого заведите отдельный доступ Query, привязанный к конкретной идентичности клиента, и выдайте этой идентичности только те права, которые нужны боту:

queryloginadd client_login_name=ranksystem cldbid=42

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

6. Настройте Anti-Flood виртуального сервера

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

use sid=1
serveredit virtualserver_antiflood_points_tick_reduce=5 virtualserver_antiflood_points_needed_command_block=150 virtualserver_antiflood_points_needed_ip_block=250

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

7. Поднимите уровень идентичности против автоматического join-спама

У каждой идентичности TeamSpeak есть уровень безопасности, который зарабатывается вычислениями. Сервер может требовать минимальный уровень, по умолчанию это уровень 8. Тому, кто хочет штамповать одноразовые идентичности пачками, придётся считать для каждой отдельно:

serveredit virtualserver_needed_identity_security_level=10

Против волн ботов это работает, но у меры есть цена: действующим участникам придётся один раз донастроить свою идентичность, а примерно с уровня 12 на слабых устройствах это тянется неприятно долго. Объявите о повышении заранее, а не включайте его посреди прайм-тайма.

8. Список серверов, пароль сервера и настоящее ограничение доступа

Запись в публичном списке серверов делает ваш адрес легко находимым для машин, а закрытому клановому серверу она ничего не даёт. Отключается так:

serveredit virtualserver_weblist_enabled=0

Но будьте честны с собой: это убирает удобный способ найти ваш адрес, однако не прячет его. Сканирование диапазона адресов всё равно обнаружит открытый UDP-порт 9987.

Настоящее ограничение доступа делается двумя путями. Внутри TeamSpeak вы задаёте пароль сервера и работаете с токенами для выдачи групп. На сетевом уровне, что заметно жёстче, вы открываете 9987/UDP только для известных адресов или держите голосовой сервер внутри VPN. Для постоянного круга из десяти человек это осуществимо, для открытого сообщества нет.

Если вы хотите раздавать имя вместо IP-адреса, используйте SRV-запись вида _ts3._udp.example.com. Клиент сам разрешит её вместе с номером порта, а при смене IP вы поменяете только эту одну запись.

9. Ограничение частоты на самом хосте и честная оценка его пользы

Во всех четырёх названных системах пакетный фильтр под капотом работает на nftables. С его помощью можно ограничить частоту пакетов по каждому адресу отправителя. Заведите для этого отдельную таблицу, чтобы не трогать существующую конфигурацию UFW:

table inet ts3 {
    chain input {
        type filter hook input priority filter; policy accept;
        udp dport 9987 meter ts3flood { ip saddr limit rate over 400/second burst 800 packets } counter drop
    }
}

Сохраните это как /etc/nftables.d/ts3.nft, при необходимости сначала создав каталог, и загрузите файл от root:

nft -f /etc/nftables.d/ts3.nft
nft list table inet ts3

Отменить изменение можно командой nft delete table inet ts3. После перезагрузки таблица исчезнет, если файл не подключён из /etc/nftables.conf.

О порядке величин: говорящий клиент при кадрах по 20 миллисекунд отправляет около 50 пакетов в секунду. Значит, 400 пакетов в секунду оставляют изрядный запас даже нескольким людям за одним подключением, а счётчик покажет, сработало ли правило вообще.

А теперь честная оценка: против распределённой атаки это правило почти не помогает. Оно считает по адресу отправителя, а злоумышленник подделывает адрес отправителя заново в каждом пакете. Правило хорошо против отдельных нарушителей и против неверно настроенных клиентов. Защитой от DDoS оно не является.

10. Ведите записи, чтобы в критический момент у вас были цифры

Когда всё начнётся, вам понадобятся измерения, а не ощущение, что «что-то тормозит». Счётчики пакетов и ошибок сетевой карты читаются так:

ip -s link show eth0

Выполните команду дважды с интервалом в десять секунд и вычтите одно значение из другого: получится ваша частота пакетов. Кто прямо сейчас держит соединения с голосовым портом, покажет:

ss -uan 'sport = :9987'

Небольшую выборку входящего трафика даст:

tcpdump -ni eth0 udp port 9987 -c 20

Лог-файлы сервера лежат в подкаталоге logs/. С параметром logquerycommands=1 из шага 3 туда попадают и отправленные команды Query, благодаря чему злоупотребление становится видно задним числом. Как отличить атаку от ошибки в конфигурации, показывает статья Как определить DDoS-атаку на сервере.

Где эти меры заканчиваются

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

Посчитайте вместе с нами: канал 1 Гбит/с передаёт примерно 125 мегабайт в секунду, а при самых маленьких пакетах около 1,49 миллиона пакетов в секунду. При 10 Гбит/с это соответственно около 14,9 миллиона пакетов в секунду. Это жёсткий потолок канала, и он не зависит от того, что работает на сервере.

Реально измеренная атака на сервер TeamSpeak по порту 9987 UDP достигала более 473,4 Гбит/с и более 41,5 миллиона пакетов в секунду. Это примерно в 470 раз больше канала 1 Гбит/с и по-прежнему почти втрое больше той частоты пакетов, которую вообще способен пропустить канал 10 Гбит/с.

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

К этому добавляется процессорное время. Даже если бы ваше ядро могло отбрасывать миллионы пакетов в секунду, каждое такое решение стоит CPU. Голосовой сервер, занятый выбрасыванием пакетов, звучит ровно так же скверно, как и тот, который вообще перестал отвечать.

Что противопоставляет этому KernelHost

Ступень 1: постоянная защита, включённая в каждый сервер

На каждом сервере KernelHost DDoS-фильтрация работает постоянно и без доплаты, и вам не нужно ничего включать или настраивать. Устроена она в два уровня:

  • Уровень 1: 17 Тбит/с мощности mitigation в глобальной scrubbing-сети. Объёмные атаки перехватываются вблизи источника, задолго до того как они дойдут до дата-центра. Это именно тот уровень, который разгружает канал там, где вы сами разгрузить его не можете.
  • Уровень 2: 3,2 Тбит/с фильтрации Arbor в реальном времени в maincubes Premium Datacenter во Франкфурте-на-Майне. Непосредственно перед сервером распознаются специфичные для протокола схемы, и трафик отбрасывается пакет за пакетом, в том числе UDP-флуды по типичным портам голосовых и игровых серверов.

Два момента здесь важнее, чем кажется на первый взгляд. Во-первых, защита активна постоянно и ей не нужно сначала запускаться, поэтому нет фазы разгона, в течение которой атака проходит насквозь. Во-вторых, атакуемый IP-адрес не убирается из сети: отказ от null-routing означает, что ваши участники продолжают разговаривать, пока идёт фильтрация. Как это выглядит для других игр и протоколов, описывает статья Защита игровых серверов от DDoS в реальном времени.

Ступень 2: Advanced DDoS Protection для проектов под постоянными атаками

Некоторые проекты получают не один удар, а обстрел на протяжении недель. Для таких случаев есть Advanced DDoS Protection от 50,00 € в месяц, PrePaid и без минимального срока. Она дополняет включённую постоянную защиту тремя вещами:

  • Выделенный защищённый IP-адрес из франкфуртского ядра сети, на который переводится ваш сервер. С вашей стороны никакой перестройки для этого не требуется.
  • Самостоятельно управляемые правила защиты по каждому порту и протоколу в личном кабинете. Фильтрацию для 9987/UDP вы настраиваете иначе, чем для 30033/TCP, и без единого тикета, а изменения применяются в реальном времени.
  • Профиль защиты под конкретную игру или службу, с готовыми профилями более чем для 40 игр и протоколов, включая TeamSpeak.

PrePaid здесь означает ровно то, что написано: нет минимального срока, нет срока расторжения, нет договора, нет платы за подключение. Вы подключаете защиту на время волны атак, а потом просто даёте ей закончиться.

Сравнение двух ступеней

Характеристика Включённая постоянная защита Advanced DDoS Protection
Цена входит в каждый сервер без доплаты от 50,00 € в месяц, PrePaid
Подключение не требуется, активна с первой минуты заказ в личном кабинете, выделенный защищённый IP-адрес
Ёмкость 17 Тбит/с глобального scrubbing плюс 3,2 Тбит/с фильтрации Arbor в реальном времени во Франкфурте-на-Майне
Правила защиты автоматические профили, которые ведёт сетевая команда управляются вами по каждому порту и протоколу, изменения применяются в реальном времени
Профиль игры назначается автоматически выбираете сами, более 40 игр и протоколов
Поведение во время атаки null-routing не применяется, IP-адрес остаётся доступным
Срок часть серверного тарифа PrePaid, без минимального срока и без срока расторжения
Кому подходит обычная работа и эпизодические атаки проекты, которые обстреливают постоянно и целенаправленно

Частые ошибки и их решения

Голосовой порт меняют, чтобы атака ушла в пустоту: это работает ровно до того момента, пока кто-нибудь не запустит сканирование портов, то есть обычно несколько минут. Одновременно всем участникам придётся править свои закладки. Другой порт имеет смысл только тогда, когда вы и так держите на одном сервере несколько инстансов.

ServerQuery оставляют открытым, потому что он нужен боту: как правило, бот работает на том же самом сервере, и тогда достаточно query_ip=127.0.0.1. Если он работает где-то ещё, откройте порт только для его постоянного IP-адреса и заведите ему через queryloginadd ограниченный доступ.

Файрвол включили, и доступ пропал: на KVM root-серверах и выделенных серверах KernelHost вы попадаете в систему через VNC-консоль в личном кабинете. Эта консоль не висит на сетевом стеке гостевой системы, поэтому правило файрвола заблокировать её не может. Войдите там как root и отключите файрвол командой ufw disable, прежде чем искать причину.

Ограничение частоты выставили слишком узко, и оно бьёт по своим же участникам: типичный пример: общежитие или семья за одним общим подключением. Для фильтра это выглядит как один адрес с подозрительно большим числом пакетов. Проверьте счётчик командой nft list table inet ts3: если он растёт, хотя никакой атаки нет, значение слишком низкое.

После правки ts3server.ini сервер больше не стартует: почти всегда файл отредактировали, но не передали при запуске, либо наоборот. Проверьте оба момента и загляните в самый свежий файл в logs/, причина написана там открытым текстом.

Все меры выполнены, а сервер всё равно недоступен: значит, идёт объёмная атака, и на самом сервере у вас больше нет рычагов. Соберите показания из ip -s link и время первых странностей, а затем передайте и то и другое своему провайдеру. В KernelHost вы открываете тикет в личном кабинете; во время идущей атаки с нами можно связаться дополнительно через экстренный чат в WhatsApp по номеру +43 650 8209883.

Короткий чек-лист на критический случай

  1. Измеряйте, а не гадайте: выполните ip -s link show eth0 дважды и вычислите разницу.
  2. Проверьте, что открыты только 9987/UDP и 30033/TCP, и закройте порт Query.
  3. Проконтролируйте защиту от флуда на уровне инстанса и Anti-Flood виртуального сервера.
  4. Если забит сам канал: сохраните цифры и время, затем подключайте провайдера.

Частые вопросы

Мой сервер TeamSpeak сейчас недоступен. Как понять, атака это или нет?
Прочитайте счётчики сетевой карты командой ip -s link show eth0 дважды с интервалом в десять секунд и вычислите разницу. Если число принятых пакетов выросло далеко за обычный уровень, хотя подключено едва ли несколько человек, это говорит в пользу атаки. Если оно осталось обычным, причина скорее в самой службе или в операционной системе.
Помогает ли смена голосового порта 9987 на другой?
Почти нет. Сканирование портов находит новый порт обычно за несколько минут, а всем участникам тем временем приходится править закладки. Как временная мера это в лучшем случае даёт короткую передышку, защитой такой приём не является.
Смогу ли я отбиться от идущей атаки с помощью nftables или iptables?
От отдельных нарушителей да, от распределённой атаки нет. Ограничение частоты по адресу отправителя не сработает, если адрес отправителя подделывается в каждом пакете. И главное: любое правило в операционной системе действует только тогда, когда пакет уже дошёл. Канал перед ней к этому моменту давно забит.
Порт ServerQuery 10011 открыт. Может ли кто-то через него положить мой сервер?
Да, и ботнет для этого никому не нужен. Через порт Query можно перебирать учётные данные и отправлять команды каждую секунду. Привяжите службу параметром query_ip=127.0.0.1 в ts3server.ini только к локальному адресу и обращайтесь к ней через SSH-туннель. Если она нужна боту снаружи, откройте порт исключительно для его постоянного IP-адреса.
Есть ли смысл убирать сервер из публичного списка серверов?
Это отнимает у злоумышленников удобный способ найти ваш адрес, но не прячет его. Кто адрес уже знает, тот его и сохранит, а сканирование диапазона адресов всё равно обнаружит открытый UDP-порт 9987. Отключается запись через ServerQuery командой serveredit virtualserver_weblist_enabled=0.
Убирает ли KernelHost мой IP-адрес из сети во время атаки?
Нет. Null-routing не применяется. Атакуемый IP-адрес остаётся доступным, отбрасываются только вредоносные пакеты. Постоянная защита активна на каждом сервере всё время и не должна сначала запускаться, поэтому в начале атаки нет фазы разгона.
Хватит ли включённой защиты или нужна Advanced DDoS Protection?
Для обычной работы и эпизодических атак включённой постоянной защиты достаточно, она входит в каждый сервер без доплаты: 17 Тбит/с мощности mitigation в глобальной scrubbing-сети плюс 3,2 Тбит/с фильтрации Arbor в реальном времени во Франкфурте-на-Майне. Advanced DDoS Protection от 50,00 € в месяц оправдана тогда, когда проект целенаправленно обстреливают неделями: выделенный защищённый IP-адрес и правила защиты, которыми вы управляете сами по каждому порту и протоколу в личном кабинете. PrePaid, без минимального срока.
Меня атакуют прямо сейчас, а клиентом я ещё не являюсь. Что делать?
Сначала зафиксируйте измерения: частоту пакетов из ip -s link, затронутый IP-адрес, порт и время первых странностей. С этими данными сможет работать ваш текущий провайдер. Если он не фильтрует или уводит ваш IP-адрес в офлайн, надолго помогает только переезд за фильтрацию в сети. Во время идущей атаки с нами можно связаться через экстренный чат в WhatsApp по номеру +43 650 8209883.

TeamSpeak Сервер TeamSpeak 3 Защита от DDoS Голосовой сервер UDP-флуд ServerQuery Anti-Flood Защита игровых серверов