Protéger un serveur Garry's Mod des attaques DDoS

Publié le 28 min de lecture

Chez Garry's Mod, le trafic de jeu et la requête d'état passent par le même port 27015. Quelles règles agissent réellement sur le serveur, comment sécuriser RCON et les événements réseau Lua, et à partir de quelle taille d'attaque seul le filtrage dans le réseau en amont agit encore.

Un serveur Garry's Mod qui disparaît trois minutes à vingt heures et revient ensuite a rarement un problème de matériel. Dans la très grande majorité des cas, une attaque est en cours, et elle se produit précisément au moment où le plus grand nombre de joueurs sont connectés. La protection DDoS pour Garry's Mod consiste donc d'abord à savoir quels paquets ont le droit d'arriver sur votre serveur. Cet article montre, dans cet ordre, ce que vous pouvez sécuriser vous-même dans les dix prochaines minutes sans dépenser un centime, où ces mesures s'arrêtent physiquement, et ce qui doit ensuite se passer dans le réseau, en amont du serveur.

Toutes les indications se rapportent à un serveur srcds sous Debian 12, Debian 13, Ubuntu 22.04 LTS ou Ubuntu 24.04 LTS. Le fichier de configuration se trouve dans garrysmod/cfg/server.cfg, les commandes sont écrites pour root ; en tant qu'utilisateur normal, faites-les précéder de sudo. Il est toujours question d'une exploitation sur votre propre serveur root ou serveur dédié, et non d'un slot chez un hébergeur de serveurs de jeu.

Si l'attaque est en cours : ne modifiez rien dans server.cfg maintenant et ne redémarrez pas srcds. Sauvegardez d'abord vos mesures (section 9), car après l'attaque elles auront disparu. Un redémarrage vous coûte les compteurs et replace ensuite le serveur dans la même inondation.

Pourquoi un serveur Garry's Mod a besoin d'une protection DDoS

Un serveur Garry's Mod publie lui-même son adresse IP et son port. Ce n'est pas une négligence, c'est une condition de fonctionnement : celui qui n'apparaît pas dans le navigateur de serveurs n'obtient aucun nouveau joueur. L'entrée existe parce que le serveur s'enregistre auprès du serveur maître de Steam et répond ensuite à chaque requête A2S venue de l'extérieur. La question n'est donc jamais de savoir si un attaquant trouvera votre adresse, mais uniquement ce qui se passe quand il tire dessus.

