Protéger un serveur TeamSpeak 3 des attaques DDoS

Publié le 16 min de lecture

Fermer le port ServerQuery, durcir l'anti-flood, poser une limitation de débit : ce que vous sécurisez vous-même sur un serveur TeamSpeak 3. Et là où ces mesures s'arrêtent, parce que la ligne est déjà saturée en amont.

Pour un clan, le serveur TeamSpeak est le centre nerveux. Celui qui l'éteint ne met pas seulement fin à une conversation, il met fin à l'entraînement, au scrim ou au raid. C'est exactement pour cette raison que les serveurs vocaux se retrouvent souvent dans le viseur, le plus souvent de personnes issues de l'entourage direct : une manche perdue, un bannissement, une querelle entre deux clans.

Cet article montre ce que vous pouvez sécuriser vous-même sans frais supplémentaires, où ces mesures atteignent leur limite et ce qu'il reste ensuite. Les commandes sont écrites pour Debian 12, Debian 13, Ubuntu 22.04 LTS et Ubuntu 24.04 LTS. Là où root est nécessaire, c'est indiqué.

Pourquoi les serveurs vocaux sont attaqués aussi souvent

Trois raisons très concrètes, et aucune n'a de rapport avec la taille de votre projet.

Premièrement, la voix en temps réel ne pardonne rien. Personne ne remarque un site web qui perd deux pour cent de ses paquets, parce que TCP renvoie les segments manquants. Pour la voix, il n'existe aucune seconde chance : un paquet perdu est un trou dans le son, et tout le monde l'entend aussitôt. Une attaque n'a donc même pas besoin de saturer votre raccordement pour le rendre inutilisable.

Deuxièmement, le canal vocal fonctionne sans connexion. TeamSpeak transporte la voix par UDP. Il n'y a ni poignée de main ni état établi avant l'arrivée du premier paquet. L'adresse source se falsifie librement, et votre serveur doit examiner chaque paquet entrant avant de pouvoir le rejeter. L'attaquant n'a besoin ni d'un accès ni d'un mot de passe, seulement de votre adresse IP et du numéro de port. Ce qui se passe techniquement dans ce cas est décrit dans l'article Qu'est-ce qu'une attaque DDoS ?.

Troisièmement, cette adresse est justement publique. Elle figure sur votre Discord, sur votre site web et, si l'option est activée, dans la liste des serveurs TeamSpeak. Un serveur vocal que personne ne trouve ne sert à rien. L'anonymat n'est donc pas une stratégie de protection.

Les ports par défaut de TeamSpeak 3

Avant de sécuriser quoi que ce soit, vous devez savoir ce qui est ouvert. Voici les réglages d'usine d'un serveur TeamSpeak 3 :

Port Protocole Sens Fonction
9987 UDP entrant Transmission de la voix (default_voice_port)
30033 TCP entrant Transfert de fichiers (avatars, icônes, fichiers de salon)
10011 TCP entrant ServerQuery en clair (raw)
10022 TCP entrant ServerQuery par SSH
10080 et 10443 TCP entrant ServerQuery par HTTP et par HTTPS respectivement
41144 TCP entrant TSDNS, nécessaire uniquement avec votre propre résolution de noms
2008 TCP sortant Service de licence et de facturation de TeamSpeak
2010 TCP sortant Inscription dans la liste publique des serveurs

La ligne la plus importante de ce tableau : seul 9987/UDP doit être joignable depuis Internet. Tout le reste est facultatif ou doit rester derrière une restriction d'accès.

Ce que vous pouvez faire vous-même avant de dépenser de l'argent

Les dix étapes qui suivent ne coûtent rien et agissent contre les types d'attaques qui touchent le plus souvent un serveur vocal : les floods ServerQuery, le spam de connexions et les floods UDP de faible ampleur venant de quelques sources.

1. État des lieux : qu'est-ce qui écoute réellement

Des règles écrites pour des services qui n'existent pas sont sans danger. Un port ouvert que vous avez oublié, lui, vous coûte votre soirée. Commencez donc par faire le tour de la situation en tant que root :

ss -lntup

