Proteger tu servidor TeamSpeak 3 frente a ataques DDoS

Publicado el 16 min de lectura

Cerrar el puerto de query, afinar el anti-flood y poner un límite de tasa: lo que puedes asegurar tú mismo en un servidor TeamSpeak 3. Y dónde acaban esas medidas, porque la línea que hay delante ya está llena.

Para un clan, un servidor TeamSpeak es el centro neurálgico. Quien lo tumba no corta solo una conversación: corta el entrenamiento, la scrim o la raid. Por eso los servidores de voz acaban tan a menudo en el punto de mira, y casi siempre por gente del propio entorno: una ronda perdida, un baneo, una pelea entre dos clanes.

Este artículo muestra qué puedes asegurar tú mismo sin gastar nada, dónde llegan esas medidas a su límite y qué queda después. Los comandos están escritos para Debian 12, Debian 13, Ubuntu 22.04 LTS y Ubuntu 24.04 LTS. Donde hace falta root, se indica.

Por qué los servidores de voz reciben tantos ataques

Hay tres razones bastante sobrias, y ninguna tiene que ver con el tamaño de tu proyecto.

Primera: la voz en tiempo real no perdona. Una web con un 2 % de pérdida de paquetes no la nota nadie, porque TCP vuelve a enviar los segmentos que faltan. En la voz no hay repetición: un paquete perdido es un hueco en el sonido, y eso lo oye al instante todo el que esté en el canal. Así que un ataque ni siquiera tiene que saturar tu línea para dejarla inservible.

Segunda: el canal de voz no tiene conexión previa. TeamSpeak transporta la voz por UDP. No hay saludo inicial ni estado alguno antes de que llegue el primer paquete. La dirección de origen se puede falsificar sin problema, y tu servidor tiene que mirar cada paquete entrante antes de poder descartarlo. El atacante no necesita ni acceso ni contraseña, solo tu dirección IP y el número de puerto. Qué ocurre técnicamente en ese momento lo explica el artículo ¿Qué es un ataque DDoS?.

Tercera: esa dirección es pública. Está en el Discord, en la web y, si lo tienes activado, en la lista de servidores de TeamSpeak. Un servidor de voz que nadie encuentra no sirve de nada. Por eso el anonimato no es una estrategia de protección.

Los puertos estándar de TeamSpeak 3

Antes de asegurar nada, conviene saber qué está abierto de verdad. Estos son los valores de fábrica de un servidor TeamSpeak 3:

Puerto Protocolo Dirección Función
9987 UDP entrante transmisión de voz (default_voice_port)
30033 TCP entrante transferencia de archivos (avatares, iconos, archivos de canal)
10011 TCP entrante ServerQuery en texto plano (raw)
10022 TCP entrante ServerQuery por SSH
10080 y 10443 TCP entrante ServerQuery por HTTP y por HTTPS respectivamente
41144 TCP entrante TSDNS, solo hace falta si resuelves los nombres por tu cuenta
2008 TCP saliente servicio de licencias y facturación de TeamSpeak
2010 TCP saliente registro en la lista pública de servidores

La fila más importante de esta tabla: desde internet solo tiene que ser accesible 9987/UDP. Todo lo demás es opcional o va detrás de una restricción de acceso.

Qué puedes hacer tú mismo antes de gastar dinero

Los diez pasos que vienen a continuación no cuestan nada y sirven contra los tipos de ataque que más golpean a un servidor de voz: floods de query, spam de joins y floods UDP pequeños desde pocas fuentes.

1. Inventario: qué está escuchando de verdad

Las reglas para servicios que no existen son inofensivas. Un puerto abierto que se te pasa por alto te cuesta la noche entera. Hazte primero una idea general como root:

ss -lntup

La columna que interesa es Local Address:Port. Si ahí pone 0.0.0.0:10011 o [::]:10011, tu acceso ServerQuery es accesible desde todo internet. Si pone 127.0.0.1:10011, solo responde en local y ya no necesita ninguna regla de firewall.

2. Cerrar todo lo que no se necesita

La base es un firewall con la regla por defecto "descartar todo lo entrante". Fíjate bien en el orden, porque si no te dejas fuera a ti mismo. El proceso completo, con vía de rescate incluida, está en la guía Configurar el firewall UFW sin quedarte fuera del servidor. Para un servidor TeamSpeak el resultado queda así:

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

Si de verdad necesitas el acceso ServerQuery desde fuera, ábrelo solo para tu propia dirección. Sustituye 203.0.113.10 por tu dirección IP real:

ufw allow from 203.0.113.10 to any port 10011 proto tcp