S'y ajoute la nature des communautés. Garry's Mod ne se joue pas principalement en manches, mais dans des mondes durables : une communauté DarkRP conserve des mois durant les comptes des joueurs, leurs biens, leurs métiers et leur progression dans une base de données. Une panne le vendredi soir coûte donc plus qu'un match perdu, elle coûte des joueurs réguliers. C'est précisément pour cela que les communautés concurrentes, les joueurs bannis et les booters achetés (des services qui déclenchent, pour quelques euros par mois, des attaques contre n'importe quelle adresse) sont les trois déclencheurs les plus fréquents. L'attaquant n'a besoin pour cela ni de compétence particulière ni d'argent notable.

Sur le plan technique, trois particularités se cumulent. Le trafic de jeu passe par UDP, et UDP ne prévoit aucun établissement de connexion que l'on pourrait exiger : les adresses source se falsifient sans peine. La requête d'état occupe le même port que le jeu, un blocage grossier touche donc toujours les deux. Et au-dessus de tout cela il y a Lua : chaque addon du Workshop apporte son propre code dans le même processus, et un seul événement réseau non protégé suffit pour qu'un unique client ralentisse le serveur sans aucune bande passante. Ce qu'est fondamentalement une attaque DDoS, l'article Qu'est-ce qu'une attaque DDoS ? l'explique.

Les ports dont il est réellement question chez Garry's Mod

Un serveur Garry's Mod démarre par défaut sur le port 27015, en UDP pour le jeu et la requête d'état, en TCP pour RCON. Le numéro se change au démarrage avec -port ; avec plusieurs instances, on incrémente (27016, 27017 et ainsi de suite). Une ligne de démarrage typique ressemble à ceci :

./srcds_run -game garrysmod -console \
  -port 27015 \
  +maxplayers 64 \
  +gamemode darkrp \
  +map rp_downtown_v4c_v2 \
  +sv_setsteamaccount VOTRE_TOKEN_GSLT \
  +host_workshop_collection 123456789 \
  -authkey VOTRE_CLE_API_WEB_STEAM

Il en découle toute la surface d'attaque. Le tableau suivant sert de base à chaque règle de pare-feu présentée plus bas :

Port et protocole Pour quoi Modifiable par A sa place sur le réseau ouvert
27015/UDP Trafic de jeu et requête A2S sur le même port -port oui, c'est le seul port qui doit réellement être ouvert
27015/TCP RCON, le protocole RCON de Source -port (même numéro que le jeu) non, uniquement pour votre propre adresse
27005/UDP Port client, il part du joueur -clientport non, aucune règle nécessaire sur le serveur
27020/UDP SourceTV +tv_port uniquement si vous diffusez réellement
26901/UDP Enregistrement auprès du serveur maître de Steam sortant non, aucune règle d'entrée nécessaire
80/TCP et 443/TCP FastDL via sv_downloadurl, si le serveur web se trouve sur le même hôte Serveur web uniquement si FastDL s'y trouve (mieux vaut séparer)
3306/TCP MySQL pour DarkRP et les données des joueurs (via le module mysqloo) bind-address non, exclusivement 127.0.0.1
22/TCP Accès SSH sshd_config oui, mais de façon restreinte

Sur ces huit entrées, une seule a sa place sans restriction sur le réseau ouvert : 27015/UDP. Tout le reste est soit limité à votre propre adresse, soit lié à 127.0.0.1, soit tout simplement jamais démarré. L'erreur de raisonnement la plus coûteuse dans ce domaine consiste à croire qu'il existe chez Garry's Mod un port de requête séparé que l'on pourrait simplement fermer. Il n'en existe pas.

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

Cette section est la plus longue, et c'est volontaire. Un serveur Garry's Mod proprement configuré encaisse par ses propres moyens les attaques petites et moyennes, quel que soit l'hébergeur chez qui il se trouve. Rien de tout cela ne coûte d'argent, et l'essentiel est réglé en un quart d'heure.

1. État des lieux : qu'est-ce qui écoute au juste

Avant d'écrire la moindre règle, regardez ce que votre serveur propose vers l'extérieur. Ne devinez pas, vérifiez :

ss -lntup

La colonne qui compte est celle de l'adresse locale. 0.0.0.0:27015 et [::]:27015 signifient « joignable depuis tout Internet », 127.0.0.1:3306 signifie « en local uniquement » et ne demande aucune règle de pare-feu. Sur un serveur DarkRP qui a vécu, on y trouve presque toujours plus de services que prévu : MySQL, un serveur web pour FastDL, un panneau de contrôle, un bot Discord, un second serveur de test sur 27016 et un service vocal oublié depuis longtemps. Le point de vue de l'attaquant s'obtient par un scan de ports depuis l'extérieur :

nmap -Pn -sU -sT -p- --min-rate 1000 ADRESSE.IP.DE.VOTRE.SERVEUR

2. Ne laisser ouverts que les ports dont srcds a réellement besoin

Pour Garry's Mod, une seule ouverture vers l'extérieur suffit, à laquelle s'ajoutent SSH et l'accès RCON restreint. Avec UFW, cela donne ceci, et exactement dans cet ordre, pour ne pas vous bloquer vous-même :

ufw allow 22/tcp comment 'SSH'
ufw allow 27015/udp comment 'Garrys Mod jeu et A2S'
ufw allow from 203.0.113.10 to any port 27015 proto tcp comment 'RCON'
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose

Remplacez 203.0.113.10 par votre propre adresse. N'ouvrez SourceTV sur 27020/UDP que si vous diffusez réellement. Le guide complet, voie de secours comprise, se trouve dans Configurer le pare-feu UFW sans se bloquer l'accès SSH. Si cela arrive quand même : les serveurs root KVM et les serveurs dédiés de KernelHost n'ont ni IPMI ni iDRAC, vous revenez par la console VNC de l'espace client. Celle-ci ne dépend pas de la pile réseau du système invité, aucune règle de pare-feu à l'intérieur de l'invité ne peut donc la bloquer.

La base de données n'a en aucun cas sa place sur le réseau ouvert. Vérifiez dans /etc/mysql/mariadb.conf.d/50-server.cnf que la ligne suivante est bien présente :

bind-address = 127.0.0.1

3. Limiter la requête A2S sans disparaître de la liste des serveurs

C'est ici que se trouve l'erreur qui coûte le plus de serveurs Garry's Mod. Comme le trafic de jeu et la requête d'état occupent le même port, un blocage global ou une limitation de débit trop stricte sur 27015/UDP éjecte vos propres joueurs et termine l'attaque à la place de l'attaquant. Le bon point d'accroche est la distinction entre paquets de requête et paquets de jeu.

Le moteur apporte pour cela trois variables de console, qui figurent dans server.cfg. Leurs valeurs par défaut sont prudentes, mais elles sont bien définies :

sv_max_queries_sec 3
sv_max_queries_sec_global 60
sv_max_queries_window 30

sv_max_queries_sec limite le nombre de requêtes auxquelles le serveur répond par adresse source (valeur par défaut 3 par seconde), sv_max_queries_sec_global plafonne le total sur l'ensemble des adresses (valeur par défaut 60 par seconde), sv_max_queries_window fixe la fenêtre de moyennage (valeur par défaut 30 secondes). Ces valeurs évitent au CPU de produire des réponses inutiles. Elles n'empêchent pas les paquets d'arriver, et celui qui resserre trop la valeur globale disparaît du navigateur de serveurs pendant l'attaque, parce que les requêtes des sites de listing restent elles aussi sans réponse.

Un cran plus bas, le trafic de requêtes se sépare proprement. Tous les paquets sans connexion du moteur Source commencent par quatre octets à un (0xffffffff), alors que le trafic des joueurs déjà connectés n'a pas cet en-tête. C'est exactement là-dessus que nftables permet de poser une limitation de débit par adresse source :

table inet gmod {
    chain input {
        type filter hook input priority -10; policy accept;
        udp dport 27015 @th,64,32 0xffffffff \
            meter a2sflood { ip saddr limit rate over 8/second burst 20 packets } drop
    }
}

Vous chargez le fichier avec nft -f. La priorité -10 fait que la règle s'applique avant la chaîne de filtrage d'UFW, et @th,64,32 lit les quatre premiers octets situés après l'en-tête UDP. Avec iptables classique, une comparaison u32 fait la même chose :

iptables -A INPUT -p udp --dport 27015 \
  -m u32 --u32 "0>>22&0x3C@8=0xFFFFFFFF" \
  -m hashlimit --hashlimit-name gmod_a2s --hashlimit-mode srcip \
  --hashlimit-above 8/sec --hashlimit-burst 20 -j DROP

Un point que presque tous les guides du web passent sous silence : la requête d'état n'est pas la seule à être sans connexion, l'établissement de connexion l'est aussi. Un joueur qui rejoint la partie envoie plusieurs paquets portant le même en-tête avant d'être en jeu. Une limite trop stricte exclut donc les nouveaux joueurs, alors même que le serveur reste joignable. Commencez large (8 à 15 paquets par seconde et par adresse) et ne resserrez la limite qu'après avoir mesuré une semaine de fonctionnement normal.

4. Sécuriser RCON ou le désactiver complètement

Sur les serveurs Source, RCON est une cible prisée, et ce pour trois raisons à la fois. Premièrement, il occupe le même numéro de port que le jeu, seulement en TCP, et se trouve donc sans la moindre recherche. Deuxièmement, le protocole RCON de Source transmet le mot de passe en clair, sans TLS et sans échange de clés : qui lit le trafic le possède. Troisièmement, le gain est maximal, car celui qui dispose de RCON peut changer de carte, bannir tous les joueurs, modifier la configuration et arrêter le serveur. Un attaquant qui prend RCON n'a plus besoin d'aucune bande passante.

Ne laissez jamais rcon_password vide et ne le composez jamais de tête, une valeur issue de openssl rand -base64 32 suffit. Contre les tentatives de connexion, le moteur apporte un frein :

rcon_password "UN_LONG_MOT_DE_PASSE_ALEATOIRE"
sv_rcon_minfailures 3
sv_rcon_maxfailures 5
sv_rcon_minfailuretime 30
sv_rcon_banpenalty 1440

Une adresse est ainsi bannie pour une journée après trois échecs en 30 secondes. Deux mises en garde à ce sujet. Premièrement, ce mécanisme bannit aussi votre propre panneau d'administration si un ancien mot de passe y est enregistré : ce que les exploitants signalent comme « RCON ne fonctionne plus du jour au lendemain » est le plus souvent leur propre bannissement. Deuxièmement, la restriction de pare-feu de l'étape 2 reste plus efficace, car elle empêche la tentative d'atteindre l'application. Si vous n'avez besoin de RCON qu'occasionnellement, laissez le port entièrement fermé et travaillez par une redirection de port SSH :

ssh -N -L 27015:127.0.0.1:27015 root@ADRESSE.IP.DE.VOTRE.SERVEUR

5. Limiter les messages réseau Lua, la panne maison la plus fréquente

Une part importante des pannes Garry's Mod signalées comme DDoS n'en sont pas. Ce sont des surcharges Lua, déclenchées par un seul client connecté avec quelques kilobits par seconde. La raison tient à la conception de la bibliothèque net : dès qu'un addon enregistre un événement réseau avec util.AddNetworkString et l'écoute avec net.Receive, n'importe quel client peut déclencher cet événement en boucle. Sans limitation propre, le serveur exécute chaque message, un par un. Facepunch l'a documenté à plusieurs reprises dans ses propres rapports d'erreurs et n'a prévu aucune solution dans le moteur : la limitation incombe explicitement à l'auteur de l'addon.

Vérifiez donc trois choses sur chaque addon, le vôtre comme celui que vous avez acheté : un plafond par joueur et par seconde, un contrôle de la longueur du message, et le fait que le joueur soit déterminé côté serveur à partir du deuxième paramètre plutôt qu'à partir du contenu du message. Voici un schéma solide :

util.AddNetworkString("khrp_buy")

local budget = {}

net.Receive("khrp_buy", function(len, ply)
    if not IsValid(ply) then return end
    if len > 256 then return end

    local now = CurTime()
    local b = budget[ply]

    if not b or now - b.start >= 1 then
        b = { start = now, count = 0 }
        budget[ply] = b
    end

    b.count = b.count + 1
    if b.count > 10 then return end

    KHRP.HandleBuy(ply, net.ReadString())
end)

hook.Add("PlayerDisconnected", "khrp_budget_cleanup", function(ply)
    budget[ply] = nil
end)

S'y ajoutent deux lignes dans server.cfg. Dans Garry's Mod, sv_allowcslua vaut 1 par défaut et permet aux clients d'exécuter leur propre code avec lua_run_cl et lua_openscript_cl : sur un serveur public, cette valeur doit être à 0. Et sv_kickerrornum déconnecte les clients qui produisent plus que le nombre indiqué d'erreurs côté client (valeur par défaut 0, donc désactivé) :

sv_allowcslua 0
sv_kickerrornum 25

6. Séparer les contenus du Workshop et FastDL du serveur de jeu

Chez Garry's Mod, les addons du Workshop ne sont pas un sujet marginal, ils sont la norme : une communauté DarkRP intègre sa collection avec +host_workshop_collection, et les clients téléchargent ces contenus directement depuis Steam. Cela ne charge pas votre liaison. La clé passée à -authkey est une clé de l'API web de Steam et doit être traitée comme un mot de passe : dans le script de démarrage, pas dans un dépôt public ni dans un canal Discord.

C'est le second chemin qui coûte de la bande passante. Tout ce qui ne vient pas du Workshop (cartes maison, sons, matériaux) passe par le canal de téléchargement. Sans sv_downloadurl, ce canal emprunte le port de jeu lui-même et entre en concurrence directe avec le trafic de jeu. Avec FastDL, il passe par HTTP. Si ce serveur web se trouve sur le même hôte et la même adresse IP, les deux partagent la même liaison : une vague d'arrivées ou une attaque sur 80/TCP touche donc aussi le jeu. Ces valeurs sont pertinentes :

sv_downloadurl "https://fastdl.votre-domaine.fr/garrysmod/"
sv_allowdownload 1
sv_allowupload 0
net_maxfilesize 64

sv_allowupload 0 retire aux clients la possibilité d'envoyer leurs propres fichiers au serveur et ferme ainsi une voie qui n'est ni nécessaire ni contrôlée. net_maxfilesize limite en mégaoctets la taille des fichiers transmis par le canal de jeu. Placez FastDL si possible sur un autre hôte ou derrière un nom distinct, la charge ne reposera alors pas sur la même adresse que le port de jeu.

7. Absorber le flood d'arrivées et l'épuisement des places

L'épuisement des places est une attaque qui n'a besoin d'aucune bande passante : l'attaquant occupe toutes les places libres avec des connexions automatisées, si bien que les vrais joueurs voient un serveur complet. Chez Garry's Mod, une difficulté s'ajoute : chaque arrivée coûte du travail au serveur, parce que la liste des ressources et le gamemode sont négociés bien avant que le joueur ne soit en jeu.

Quatre choses y répondent. Premièrement, un plafond réaliste : régler +maxplayers plus haut que ce que votre gamemode supporte ne fait qu'agrandir la surface d'attaque. Deuxièmement sv_timeout, qui fixe après combien de secondes sans message un client est déconnecté (120 dans les configurations répandues) : qui veut se débarrasser plus vite des demi-connexions en suspens abaisse cette valeur. Troisièmement, la limitation de débit des paquets sans connexion de l'étape 3, car l'établissement de connexion passe exactement par là. Quatrièmement, pour les groupes fermés, un mot de passe de serveur :

sv_password "groupe_habituel_2026"
sv_timeout 90
sv_filterban 1
sv_region 3

Garry's Mod n'embarque pas de véritable liste blanche ; elle passe par des extensions comme ULX ou par un contrôle maison dans le hook CheckPassword. Et une chose doit être claire : une liste blanche protège votre logique de jeu, pas votre liaison. Un attaquant qui inonde votre serveur ne cherche pas du tout à le rejoindre. Ses paquets sont refusés, mais ils sont malgré tout arrivés, et c'est précisément là que se situe le problème.

8. Soulager le noyau : suivi de connexions et tampon de réception

Cette étape explique des pannes qui ressemblent à une attaque volumétrique sans en être une. Le noyau crée pour le trafic UDP des entrées dans le suivi de connexions (conntrack), et avec des adresses source falsifiées, chaque adresse signifie une nouvelle entrée. Une fois la table pleine, le noyau jette les paquets sans faire de différence : l'attaque et vos joueurs sortent ensemble, et le journal système affiche « nf_conntrack: table full ». L'état et la limite s'affichent avec :

sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max

L'action la plus efficace consiste à ne pas faire suivre du tout le trafic de jeu, puisque le moteur gère lui-même ses sessions :

table inet raw {
    chain prerouting {
        type filter hook prerouting priority raw; policy accept;
        udp dport { 27015, 27020 } notrack
    }
    chain output {
        type filter hook output priority raw; policy accept;
        udp sport { 27015, 27020 } notrack
    }
}

Avec iptables, l'équivalent s'écrit iptables -t raw -A PREROUTING -p udp --dport 27015 -j NOTRACK, plus la même ligne pour OUTPUT avec --sport. Le port a ensuite besoin d'une ouverture explicite, car sans suivi, plus aucune règle testant un état existant ne s'applique. Si par ailleurs les paquets arrivent plus vite que srcds ne les récupère, le tampon de réception déborde, et pour les joueurs cela ressemble à de la perte de paquets sur une liaison libre :

net.core.rmem_max = 16777216
net.core.rmem_default = 1048576
net.core.netdev_max_backlog = 16384

Ces lignes ont leur place dans un fichier sous /etc/sysctl.d/ et deviennent actives avec sysctl --system. Le noyau vous dit lui-même si elles sont nécessaires : si UdpRcvbufErrors augmente dans nstat -az, elles servent à quelque chose. Si le compteur reste à zéro, le réglage ne change rien. C'est une réserve, pas une protection.

9. Sauvegarder les mesures tant que tout fonctionne normalement

L'étape la plus importante est celle que presque personne ne franchit à l'avance : constituer une base de comparaison. Sans valeur de référence, vous ne pourrez pas dire après un incident si 40 000 paquets par seconde représentaient beaucoup, ou simplement un samedi soir. Calculez une fois la valeur normale de votre serveur : 64 joueurs avec cl_cmdrate 66 produisent environ 4 200 paquets entrants par seconde, et tout ce qui dépasse nettement ce chiffre demande une explication. Avec apt-get install -y vnstat sysstat, la mesure tourne en permanence. Pendant un incident, quatre commandes suffisent :

sar -n DEV 1 10
ip -s link show eth0
nstat -az | grep -i udp
tcpdump -ni eth0 -c 200 "udp port 27015 and udp[8:4] = 0xffffffff"

La première commande affiche les paquets et les octets par seconde, la deuxième les compteurs de rejet de l'interface, la troisième les compteurs d'erreurs UDP du noyau. La quatrième ligne ne montre que les paquets sans connexion, c'est-à-dire exactement la catégorie dont abuse une inondation de requêtes : si le compteur se remplit en quelques secondes alors que presque personne n'est connecté, vous avez votre réponse. Limitez toujours tcpdump avec -c, car une capture à pleine charge alourdit encore un serveur déjà surchargé. La façon d'interpréter ces valeurs est expliquée dans Détecter une attaque DDoS sur son serveur.

Qu'est-ce que la faille de réflexion A2S et me concerne-t-elle encore

La réflexion A2S est une attaque dans laquelle votre serveur n'est pas la cible, mais l'outil. L'attaquant envoie une petite requête avec une adresse source falsifiée à des milliers de serveurs de jeu, et leurs réponses, nettement plus grandes, convergent toutes vers la véritable victime. Historiquement, une requête A2S_INFO pesait 25 octets (4 octets 0xFFFFFFFF, 1 octet 0x54, plus 20 octets pour la chaîne « Source Engine Query »), alors que la réponse faisait plusieurs centaines d'octets. Le US-CERT inscrit le protocole Steam dans sa liste des attaques par amplification avec un facteur de 5,5, ce qui signifie qu'un gigabit chez l'attaquant devient 5,5 gigabits chez la victime.

Valve a comblé cette faille à partir de novembre 2020, et ce par deux moyens. Depuis, les paquets de requête sans connexion doivent être complétés par l'expéditeur jusqu'à 1 200 octets, si bien que la question est plus grande que la réponse et que le facteur d'amplification tombe sous 1. Pendant la transition, les exploitants pouvaient imposer ce comportement plus strict à l'avance avec la variable d'environnement STEAM_GAMESERVER_MIN_CONNECTIONLESS_PACKET_SIZE=1200. De plus, pour A2S_PLAYER et A2S_RULES, le serveur ne répond plus immédiatement par des données, mais par un challenge (S2C_CHALLENGE) que le demandeur doit renvoyer dans une seconde requête. Celui qui falsifie l'adresse source ne voit jamais ce challenge.

Deux conséquences pour vous. Gardez le binaire du serveur à jour, car la protection réside dans la couche Steam des serveurs de jeu et non dans votre configuration. Et ne confondez pas la réflexion avec une inondation de requêtes dirigée contre vous : contre cette seconde forme, seules la limitation de débit de l'étape 3 et, au-delà, le filtrage dans le réseau en amont du serveur sont efficaces.

Où ces mesures s'arrêtent : bande passante et débit de paquets

Vient maintenant la partie qu'aucun fichier de configuration ne peut résoudre. Tout ce qui précède s'exécute sur votre serveur, donc au bout de la liaison. Une règle de pare-feu décide du sort d'un paquet qui a déjà parcouru le câble. Vous pouvez le rejeter, mais vous ne pouvez pas faire qu'il n'ait jamais été envoyé.

Faites le calcul une fois. Un serveur de jeu classique est raccordé à 1 Gbit/s, soit 125 mégaoctets par seconde, et la liaison est saturée dès que quelqu'un envoie davantage. La seconde grandeur frappe le plus souvent plus tôt : avec des paquets de 64 octets, la plus petite taille possible, environ 1,49 million de paquets par seconde tiennent dans 1 Gbit/s, et environ 14,88 millions dans 10 Gbit/s. Selon le CPU et la carte réseau, un noyau de serveur normal en traite quelques centaines de milliers avant de commencer à rejeter. Une attaque qui ne remplit même pas un tiers de votre liaison peut donc paralyser votre serveur, parce que le temps de calcul part dans le rejet des paquets. Les exploitants vivent cela comme ceci : « la charge n'était même pas élevée, et pourtant tout le monde avait des pics de lag ».

Indicateur Valeur
Requête A2S_INFO, taille historique 25 octets
Facteur d'amplification du protocole Steam (US-CERT) 5,5
Taille minimale des paquets de requête sans connexion depuis 2020 1 200 octets
Trafic normal : 64 joueurs avec cmdrate 66 environ 4 200 paquets entrants par seconde
1 Gbit/s avec des paquets de 64 octets environ 1,49 million de paquets par seconde (125 mégaoctets par seconde)
10 Gbit/s avec des paquets de 64 octets environ 14,88 millions de paquets par seconde
Taille d'attaque typique contre un serveur de jeu communautaire 5 à 50 Gbit/s
Pic mesuré sur des serveurs KernelHost 473,4 Gbit/s à 41,5 millions de paquets par seconde

Pour situer les ordres de grandeur qui se produisent réellement : sur des serveurs KernelHost, nous avons notamment filtré un flood UDP de plus de 112,2 Gbit/s et de plus de 8,7 millions de paquets par seconde contre un serveur de jeu, ainsi qu'une attaque multivecteur de plus de 473,4 Gbit/s et de plus de 41,5 millions de paquets par seconde contre un serveur vocal. 473,4 Gbit/s représentent environ 470 fois un raccordement à 1 Gbit/s, et encore environ 47 fois un raccordement à 10 Gbit/s. Il n'existe aucun réglage local pour cela. Les attaques volumétriques doivent s'arrêter dans le réseau, en amont du serveur.

Ce que KernelHost oppose à cela

La protection permanente comprise dans chaque pack serveur

La protection DDoS de KernelHost repose sur deux niveaux et reste active en permanence, sans que vous ayez quoi que ce soit à activer, à commander ou à configurer :

  • Niveau 1 : 17 Tbps de capacité de mitigation dans le réseau de scrubbing mondial. Les attaques volumétriques sont nettoyées au plus près de leur source, avant même d'atteindre le centre de données.
  • Niveau 2 : filtrage Arbor en temps réel à 3,2 Tbps à Francfort-sur-le-Main. Juste devant le serveur, les schémas propres à chaque protocole sont identifiés et rejetés, paquet par paquet.

Deux caractéristiques sont décisives. La protection fonctionne en permanence et n'a pas besoin de réagir d'abord à une attaque : il n'y a donc pas de temps de bascule pendant lequel vos joueurs seraient éjectés. Et aucun null-routing n'est employé : votre adresse IP reste dans le réseau, seuls les paquets malveillants sont rejetés. Retirer l'adresse IP du réseau aboutit, de votre point de vue, exactement au même résultat que l'attaquant. Le site est Francfort-sur-le-Main. Les jeux et protocoles couverts sont listés dans Protection DDoS des serveurs de jeu en temps réel.

Advanced DDoS Protection pour les communautés visées en continu

Certains projets ne sont pas attaqués de temps à autre, mais de façon ciblée et pendant des semaines, avec des schémas changeants et toujours pile à l'heure de pointe. Pour ces cas, il existe l'Advanced DDoS Protection à partir de 50,00 € par mois, en PrePaid et sans durée minimale. La différence ne tient pas à une capacité supérieure, mais au contrôle :

  • Une IP protégée dédiée issue du cœur de réseau de Francfort, vers laquelle votre serveur est basculé au sein de notre propre réseau. 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 définissez ce qui est autorisé sur 27015/UDP et ce qui l'est sur 27015/TCP, sans avoir à ouvrir de ticket.
  • Les changements s'appliquent en temps réel, vous pouvez donc affiner les réglages pendant une attaque en cours au lieu d'attendre la prochaine fenêtre de maintenance.
  • Un profil de protection adapté au jeu concerné, pour Garry's Mod et les autres titres Source comme pour les profils TCP et UDP libres destinés aux serveurs modifiés et aux applications maison.

Ici aussi, le modèle PrePaid s'applique : pas de durée minimale, pas de préavis de résiliation, pas de contrat et pas de frais de mise en service. Une fois la vague d'attaques passée, il vous suffit de ne pas renouveler. Si vous hébergez votre serveur Garry's Mod ailleurs jusqu'à présent, cette protection passe par un transfert chez KernelHost, car le filtrage s'effectue dans notre propre réseau et non sur une infrastructure tierce.

Les deux niveaux de protection comparés

Caractéristique Protection DDoS permanente incluse Advanced DDoS Protection
Prix comprise dans chaque pack serveur, sans supplément à partir de 50,00 € par mois, PrePaid
Activation active dès la mise en service, rien à configurer commander, recevoir l'IP protégée, le serveur est basculé
Capacité de filtrage 17 Tbps de scrubbing mondial, plus le filtrage Arbor en temps réel à 3,2 Tbps à Francfort-sur-le-Main le même filtrage à deux niveaux
Adresse IP l'adresse IP de votre serveur IP protégée dédiée supplémentaire
Jeu de règles profils automatiques, aucune configuration nécessaire vos propres règles par port et par protocole dans l'espace client
Modifications suivent automatiquement s'appliquent en temps réel, y compris pendant une attaque
Profil de jeu profils optimisés pour les jeux courants, Garry's Mod compris profil sélectionnable par port, y compris pour les serveurs modifiés
Null-routing pendant l'attaque non non
Durée d'engagement liée au pack serveur PrePaid, sans durée minimale, sans préavis de résiliation, sans frais de mise en service

Pour la plupart des communautés Garry's Mod, la protection permanente incluse suffit, à condition que la configuration du serveur soit propre. L'Advanced DDoS Protection est la réponse au cas où quelqu'un en fait une affaire personnelle.

Erreurs fréquentes et solutions

« Le serveur tourne, mais il a disparu du navigateur de serveurs » : le plus souvent, 27015/UDP a été bloqué globalement ou limité en débit de façon trop stricte. Comme le trafic de jeu et la requête partagent le même port, une règle grossière touche les deux. Travaillez plutôt avec une comparaison portant sur les paquets sans connexion. Si le serveur reste invisible alors que le port est joignable, vérifiez sv_setsteamaccount : sans Game Server Login Token valide, un serveur Garry's Mod est fortement déclassé dans la liste, et chaque serveur a besoin de son propre token.

« Ma règle iptables est correcte et reste pourtant sans effet » : trois causes sont fréquentes. La règle se trouve derrière les chaînes UFW et n'est jamais atteinte, elle a disparu au dernier redémarrage (apt-get install -y iptables-persistent et netfilter-persistent save ou une entrée dans /etc/ufw/before.rules y remédient), ou bien l'attaque est volumétrique et la règle travaille correctement sur une liaison déjà saturée. Vérifiez avec iptables -L INPUT -n -v si les compteurs de correspondances augmentent. S'ils restent à zéro, c'est que la règle n'est jamais atteinte.

« Mon serveur DarkRP saccade pour tout le monde, mais la liaison est libre » : c'est presque toujours Lua et non une attaque sur la liaison. Regardez dans le journal du serveur quel événement réseau arrive anormalement souvent, et vérifiez si l'addon correspondant impose une limite par joueur. Si sar -n DEV 1 10 et les compteurs de rejet ne montrent rien d'anormal, ce n'était pas une attaque DDoS.

« RCON ne fonctionne plus du jour au lendemain » : ce n'est pas un DDoS, mais le plus souvent votre propre bannissement. Un panneau d'administration avec un ancien mot de passe déclenche sv_rcon_minfailures, et sv_rcon_banpenalty bannit l'adresse pour le nombre de minutes configuré. Corrigez le mot de passe, levez le bannissement, puis restreignez le port à votre propre adresse.

« J'ai changé d'adresse IP et deux jours plus tard j'étais de nouveau hors ligne » : c'est le cas normal. Votre serveur publie lui-même la nouvelle adresse dès qu'il est de nouveau enregistré auprès du serveur maître, et un serveur de jeu sans adresse publique n'a pas de joueurs. Un changement d'adresse procure quelques heures à quelques jours, ce n'est pas une solution.

« Mon hébergeur précédent a bloqué mon adresse IP » : c'est du null-routing. L'hébergeur protège ainsi son propre réseau ; pour vous, le résultat est identique à une attaque réussie, et le plus souvent pendant encore des heures. En cas de doute, demandez si le trafic est filtré ou si l'adresse est simplement retirée du réseau. La réponse pèse davantage sur votre disponibilité que n'importe quelle fiche technique.

« Dans tcpdump, je ne vois rien d'anormal » : si le trafic est déjà filtré dans le réseau en amont, rien n'arrive sur le serveur, et c'est bien ce à quoi il faut s'attendre. C'est le cas normal quand le filtrage fonctionne. À l'inverse : si la liaison est saturée, il se peut que même la session SSH avec laquelle vous vouliez mesurer ne vous parvienne plus. Utilisez alors la console VNC de l'espace client.

En résumé

  • Un serveur Garry's Mod a besoin d'exactement un port ouvert : 27015/UDP. Le trafic de jeu et la requête A2S y passent ensemble, il n'existe pas de port de requête séparé.
  • RCON se trouve sur 27015/TCP, transmet le mot de passe en clair et doit être ouvert exclusivement à votre propre adresse ou atteint par une redirection de port SSH.
  • Ne limitez pas le port, mais les paquets sans connexion portant l'en-tête 0xffffffff. Un blocage global sur 27015/UDP éjecte vos propres joueurs.
  • La panne Garry's Mod la plus fréquente n'est pas une attaque DDoS, mais un événement réseau sans limite : chaque événement enregistré avec util.AddNetworkString a besoin d'un plafond par joueur et par seconde.
  • Avec des paquets de 64 octets, une liaison à 1 Gbit/s transporte environ 1,49 million de paquets par seconde. Au-delà, la perte se produit sur le routeur en amont et toute règle locale devient inopérante.
  • Chez KernelHost, la protection permanente à deux niveaux est comprise dans chaque pack serveur sans supplément : 17 Tbps de capacité de mitigation dans le réseau de scrubbing mondial et un filtrage Arbor en temps réel à 3,2 Tbps à Francfort-sur-le-Main, sans null-routing.
  • Qui est visé en continu et de façon ciblée complète avec l'Advanced DDoS Protection à partir de 50,00 € par mois : IP protégée dédiée, règles gérées par vous-même port par port et protocole par protocole, effet en temps réel.

Si votre serveur tourne déjà chez KernelHost, le filtrage est actif sans que vous ayez quoi que ce soit à faire. Si vous constatez malgré tout des anomalies, ouvrez un ticket de support afin que les règles de filtrage soient ajustées pour votre adresse IP. Indiquez d'emblée quatre informations : adresse IP, port, période dans votre fuseau horaire et ce que vous observez (des joueurs sont éjectés, le serveur n'apparaît pas dans le navigateur, pics de lag). Pendant une attaque en cours, vous pouvez également nous joindre par le chat d'urgence WhatsApp au +43 650 8209883.