La colonne qui compte est Local Address:Port. Si vous y lisez 0.0.0.0:10011 ou [::]:10011, votre accès ServerQuery est joignable depuis tout Internet. Si vous y lisez 127.0.0.1:10011, il n'est accessible qu'en local et n'a plus besoin d'aucune règle de pare-feu.

2. Fermer tout ce qui ne sert à rien

La base, c'est un pare-feu dont la règle par défaut est « rejeter tout le trafic entrant ». Faites attention à l'ordre des commandes, sinon vous vous bloquez vous-même l'accès. La procédure complète, voie de secours comprise, est décrite dans le guide Configurer le pare-feu UFW sans se bloquer l'accès SSH. Pour un serveur TeamSpeak, le résultat ressemble à ceci :

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

Si vous avez réellement besoin de l'accès ServerQuery depuis l'extérieur, ne l'ouvrez que pour votre propre adresse. Remplacez 203.0.113.10 par votre adresse IP réelle :

ufw allow from 203.0.113.10 to any port 10011 proto tcp

En revanche, ne murez pas complètement les connexions sortantes. Sans accès au service de licence et de facturation, le serveur TeamSpeak ne démarre pas correctement.

3. Retirer le port ServerQuery d'Internet

L'accès ServerQuery est la surface d'attaque la plus sous-estimée d'un serveur TeamSpeak. Le port 10011 permet de tester des identifiants en série et d'envoyer des commandes en rafale. Ce n'est pas une attaque volumétrique, c'est une attaque très économe, qui se passe de botnet.

La solution la plus propre consiste à ne pas exposer du tout le service ServerQuery vers l'extérieur. Ouvrez le fichier ts3server.ini dans le répertoire du serveur et définissez :

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

Le service ServerQuery n'écoute alors plus que sur le serveur lui-même, et vous l'atteignez au besoin par un tunnel SSH. Encore faut-il que le fichier soit réellement lu au démarrage. Le paramètre de démarrage prévu pour cela est le suivant :

./ts3server_startscript.sh restart inifile=ts3server.ini

Le fichier query_ip_allowlist.txt contient les adresses exemptées du contrôle de flood du service ServerQuery, query_ip_denylist.txt celles qui sont bloquées. Ces noms valent à partir de la version 3.12 du serveur, les versions plus anciennes utilisent query_ip_whitelist.txt et query_ip_blacklist.txt. N'inscrivez dans la liste d'autorisation que ce qui doit s'y trouver, typiquement 127.0.0.1. Chaque adresse supplémentaire est une exception à la protection que vous venez précisément d'activer.

4. Durcir le contrôle de flood de l'instance

Le serveur embarque son propre frein pour ServerQuery. Connectez-vous en tant que serveradmin, sans sélectionner de serveur virtuel, et regardez d'abord les valeurs actuelles :

instanceinfo

Vous les resserrez ainsi :

instanceedit serverinstance_serverquery_flood_commands=10 serverinstance_serverquery_flood_time=3 serverinstance_serverquery_ban_time=600

Cela autorise dix commandes en trois secondes, puis bannit l'adresse pendant dix minutes. Si la sortie d'instanceinfo de votre version affiche en plus une limite du nombre de connexions ServerQuery simultanées par adresse, mettez-la elle aussi à une petite valeur.

5. Ne jamais faire tourner un bot ServerQuery avec le compte serveradmin

Ranksystem, bot de musique, script de statistiques : presque tous tournent avec les identifiants complets du compte serveradmin. Si le bot est compromis, ou si son mot de passe traîne dans un fichier de configuration public, le serveur appartient à quelqu'un d'autre.

Créez plutôt un accès ServerQuery dédié, rattaché à une identité client précise, et n'accordez à cette identité que les droits dont le bot a besoin :

queryloginadd client_login_name=ranksystem cldbid=42

L'identifiant de base de données de votre bot s'obtient avec clientdblist. Le serveur n'affiche le mot de passe qu'une seule fois, jamais ensuite.

6. Régler l'anti-flood du serveur virtuel