Las conexiones salientes no las puedes tapiar del todo. Sin acceso al servicio de licencias y facturación, el servidor TeamSpeak no arranca correctamente.

3. Sacar el puerto ServerQuery de internet

El acceso ServerQuery es la superficie de ataque más subestimada de un servidor TeamSpeak. Por el puerto 10011 se pueden ir probando credenciales y lanzar comandos cada segundo. Eso no es un ataque volumétrico, sino uno muy barato y sin botnet.

Lo más limpio es no sacar el servicio de query hacia fuera. Abre el archivo ts3server.ini del directorio del servidor y pon:

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

Con eso el servicio de query solo escucha en el propio servidor, y cuando lo necesites llegas a él por un túnel SSH. Lo importante es que el archivo se lea de verdad durante el arranque. El parámetro de arranque para eso es:

./ts3server_startscript.sh restart inifile=ts3server.ini

El archivo query_ip_allowlist.txt contiene las direcciones que quedan exentas del control anti-flood del servicio de query, y query_ip_denylist.txt las que están bloqueadas. Los archivos se llaman así a partir de la versión 3.12 del servidor; las versiones anteriores usan query_ip_whitelist.txt y query_ip_blacklist.txt. En la allowlist apunta solo lo que debe estar ahí, normalmente 127.0.0.1. Cada dirección de más es una excepción a la misma protección que acabas de activar.

4. Afinar el control anti-flood de la instancia

El servidor trae su propio freno para ServerQuery. Inicia sesión como serveradmin sin seleccionar ningún servidor virtual y mira primero los valores actuales:

instanceinfo

Para dejarlos más estrictos:

instanceedit serverinstance_serverquery_flood_commands=10 serverinstance_serverquery_flood_time=3 serverinstance_serverquery_ban_time=600

Eso permite diez comandos en tres segundos y después bloquea la dirección durante diez minutos. Si la salida de instanceinfo de tu versión muestra además un tope de conexiones de query simultáneas por dirección, ponlo también en un valor bajo.

5. No usar nunca el acceso de serveradmin para los bots de query

Ranksystem, bot de música, script de estadísticas: casi todos funcionan con las credenciales completas de serveradmin. Si el bot queda comprometido o su contraseña acaba en un archivo de configuración público, el servidor pasa a ser de otro.

En su lugar, crea un acceso de query propio, ligado a una identidad de cliente concreta, y dale a esa identidad solo los permisos que el bot necesita:

queryloginadd client_login_name=ranksystem cldbid=42

El ID de base de datos de tu bot lo encuentras con clientdblist. La contraseña la muestra el servidor una sola vez, después ya no.

6. Configurar el anti-flood del servidor virtual

Además del freno de la instancia, cada servidor virtual tiene su propio sistema de puntos contra el spam de comandos. Cada comando de un cliente cuesta puntos y cada segundo se descuentan puntos. Hay dos umbrales que provocan una reacción: el primero bloquea más comandos, el segundo bloquea la dirección. Selecciona el servidor virtual y ajusta los valores:

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

Esos son los valores por defecto. Si el spam de joins y pokes no cesa, baja los dos umbrales poco a poco y vigila el log. Unos valores demasiado agresivos acaban golpeando a tus propios miembros.

7. Subir el nivel de identidad contra el spam de joins automatizado

Cada identidad de TeamSpeak tiene un nivel de seguridad que se genera a base de cálculo. El servidor puede exigir un nivel mínimo, que de fábrica es el nivel 8. Quien quiera fabricar identidades desechables en masa tiene que calcular una por una:

serveredit virtualserver_needed_identity_security_level=10

Eso funciona contra las oleadas de bots, pero tiene un precio: los miembros que ya están tienen que mejorar su identidad una vez, y a partir del nivel 12 aproximadamente eso tarda un rato incómodo en equipos flojos. Avisa antes de subirlo, en vez de aplicarlo en plena hora punta.

8. Lista de servidores, contraseña del servidor y restricción de acceso real

El registro en la lista pública de servidores hace que tu dirección se pueda encontrar de forma automatizada y no le aporta nada a un servidor de clan cerrado. Para desactivarlo:

serveredit virtualserver_weblist_enabled=0

Sé honesto contigo mismo: eso quita un camino cómodo para llegar a tu dirección, pero no la esconde. Un escaneo del rango de direcciones encuentra igualmente un puerto UDP 9987 abierto.