Si vous exploitez d'autres titres Source à côté de Garry's Mod, les bases communes se trouvent dans Protéger un serveur CS2 ou Source des attaques DDoS, et la façon de mettre en place proprement la couche de base est décrite dans Installer un serveur de jeu avec SteamCMD.

Questions fréquentes

Mon serveur Garry's Mod est hors ligne en ce moment. Est-ce une attaque DDoS ?
Vérifiez d'abord le débit de paquets, pas la charge CPU. La commande sar -n DEV 1 10 affiche les paquets et les octets par seconde, ip -s link show eth0 les compteurs de rejet de l'interface, nstat -az les compteurs d'erreurs UDP du noyau. Si les paquets entrants montent bien au-dessus de votre valeur normale alors que presque personne n'est connecté, c'est une attaque. Si les compteurs réseau restent discrets et que tout saccade malgré tout, la cause se trouve presque toujours dans Lua : un addon ou un événement réseau non protégé dévore alors le temps de calcul, et aucun filtrage au monde n'y change quoi que ce soit.
De quels ports un serveur Garry's Mod a-t-il réellement besoin ?
Exactement un : 27015/UDP, défini par le paramètre de démarrage -port. Le trafic de jeu et la requête A2S du navigateur de serveurs passent ensemble par ce port unique, il n'existe pas de port de requête séparé chez Garry's Mod. RCON se trouve sur 27015/TCP et doit être ouvert exclusivement à votre propre adresse. Vous n'avez besoin de 27020/UDP que si vous diffusez avec SourceTV. Le port client 27005/UDP part du joueur et ne demande aucune règle sur le serveur. MySQL pour DarkRP doit être lié à 127.0.0.1 et jamais exposé sur le réseau ouvert.
Puis-je bloquer le port de requête pour que l'inondation de requêtes cesse ?
Non, car il n'existe pas de port de requête séparé. Celui qui bloque 27015/UDP ou lui applique une limitation de débit globale éjecte du même geste ses propres joueurs et disparaît du navigateur de serveurs. La bonne approche est une limitation qui ne touche que les paquets sans connexion : toutes les requêtes d'état et tous les établissements de connexion du moteur Source commencent par les quatre octets 0xffffffff, alors que le trafic des joueurs déjà connectés n'a pas cet en-tête. C'est exactement sur ce motif que vous posez une limite par adresse source avec nftables ou iptables, avec environ huit paquets par seconde comme valeur de départ.
Pourquoi RCON est-il une cible si prisée chez Garry's Mod ?
Parce que le gain est maximal et l'obstacle minime. RCON occupe le même numéro de port que le jeu, seulement en TCP, et se trouve donc sans la moindre recherche. Le protocole RCON de Source transmet le mot de passe en clair, sans TLS et sans échange de clés. Et celui qui prend RCON peut changer de carte, bannir tous les joueurs, modifier la configuration et arrêter le serveur, sans aucune bande passante. Définissez donc un long mot de passe aléatoire, activez sv_rcon_minfailures et sv_rcon_banpenalty, et n'ouvrez 27015/TCP que pour votre propre adresse.
Qu'est-ce que la faille de réflexion A2S et me concerne-t-elle encore ?
La réflexion A2S est une attaque dans laquelle votre serveur n'est pas la cible, mais l'outil : l'attaquant interroge des milliers de serveurs de jeu avec une adresse source falsifiée, et les réponses, nettement plus grandes, convergent chez la véritable victime. Une requête A2S_INFO pesait historiquement 25 octets, et le US-CERT inscrit le protocole Steam avec un facteur d'amplification de 5,5. Valve a comblé la faille à partir de novembre 2020 : les paquets de requête doivent être complétés jusqu'à 1 200 octets, et A2S_PLAYER ainsi que A2S_RULES exigent un challenge. Gardez le binaire du serveur à jour, cette protection s'applique alors.
Pourquoi ma règle de pare-feu ne sert-elle à rien pendant l'attaque ?
Parce qu'elle ne s'applique qu'une fois le paquet arrivé. Avec des paquets de 64 octets, une liaison à 1 Gbit/s transporte environ 1,49 million de paquets par seconde, une liaison à 10 Gbit/s environ 14,88 millions. Si l'attaque dépasse ce seuil, la perte se produit sur le routeur en amont et votre règle n'est jamais exécutée. Bien avant que la liaison ne soit saturée, c'est en outre le CPU qui arrive au bout, car chaque paquet coûte un passage complet dans la pile réseau, même s'il est rejeté ensuite. À partir de ce point, seul un filtrage dans le réseau en amont du serveur aide.
Mon serveur DarkRP a des pics de lag, mais la liaison est libre. D'où cela vient-il ?
C'est alors presque toujours Lua et non une attaque sur la liaison. Dès qu'un addon enregistre un événement réseau avec util.AddNetworkString et l'écoute avec net.Receive, n'importe quel client connecté peut déclencher cet événement en boucle, et le serveur exécute chaque message, un par un. Un joueur avec quelques kilobits par seconde y suffit. La solution se trouve dans l'addon et non dans le pare-feu : un plafond par joueur et par seconde, un contrôle de la longueur du message, et la détermination du joueur côté serveur plutôt qu'à partir du contenu du message.
Mon serveur chez KernelHost passe-t-il hors ligne pendant une attaque ?
Non. Aucun null-routing n'est employé. Votre adresse IP reste dans le réseau, seuls les paquets malveillants sont rejetés. La protection repose sur deux niveaux : 17 Tbps de capacité de mitigation dans le réseau de scrubbing mondial et un filtrage Arbor en temps réel à 3,2 Tbps à Francfort-sur-le-Main. Elle fonctionne en permanence et n'a pas besoin de réagir d'abord à une attaque, il n'y a donc pas de temps de bascule pendant lequel vos joueurs seraient éjectés. Cette protection permanente est comprise dans chaque pack serveur sans supplément et active dès la mise à disposition.
Quand ai-je besoin en plus de l'Advanced DDoS Protection ?
Lorsque votre communauté n'est pas visée de temps à autre, mais de façon ciblée et pendant des semaines, et que vous voulez piloter le filtrage vous-même. Vous recevez une IP protégée dédiée et vous gérez vous-même les règles de protection par port et par protocole dans l'espace client, donc 27015/UDP autrement que 27015/TCP. Les changements s'appliquent en temps réel, vous pouvez donc affiner les réglages pendant une attaque en cours. Le prix débute à 50,00 € par mois, en PrePaid, sans durée minimale, sans préavis de résiliation et sans frais de mise en service.

Garry's Mod Garrys Mod DDoS-Schutz DarkRP Source-Engine A2S-Query Gameserver-Schutz Port 27015 Advanced DDoS Protection