À côté du frein de l'instance, chaque serveur virtuel dispose de son propre système de points contre le spam de commandes. Chaque commande d'un client coûte des points, et des points sont retirés à chaque seconde. Deux seuils déclenchent une réaction : le premier bloque les commandes suivantes, le second bannit l'adresse. Sélectionnez le serveur virtuel et ajustez les valeurs :

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

Ce sont les valeurs par défaut. En cas de spam persistant de connexions et de pokes, abaissez les deux seuils par paliers et surveillez le journal. Des valeurs trop agressives touchent vos propres membres.

7. Relever le niveau de sécurité des identités contre le spam de connexions automatisé

Chaque identité TeamSpeak possède un niveau de sécurité, obtenu au prix de calculs. Le serveur peut exiger un niveau minimal, réglé sur 8 en usine. Qui veut produire des identités jetables en masse doit calculer pour chacune d'elles :

serveredit virtualserver_needed_identity_security_level=10

C'est efficace contre les vagues de bots, mais cela a un prix : les membres existants doivent améliorer leur identité une fois, et à partir du niveau 12 environ, l'opération devient désagréablement longue sur les machines modestes. Annoncez une augmentation à l'avance plutôt que de l'appliquer en pleine heure de pointe.

8. Liste des serveurs, mot de passe du serveur et véritable restriction d'accès

L'inscription dans la liste publique des serveurs rend votre adresse repérable automatiquement et n'apporte rien à un serveur de clan fermé. Pour la désactiver :

serveredit virtualserver_weblist_enabled=0

Restez honnête avec vous-même : cela supprime un moyen commode de trouver votre adresse, mais ne la cache pas. Un scan de la plage d'adresses trouve de toute façon un port UDP 9987 ouvert.

Une véritable restriction d'accès passe par deux voies. À l'intérieur de TeamSpeak, vous définissez un mot de passe de serveur et vous travaillez avec des tokens pour l'attribution des groupes. Au niveau du réseau, ce qui est nettement plus strict, vous n'ouvrez 9987/UDP que pour des adresses connues, ou vous exploitez le serveur vocal à l'intérieur d'un VPN. Pour un cercle fixe de dix personnes, c'est praticable ; pour une communauté ouverte, non.

Si vous voulez distribuer un nom plutôt qu'une adresse IP, utilisez un enregistrement SRV de la forme _ts3._udp.votre-domaine.fr. Le client le résout lui-même, numéro de port compris, et lors d'un changement d'adresse IP vous ne modifiez que cet unique enregistrement.

9. Limitation de débit sur l'hôte, avec une mise en perspective honnête

Sur les quatre systèmes cités, le filtre de paquets repose sur nftables sous le capot. Cela permet de limiter le taux de paquets par adresse source. Créez pour cela une table à part, afin de ne pas avoir à toucher à une configuration UFW existante :

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

Enregistrez ce contenu sous /etc/nftables.d/ts3.nft, créez au besoin le répertoire au préalable, puis chargez le fichier en tant que root :

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

Vous revenez en arrière avec nft delete table inet ts3. Après un redémarrage, la table a disparu, sauf si le fichier est inclus depuis /etc/nftables.conf.

Pour situer l'ordre de grandeur : avec des trames de 20 millisecondes, un client qui parle envoie environ 50 paquets par seconde. 400 paquets par seconde laissent donc largement de la marge à plusieurs personnes derrière un même raccordement, et le compteur indique si la règle a effectivement agi.

Et maintenant la mise en perspective honnête : contre une attaque distribuée, cette règle n'aide quasiment pas. Elle compte par adresse source, or un attaquant falsifie l'adresse source dans chaque paquet. Elle est efficace contre des perturbateurs isolés et contre des clients mal configurés. Ce n'est pas une défense contre le DDoS.

10. Journaliser pour disposer de chiffres le jour venu

Quand cela commence, il vous faut des mesures et non l'impression que quelque chose coince. Les compteurs de paquets et d'erreurs de la carte réseau se lisent ainsi :

ip -s link show eth0

Exécutez la commande deux fois à dix secondes d'intervalle et faites la différence : vous obtenez ainsi votre taux de paquets. Pour voir qui entretient en ce moment des connexions vers le port vocal :

ss -uan 'sport = :9987'