Una restricción de acceso de verdad se consigue por dos caminos. Dentro de TeamSpeak pones una contraseña de servidor y trabajas con tokens para asignar los grupos. A nivel de red, bastante más duro, abres 9987/UDP solo para direcciones conocidas o pones el servidor de voz dentro de una VPN. Para un grupo fijo de diez personas eso es practicable, para una comunidad abierta no.

Si quieres repartir un nombre en lugar de una dirección IP, usa un registro SRV con la forma _ts3._udp.tu-dominio.es. El cliente lo resuelve por su cuenta, número de puerto incluido, y cuando cambia la IP solo tocas ese registro.

9. Límite de tasa en el host, con una valoración honesta

En los cuatro sistemas mencionados, el filtro de paquetes trabaja por debajo con nftables. Con él puedes limitar la tasa de paquetes por dirección de origen. Crea para eso una tabla propia, así no tienes que tocar una configuración de UFW que ya existe:

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
    }
}

Guarda eso como /etc/nftables.d/ts3.nft, crea antes el directorio si hace falta y carga el archivo como root:

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

Se deshace con nft delete table inet ts3. Tras un reinicio la tabla desaparece, salvo que el archivo se incluya desde /etc/nftables.conf.

Para hacerte una idea del orden de magnitud: un cliente que está hablando envía unos 50 paquetes por segundo con frames de 20 milisegundos. Así que 400 por segundo dejan aire de sobra a varias personas detrás de una misma conexión, y el contador te dice si la regla ha llegado a actuar.

Y ahora la valoración honesta: contra un ataque distribuido esta regla apenas ayuda. Cuenta por dirección de origen, y un atacante falsifica la dirección de origen en cada paquete. Va bien contra los que vienen a molestar por su cuenta y contra clientes mal configurados. No es una defensa contra DDoS.

10. Registrar datos para tener cifras cuando llegue el momento

Cuando empiece de verdad, necesitas mediciones y no la sensación de que algo va a tirones. Los contadores de paquetes y de errores de la tarjeta de red se leen así:

ip -s link show eth0

Ejecutado dos veces con diez segundos de diferencia y restando los valores, eso te da tu tasa de paquetes. Quién mantiene ahora mismo conexiones con el puerto de voz lo muestra:

ss -uan 'sport = :9987'

Una pequeña muestra del tráfico entrante la da:

tcpdump -ni eth0 udp port 9987 -c 20

Los archivos de log del servidor están en el subdirectorio logs/. Con logquerycommands=1 del paso 3, ahí quedan también los comandos de query lanzados, lo que hace visible un abuso a posteriori. Cómo distinguir un ataque de un fallo de configuración lo explica el artículo Detectar un ataque DDoS en el servidor.

Dónde acaban estas medidas

Los diez pasos tienen algo en común: solo actúan cuando el paquete ya ha llegado. Contra las molestias pequeñas eso basta y sobra, contra un ataque volumétrico no, y por un motivo que no tiene nada que ver con tu configuración.

Echa la cuenta: una conectividad de 1 Gbit/s transporta unos 125 megabytes por segundo y, con los paquetes más pequeños posibles, unos 1,49 millones de paquetes por segundo. Con 10 Gbit/s son unos 14,9 millones de paquetes por segundo. Ese es el techo duro de la línea, independientemente de lo que corra en el servidor.

Un ataque medido de verdad contra un servidor TeamSpeak en el puerto 9987 UDP alcanzó más de 473,4 Gbit/s y más de 41,5 millones de paquetes por segundo. Eso es unas 470 veces una conectividad de 1 Gbit/s y todavía casi el triple de la tasa de paquetes que una conectividad de 10 Gbit/s es capaz de transportar.

Lo decisivo es dónde se acumula ese tráfico: no en tu tarjeta de red, sino en la línea que hay delante. Si ese tramo del camino está lleno, los paquetes de tus miembros se pierden ahí antes de que tu servidor llegue a verlos. Una regla de firewall del sistema operativo no puede descargar una línea que termina antes del sistema operativo.

A eso se suma el tiempo de proceso. Aunque tu kernel pudiera descartar millones de paquetes por segundo, cada una de esas decisiones consume CPU. Un servidor de voz ocupado en tirar paquetes suena igual de roto que uno que ya no responde.

Lo que KernelHost pone frente a esos ataques

Nivel 1: la protección permanente incluida en todos los servidores