Un petit échantillon du trafic entrant s'obtient avec :

tcpdump -ni eth0 udp port 9987 -c 20

Les fichiers journaux du serveur se trouvent dans le sous-répertoire logs/. Avec logquerycommands=1 de l'étape 3, les commandes ServerQuery envoyées y figurent également, ce qui rend un abus visible après coup. Comment distinguer une attaque d'une erreur de configuration, c'est l'objet de l'article Détecter une attaque DDoS sur le serveur.

Là où ces mesures s'arrêtent

Les dix étapes ont un point commun : elles n'agissent qu'une fois le paquet arrivé. Pour de petites perturbations, cela suffit largement ; pour une attaque volumétrique, non, et ce pour une raison qui n'a rien à voir avec votre configuration.

Faites le calcul : un raccordement à 1 Gbit/s transporte environ 125 mégaoctets par seconde et, avec les plus petits paquets, quelque 1,49 million de paquets par seconde. À 10 Gbit/s, cela donne environ 14,9 millions de paquets par seconde. C'est la limite dure de la ligne, indépendamment de ce qui tourne sur le serveur.

Une attaque réellement mesurée contre un serveur TeamSpeak sur le port 9987 UDP a atteint plus de 473,4 Gbit/s et plus de 41,5 millions de paquets par seconde. Cela représente environ 470 fois un raccordement à 1 Gbit/s, et encore presque le triple du taux de paquets qu'un raccordement à 10 Gbit/s est capable de transporter.

L'endroit où ce trafic s'accumule est décisif : pas sur votre carte réseau, mais sur la ligne qui la précède. Si ce tronçon est saturé, les paquets de vos membres s'y perdent avant même que votre serveur ne les voie. Une règle de pare-feu dans le système d'exploitation ne peut pas soulager une ligne qui se termine en amont de ce système d'exploitation.

S'y ajoute le temps de calcul. Même si votre noyau pouvait rejeter des millions de paquets par seconde, chacune de ces décisions coûte du CPU. Pour vos membres, un serveur vocal occupé à jeter des paquets est aussi inutilisable qu'un serveur qui ne répond plus du tout.

Ce que KernelHost oppose à cela

Niveau 1 : la protection permanente incluse sur chaque serveur

Sur chaque serveur de KernelHost, le filtrage DDoS tourne en permanence, sans supplément et sans que vous ayez quoi que ce soit à activer ou à configurer. Il repose sur deux niveaux :

  • Niveau 1 : 17 Tbps de capacité de mitigation dans le réseau de scrubbing mondial. Les attaques volumétriques sont interceptées au plus près de leur source, bien avant d'atteindre le centre de données. C'est précisément le niveau qui soulage une ligne que vous ne pouvez pas soulager vous-même.
  • Niveau 2 : filtrage Arbor en temps réel à 3,2 Tbps dans le maincubes Premium Datacenter à Francfort-sur-le-Main. Juste devant le serveur, les schémas propres à chaque protocole sont identifiés et rejetés paquet par paquet, dont les floods UDP sur les ports habituels des serveurs vocaux et des serveurs de jeu.

Deux points comptent davantage qu'il n'y paraît. D'abord, la protection est active en permanence et n'a pas besoin de se déclencher : il n'existe donc pas de phase de démarrage pendant laquelle une attaque passe. Ensuite, aucune adresse IP attaquée n'est retirée du réseau : l'absence de null-routing signifie que vos membres continuent de parler pendant que le filtrage travaille. Ce que cela donne pour d'autres jeux et protocoles est décrit dans l'article Protection DDoS des serveurs de jeu en temps réel.

Niveau 2 : Advanced DDoS Protection pour les projets attaqués en continu

Certains projets ne sont pas touchés une seule fois, mais pendant des semaines. Pour ces cas, il existe l'Advanced DDoS Protection à partir de 50,00 € par mois, en PrePaid et sans durée minimale. Elle complète la protection permanente incluse sur trois points :

  • Une IP protégée dédiée issue du cœur de réseau de Francfort, vers laquelle votre serveur est basculé. Aucune modification n'est nécessaire de votre côté.
  • Des règles de protection par port et par protocole, que vous gérez vous-même dans l'espace client. Vous réglez le filtrage autrement pour 9987/UDP que pour 30033/TCP, sans avoir à ouvrir de ticket, et les changements s'appliquent en temps réel.
  • Un profil de protection adapté au jeu ou au service concerné, avec des profils prêts à l'emploi pour plus de 40 jeux et protocoles, TeamSpeak compris.