En cada servidor de KernelHost el filtrado DDoS corre de forma permanente, sin recargo y sin que tengas que activar ni configurar nada. Está montado en dos niveles:

  • Nivel 1: 17 Tbps de capacidad de mitigación en la red global de scrubbing. Los ataques volumétricos se interceptan cerca de su origen, mucho antes de que lleguen al centro de datos. Ese es justamente el nivel que descarga una línea que tú no puedes descargar.
  • Nivel 2: 3,2 Tbps de filtrado Arbor en tiempo real en el maincubes Premium Datacenter de Frankfurt am Main. Justo delante del servidor se reconocen los patrones específicos de cada protocolo y se descarta paquete a paquete, incluidos los floods UDP contra los puertos típicos de servidores de voz y de juego.

Hay dos detalles que pesan más de lo que parece. El primero: la protección está activa de forma permanente y no tiene que arrancar primero, así que no hay una fase inicial en la que un ataque se cuele. El segundo: ninguna dirección IP atacada se saca de la red. Que no haya null-routing significa que tus miembros siguen hablando mientras se filtra. Cómo queda esto para otros títulos y protocolos lo explica el artículo Protección DDoS para servidores de juego en tiempo real.

Nivel 2: Advanced DDoS Protection para proyectos bajo ataque permanente

A algunos proyectos no los golpean una sola vez, sino durante semanas. Para esos casos está la Advanced DDoS Protection desde 50,00 € al mes, PrePaid y sin permanencia mínima. Añade tres cosas a la protección permanente incluida:

  • Una IP de protección dedicada del núcleo de red de Fráncfort, a la que se pasa tu servidor. Por tu parte no hay que reconstruir nada.
  • Reglas de protección gestionables por ti mismo, por puerto y protocolo, en el área de cliente. Ajustas el filtrado de 9987/UDP de forma distinta al de 30033/TCP, sin abrir un ticket, y los cambios surten efecto en tiempo real.
  • Un perfil de protección a medida del juego o del servicio, con perfiles listos para más de 40 juegos y protocolos, TeamSpeak incluido.

PrePaid significa aquí exactamente eso: sin permanencia mínima, sin plazo de preaviso, sin contrato y sin cuota de alta. Contratas la protección mientras dure una oleada de ataques y después la dejas expirar.

Los dos niveles en comparación

Característica Protección permanente incluida Advanced DDoS Protection
Precio incluida sin recargo en todos los servidores desde 50,00 € al mes, PrePaid
Activación ninguna, activa desde el primer minuto se pide en el área de cliente, con IP de protección dedicada
Capacidad 17 Tbps de scrubbing global más 3,2 Tbps de filtrado Arbor en tiempo real en Frankfurt am Main
Reglas de protección perfiles automáticos, mantenidos por el equipo de red gestionables por ti mismo por puerto y protocolo, los cambios surten efecto en tiempo real
Perfil de juego asignado automáticamente lo eliges tú, más de 40 juegos y protocolos
Comportamiento durante el ataque sin null-routing, la dirección IP sigue siendo accesible
Permanencia parte del paquete de servidor PrePaid, sin permanencia mínima y sin plazo de preaviso
Adecuado para el funcionamiento normal y los ataques ocasionales proyectos atacados de forma continua y dirigida

Errores frecuentes y soluciones

Se cambia el puerto de voz para que el ataque caiga en el vacío: eso funciona justo hasta que alguien lanza un escaneo de puertos, es decir, unos pocos minutos. Y mientras tanto todos los miembros tienen que cambiar sus marcadores. Otro puerto solo tiene sentido si de todos modos tienes varias instancias en un mismo servidor.

ServerQuery se queda abierto porque un bot lo necesita: el bot suele correr en el mismo servidor, y entonces basta con query_ip=127.0.0.1. Si corre en otro sitio, abre el puerto solo para su dirección IP fija y créale un acceso limitado con queryloginadd.

Se activa el firewall y el acceso desaparece: en los servidores root KVM y en los servidores dedicados de KernelHost llegas al sistema por la consola VNC del área de cliente. Esa consola no depende del stack de red del sistema invitado, así que ninguna regla de firewall puede bloquearla. Inicia sesión ahí como root y desactiva el firewall con ufw disable antes de buscar la causa.

El límite de tasa está demasiado apretado y golpea a tus propios miembros: lo típico es una residencia de estudiantes o una familia detrás de una misma conexión. Para el filtro eso parece una sola dirección con una cantidad llamativa de paquetes. Revisa el contador con nft list table inet ts3: si sube sin que haya ningún ataque, el valor es demasiado bajo.

El servidor ya no arranca tras el cambio en el archivo ts3server.ini: casi siempre el archivo se ha editado pero no se pasa al arrancar, o al revés. Comprueba las dos cosas y mira el archivo más reciente que haya en logs/, ahí está la causa en texto claro.

Están aplicadas todas las medidas y el servidor sigue caído: entonces hay un ataque volumétrico y en el propio servidor ya no te queda nada en la mano. Reúne los valores de ip -s link y la hora de la primera anomalía, y pásale ambas cosas a tu proveedor. En KernelHost abres un ticket en el área de cliente; durante un ataque en curso puedes contactarnos además por el chat de emergencia de WhatsApp en el +43 650 8209883.

Comprobación rápida para el momento crítico

  1. Medir en vez de adivinar: ejecuta ip -s link show eth0 dos veces y calcula la diferencia.
  2. Comprueba que solo estén abiertos 9987/UDP y 30033/TCP, y cierra el puerto de query.
  3. Revisa el control anti-flood de la instancia y el anti-flood del servidor virtual.
  4. Si la línea en sí está saturada: guarda las cifras y la hora, y después avisa al proveedor.

Preguntas frecuentes

Mi servidor TeamSpeak no está accesible ahora mismo. ¿Cómo sé si es un ataque?
Lee los contadores de la tarjeta de red con ip -s link show eth0 dos veces, con diez segundos de diferencia, y calcula la diferencia. Si el número de paquetes recibidos sube muy por encima de tu valor normal aunque no haya casi nadie conectado, eso apunta a un ataque. Si no muestra nada llamativo, la causa está más bien en el propio servicio o en el sistema operativo.
¿Sirve de algo cambiar el puerto de voz del 9987 a otro puerto?
Apenas. Un escaneo de puertos suele encontrar el puerto nuevo en cuestión de minutos, mientras que todos los miembros tienen que cambiar sus marcadores. Como apaño te da como mucho un respiro corto; como protección no vale nada.
¿Puedo defenderme de un ataque en curso con nftables o iptables?
Contra los que vienen a molestar por su cuenta sí, contra un ataque distribuido no. Un límite de tasa por dirección de origen no sirve de nada cuando esa dirección viene falsificada en cada paquete. Y sobre todo, cualquier regla del sistema operativo actúa solo cuando el paquete ya ha llegado. Para entonces la línea que hay delante ya está llena.
El puerto ServerQuery 10011 está abierto. ¿Puede alguien tumbarme el servidor por ahí?
Sí, y para eso nadie necesita una botnet. Por el puerto de query se pueden ir probando credenciales y lanzar comandos cada segundo. Enlaza el servicio solo en local con query_ip=127.0.0.1 en el archivo ts3server.ini y llega a él por un túnel SSH. Si un bot lo necesita desde fuera, abre el puerto exclusivamente para su dirección IP fija.
¿Sirve de algo sacar el servidor de la lista pública de servidores?
Les quita a los atacantes un camino cómodo para llegar a tu dirección, pero no la esconde. Quien ya conoce la dirección se la queda, y un escaneo del rango de direcciones encuentra igualmente un puerto UDP 9987 abierto. El registro se desactiva por ServerQuery con serveredit virtualserver_weblist_enabled=0.
¿KernelHost saca mi dirección IP de la red durante un ataque?
No. No se utiliza null-routing. La dirección IP atacada sigue siendo accesible y solo se descartan los paquetes dañinos. La protección permanente está activa en todos los servidores y no tiene que arrancar primero, así que no hay una fase inicial al comienzo de un ataque.
¿Basta con la protección incluida o necesito la Advanced DDoS Protection?
Para el funcionamiento normal y los ataques ocasionales basta con la protección permanente incluida, que viene sin recargo en todos los servidores: 17 Tbps de capacidad de mitigación en la red global de scrubbing más 3,2 Tbps de filtrado Arbor en tiempo real en Frankfurt am Main. La Advanced DDoS Protection desde 50,00 € al mes merece la pena cuando atacan un proyecto de forma dirigida durante semanas: IP de protección dedicada y reglas de protección que gestionas tú mismo por puerto y protocolo en el área de cliente. PrePaid y sin permanencia mínima.
Me están atacando ahora mismo y todavía no soy cliente. ¿Qué hago?
Guarda primero las mediciones: la tasa de paquetes de ip -s link, la dirección IP afectada, el puerto y la hora de la primera anomalía. Con eso puede trabajar tu proveedor actual. Si no filtra, o si deja tu dirección IP fuera de línea, a largo plazo solo ayuda mudarse detrás de un filtrado en la red. Durante un ataque en curso puedes contactarnos por el chat de emergencia de WhatsApp en el +43 650 8209883.

TeamSpeak Servidor TeamSpeak 3 Protección DDoS Servidor de voz UDP Flood ServerQuery Anti-flood Protección de servidores de juego