PrePaid signifie ici exactement cela : pas de durée minimale, pas de préavis, pas de contrat, pas de frais de mise en service. Vous ajoutez la protection le temps d'une vague d'attaques et vous la laissez expirer ensuite.

Les deux niveaux comparés

Caractéristique Protection permanente incluse Advanced DDoS Protection
Prix comprise sans supplément dans chaque serveur à partir de 50,00 € par mois, PrePaid
Mise en service aucune, active dès la première minute commande dans l'espace client, IP protégée dédiée
Capacité 17 Tbps de scrubbing mondial plus filtrage Arbor en temps réel à 3,2 Tbps à Francfort-sur-le-Main
Règles de protection profils automatiques, maintenus par l'équipe réseau gérables vous-même par port et par protocole, les changements s'appliquent en temps réel
Profil de jeu attribué automatiquement au choix, plus de 40 jeux et protocoles
Comportement pendant une attaque pas de null-routing, l'adresse IP reste joignable
Durée comprise dans le pack serveur PrePaid, sans durée minimale, sans préavis
Adaptée à l'exploitation normale et les attaques occasionnelles les projets visés en continu et de façon ciblée

Erreurs fréquentes et solutions

Le port vocal est changé pour que l'attaque tombe dans le vide : cela fonctionne exactement jusqu'à ce que quelqu'un lance un scan de ports, donc le plus souvent quelques minutes. Dans le même temps, tous les membres doivent adapter leurs favoris. Un autre port n'a de sens que si vous exploitez de toute façon plusieurs instances sur un même serveur.

ServerQuery reste ouvert parce qu'un bot en a besoin : le bot tourne en règle générale sur le même serveur, et query_ip=127.0.0.1 suffit alors. S'il tourne ailleurs, n'ouvrez le port que pour son adresse IP fixe et créez-lui un accès restreint avec queryloginadd.

Le pare-feu est activé et l'accès a disparu : sur les serveurs root KVM et les serveurs dédiés de KernelHost, vous atteignez le système par la console VNC dans l'espace client. Cette console ne dépend pas de la pile réseau du système invité, aucune règle de pare-feu ne peut donc la bloquer. Connectez-vous-y en tant que root et désactivez le pare-feu avec ufw disable avant de chercher la cause.

La limitation de débit est réglée trop serré et touche vos propres membres : le cas typique est une résidence étudiante ou une famille derrière un raccordement commun. Pour le filtre, cela ressemble à une adresse unique avec un nombre de paquets remarquablement élevé. Vérifiez le compteur avec nft list table inet ts3 : s'il monte alors qu'aucune attaque n'est en cours, la valeur est trop basse.

Le serveur ne démarre plus après la modification de la ts3server.ini : presque toujours, le fichier a été modifié mais n'a pas été passé au démarrage, ou l'inverse. Vérifiez les deux points et ouvrez le fichier le plus récent sous logs/, la cause y figure en clair.

Toutes les mesures sont en place et le serveur reste malgré tout injoignable : il s'agit alors d'une attaque volumétrique, et vous n'avez plus aucune prise sur le serveur lui-même. Rassemblez les valeurs relevées par ip -s link ainsi que l'heure de la première anomalie, puis transmettez le tout à votre hébergeur. Chez KernelHost, vous ouvrez un ticket dans l'espace client ; pendant une attaque en cours, vous nous joignez en plus par le chat d'urgence WhatsApp au +43 650 8209883.

Vérification rapide en cas d'urgence

  1. Mesurer plutôt que deviner : exécuter ip -s link show eth0 deux fois et faire la différence.
  2. Vérifier que seuls 9987/UDP et 30033/TCP sont ouverts, et fermer le port ServerQuery.
  3. Vérifier le contrôle de flood de l'instance et l'anti-flood du serveur virtuel.
  4. Si la ligne elle-même est saturée : sauvegarder les chiffres et l'heure, puis solliciter l'hébergeur.

Questions fréquentes

Mon serveur TeamSpeak est injoignable en ce moment. Comment savoir s'il s'agit d'une attaque ?
Lisez les compteurs de la carte réseau avec ip -s link show eth0 deux fois à dix secondes d'intervalle et faites la différence. Si le nombre de paquets reçus monte largement au-dessus de la valeur habituelle alors que presque personne n'est connecté, cela plaide pour une attaque. S'il reste normal, la cause se situe plutôt dans le service lui-même ou dans le système d'exploitation.
Est-il utile de faire passer le port vocal de 9987 à un autre port ?
Guère. Un scan de ports trouve le nouveau port en quelques minutes le plus souvent, alors que tous les membres doivent adapter leurs favoris. Comme solution de fortune, cela vous fait gagner au mieux une courte pause ; comme protection, cela ne vaut rien.
Puis-je me défendre contre une attaque en cours avec nftables ou iptables ?
Contre des perturbateurs isolés, oui ; contre une attaque distribuée, non. Une limitation de débit par adresse source n'agit pas quand l'adresse source est falsifiée dans chaque paquet. Surtout, toute règle du système d'exploitation n'intervient qu'une fois le paquet arrivé. La ligne en amont est alors déjà saturée.
Le port ServerQuery 10011 est ouvert. Quelqu'un peut-il paralyser mon serveur par ce biais ?
Oui, et sans avoir besoin d'un botnet. Le port ServerQuery permet de tester des identifiants en série et d'envoyer des commandes en rafale. Attachez le service uniquement en local avec query_ip=127.0.0.1 dans la ts3server.ini et atteignez-le par un tunnel SSH. Si un bot en a besoin depuis l'extérieur, n'ouvrez le port que pour son adresse IP fixe.
Est-ce que retirer le serveur de la liste publique des serveurs apporte quelque chose ?
Cela enlève aux attaquants un moyen commode de trouver votre adresse, mais ne la cache pas. Qui connaît l'adresse la garde, et un scan de la plage d'adresses trouve de toute façon un port UDP 9987 ouvert. L'inscription se désactive par ServerQuery avec serveredit virtualserver_weblist_enabled=0.
KernelHost retire-t-il mon adresse IP du réseau pendant une attaque ?
Non. Aucun null-routing n'est utilisé. L'adresse IP attaquée reste joignable, seuls les paquets malveillants sont rejetés. La protection permanente est active en continu sur chaque serveur et n'a pas besoin de se déclencher : il n'existe donc pas de phase de démarrage au début d'une attaque.
La protection incluse suffit-elle ou me faut-il l'Advanced DDoS Protection ?
Pour l'exploitation normale et les attaques occasionnelles, la protection permanente incluse suffit ; elle accompagne chaque serveur sans supplément : 17 Tbps de capacité de mitigation dans le réseau de scrubbing mondial plus 3,2 Tbps de filtrage Arbor en temps réel à Francfort-sur-le-Main. L'Advanced DDoS Protection à partir de 50,00 € par mois vaut la peine quand un projet est visé de façon ciblée pendant des semaines : IP protégée dédiée et règles de protection que vous gérez vous-même par port et par protocole dans l'espace client. En PrePaid, sans durée minimale.
Je suis attaqué en ce moment et je ne suis pas encore client. Que faire maintenant ?
Sauvegardez d'abord des mesures : taux de paquets relevé par ip -s link, adresse IP concernée, port et heure de la première anomalie. Votre hébergeur actuel peut travailler avec cela. S'il ne filtre pas, ou s'il met votre adresse IP hors ligne, seul un déménagement derrière un filtrage dans le réseau règle durablement le problème. Pendant une attaque en cours, vous nous joignez par le chat d'urgence WhatsApp au +43 650 8209883.

TeamSpeak Serveur TeamSpeak 3 Protection DDoS Serveur vocal Flood UDP ServerQuery Anti-flood Protection des serveurs de jeu