CS2- en Source-servers beschermen tegen DDoS-aanvallen
Bij Counter-Strike 2 en de Source-titels lopen spelverkeer en serveropvraging over dezelfde poort 27015. Wat u zelf kunt beveiligen en vanaf welk aanvalsvolume alleen filtering in het netwerk ervoor nog helpt.
Een Counter-Strike-server gaat zelden op een willekeurig moment onderuit. De uitval komt in de beslissende ronde, vlak voor de finale van een toernooi of precies op het moment dat een geblokkeerde speler voor de tweede keer is geweigerd. Wie op dat moment onder vuur ligt, heeft geen principiële discussie nodig, maar een volgorde. Dit artikel laat eerst zien wat u zelf op de server kunt aanpassen, daarna waar die mogelijkheden ophouden, en tot slot wat er ervoor in het netwerk moet gebeuren.
Waarom CS2- en Source-servers zo vaak worden aangevallen
Counter-Strike is een spel tegen de klok. Een ronde duurt minder dan twee minuten, een match krap een uur, en uitval binnen dat uur bepaalt de uitslag. Uitval is daarmee niet alleen vervelend, maar ook een middel: wie achterstaat, wint tijd zodra de wedstrijd wordt afgebroken, en wie een concurrerende community draait, weet dat een avond vol timeouts de vaste spelers laat vertrekken.
Daar komt de bouw van de engine bij. Een Source-server is met IP-adres en poort openbaar vindbaar, en dat is een voorwaarde, geen ongelukje: zonder beantwoorde serveropvraging staat hij in geen enkele browser. De vraag is dus nooit of een aanvaller uw adres vindt, maar alleen wat er gebeurt zodra hij erop schiet.
Om welke poorten het gaat
Counter-Strike 2, CS:GO en Garry's Mod delen dezelfde poortindeling, en daarin zit een punt dat ze onderscheidt van Minecraft of Rust:
- 27015/UDP, tegelijk spelpoort en serveropvraging (
-port). Over deze ene poort loopt het spelverkeer en daarnaast de A2S-opvraging waarmee Steam en elke lijstsite de server uitlezen. Een aparte query-poort bestaat hier niet. - 27015/TCP, RCON. Zelfde nummer, ander protocol. Daarover lopen de beheerderscommando's, voor zover
rcon_passwordis ingesteld. - 27020/UDP, GOTV oftewel SourceTV (
tv_port). Alleen nodig als u daadwerkelijk uitzendt. - 27005/UDP, de clientpoort. Die gaat van de speler uit en hoeft op de server niet te worden vrijgegeven.
- Bij meerdere instanties lopen de nummers op (27016, 27017 en 27021, 27022 voor GOTV). Staat de snelle download voor maps (
sv_downloadurl) op dezelfde host, dan komt 80/TCP of 443/TCP erbij.
De gedeelde poort is de kern van het probleem. Een A2S-verzoek is een pakket van een paar tientallen bytes, het antwoord een veelvoud daarvan, en bij UDP valt het afzenderadres te vervalsen. Een aanvaller kan vreemde servers bevragen en de antwoorden naar zijn eigenlijke doelwit sturen: uw server is dan niet alleen slachtoffer, maar ook versterker. Valve heeft A2S_INFO daarom uitgebreid met een voorgeschakelde challenge, wat de zaak verzacht maar niet oplost. Waaraan u een lopende aanval herkent, beschrijft het artikel DDoS-aanval op de server herkennen.
Wat u zelf kunt doen voordat u geld uitgeeft
Het volgende deel kost niets en loont ongeacht waar uw server staat. Het houdt geen volumetrische aanval tegen, maar zorgt er wel voor dat kleine en middelgrote aanvallen zonder effect blijven.
1. Inventarisatie: wat luistert er werkelijk
Voordat u een regel schrijft, brengt u in kaart welke diensten bereikbaar zijn. Op een gameserver die in de loop van de tijd is gegroeid, zijn dat er bijna altijd meer dan verwacht:
ss -lntup
Alles wat aan 127.0.0.1 of ::1 gebonden is, hoeft niet te worden vrijgegeven. Alles wat op 0.0.0.0 of [::] luistert, is vanaf het internet bereikbaar, ook de database die een add-on voor statistieken heeft meegebracht. Vergelijk dat met uw startregel:
./game/bin/linuxsteamrt64/cs2 -dedicated \
-port 27015 \
-maxplayers_override 12 \
+game_alias competitive \
+map de_dust2 \
+sv_setsteamaccount UW_GSLT_TOKEN
Bij CS:GO en Garry's Mod neemt srcds_run dezelfde taak over. Is de onderbouw via SteamCMD ingericht, dan helpt het artikel Gameserver met SteamCMD installeren.
2. Alleen de poorten openlaten die de server echt nodig heeft
Twee UDP-poorten en één beperkte TCP-poort, meer niet. RCON hoort niet op het open internet:
ufw allow 27015/udp comment "CS2 spelpoort en A2S"
ufw allow 27020/udp comment "GOTV"
ufw allow from 203.0.113.10 to any port 27015 proto tcp comment "RCON"
Vervang 203.0.113.10 door uw eigen adres. Wisselt dat adres regelmatig, dan loopt de weg via een SSH-tunnel in plaats van via een permanente vrijgave.
Een waarschuwing die elk jaar servers kost: de volgorde waarin u een firewall scherp zet, bepaalt of u uzelf buitensluit. Die volgorde staat, inclusief de weg terug, in het artikel UFW-firewall instellen. Gebeurt het toch: KVM-rootservers en dedicated servers van KernelHost hebben geen IPMI en geen iDRAC, u bereikt de server via de VNC-console in het klantenpaneel. Die console hangt niet aan de netwerkstack van het gastsysteem.
3. Het opvraagverkeer begrenzen zonder uit de serverlijst te vallen
Hier zit de duurste fout binnen dit onderwerp. Omdat spelverkeer en serveropvraging dezelfde poort bezetten, is de voor de hand liggende reactie verkeerd: wie 27015/UDP dichtzet of er zonder onderscheid een ratelimiet overheen legt, gooit in dezelfde beweging zijn eigen spelers eruit en maakt de aanval zelf af.
Het juiste aangrijpingspunt is het onderscheid tussen opvraag- en spelpakketten. De engine ziet de inhoud en heeft daarvoor drie consolevariabelen:
sv_max_queries_sec 3
sv_max_queries_sec_global 60
sv_max_queries_window 30
De eerste begrenst het aantal beantwoorde opvragingen per afzenderadres, de tweede maximeert de som over alle adressen, de derde legt vast over hoeveel seconden daarbij wordt gemiddeld; met find sv_max_queries ziet u of uw build ze kent. Ze beschermen de CPU tegen het zinloos opstellen van antwoorden, maar voorkomen niet dat de pakketten binnenkomen.
Een laag dieper is het opvraagverkeer netjes af te splitsen. Alle verbindingsloze pakketten van de Source-engine, dus serveropvragingen en verbindingsopbouw, beginnen met vier gezette bytes (0xffffffff), en het verkeer van al verbonden spelers heeft die kop niet. Precies daarop legt u met nftables een ratelimiet:
table inet cs2 {
chain input {
type filter hook input priority -10; policy accept;
udp dport 27015 @th,64,32 0xffffffff \
meter a2sflood { ip saddr limit rate over 10/second burst 20 packets } drop
}
}
Het bestand laadt u met nft -f. De prioriteit -10 zorgt ervoor dat de regel eerder werkt dan de filterketen van UFW, en @th,64,32 leest de eerste vier bytes achter de UDP-kop. Met klassiek iptables levert een vergelijking met de kenmerkende bytereeks van A2S_INFO dezelfde scheiding op:
iptables -A INPUT -p udp --dport 27015 \
-m string --algo bm --hex-string "|ffffffff54536f7572636520456e67696e6520517565727900|" \
-m hashlimit --hashlimit-name a2sflood --hashlimit-mode srcip \
--hashlimit-above 10/sec --hashlimit-burst 20 -j DROP
Begin ruim en zet de grens pas strakker zodra aantoonbaar is dat legitieme opvragingen doorkomen.
4. RCON beveiligen
Een open RCON-poort met een zwak wachtwoord is geen DDoS-probleem, maar een overname: wie RCON heeft, kan de map wisselen, alle spelers blokkeren en de server stoppen. Laat rcon_password nooit leeg en kies nooit iets wat te raden valt, een waarde uit openssl rand -base64 32 volstaat. De Source-titels hebben daarnaast een rem tegen inlogpogingen:
sv_rcon_minfailures 3
sv_rcon_maxfailures 5
sv_rcon_minfailuretime 30
sv_rcon_banpenalty 1440
sv_rcon_whitelist_address "203.0.113.10"
Daarmee raakt een adres na drie mislukte pogingen binnen 30 seconden een dag lang geblokkeerd, terwijl uw eigen adres uitgezonderd blijft; met find sv_rcon ziet u welke variabelen uw build kent. De firewallbeperking uit stap 2 blijft toch effectiever, want die laat de poging niet tot aan de applicatie door.
5. De connection tracking ontlasten
Dit punt wordt vaak over het hoofd gezien en verklaart uitval die op een volume-aanval lijkt, maar het niet is. De kernel maakt voor UDP-verkeer vermeldingen aan in de connection tracking (conntrack), en bij vervalste afzenderadressen levert elk adres een nieuwe vermelding op. Zit de tabel vol, dan verwerpt de kernel pakketten zonder onderscheid: de aanval en uw spelers vliegen er samen uit. De meest effectieve stap is om het spelverkeer helemaal niet te laten volgen, want de engine beheert zijn sessies zelf:
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
}
}
Met iptables luidt het equivalent iptables -t raw -A PREROUTING -p udp --dport 27015 -j NOTRACK en dezelfde regel voor OUTPUT met --sport. De poort heeft daarna een uitdrukkelijke vrijgave nodig, want zonder tracking werkt geen enkele regel meer die op een bestaande status controleert.
6. Ontvangstbuffers en kernelparameters
Komen pakketten sneller binnen dan het serverproces ze ophaalt, dan loopt de ontvangstbuffer over. Voor de spelers ziet dat eruit als pakketverlies, terwijl de lijn vrij is. Een aanvulling onder /etc/sysctl.d/, geactiveerd met sysctl -p, geeft lucht:
net.core.rmem_max = 16777216
net.core.rmem_default = 1048576
net.core.netdev_max_backlog = 16384
Of de waarden nodig zijn, verklapt de kernel zelf: stijgt UdpRcvbufErrors in nstat -az, dan hebben ze zin. Blijft de teller op nul, dan verandert de aanpassing niets. Dit is reserve, geen bescherming.
7. Maatregelen bij anticheat en plugins
Een aanzienlijk deel van de storingen die als DDoS worden gemeld, is dat helemaal niet. Het zijn crashes die één enkele client met een paar honderd pakketten uitlokt, omdat er in de serverbinary of in een uitbreiding een gat openstaat. Daartegen helpt geen bandbreedte, maar onderhoud:
- Houd de serverbinary actueel. Updates dichten naast spelinhoud ook netwerkfouten. Een server die twee versies achterloopt, staat open voor bekende crashpatronen.
- Houd uitbreidingen passend bij de engineversie. Voor CS:GO en Garry's Mod zijn Metamod:Source en SourceMod de gebruikelijke onderbouw; voor Counter-Strike 2 bestaat SourceMod tot nu toe niet in dezelfde volwassenheid, daar zijn Metamod:Source in de ontwikkelversies en CounterStrikeSharp gangbaar. Een uitbreiding die niet past, is de meest voorkomende oorzaak van crashes na een update.
- Minder uitbreidingen. Elke plugin is code in hetzelfde proces, en uitbreidingen met eigen webdiensten openen extra poorten en publiceren vaak precies het adres dat u wilde beschermen.
- Begrens bij Garry's Mod de netwerkberichten. Het bekendste eigen doelpunt is een menu dat zonder begrenzing naar
net.Receiveluistert: één client stuurt het bericht in een lus en legt de server in zijn eentje plat.
local last = {}
net.Receive("mijn_menu", function(len, ply)
if last[ply] and CurTime() - last[ply] < 0.5 then return end
last[ply] = CurTime()
end)
hook.Add("PlayerDisconnected", "mijn_menu_cleanup", function(ply)
last[ply] = nil
end)
Eveneens bij Garry's Mod: sv_allowcslua 0 voorkomt dat clients eigen Lua-code uitvoeren. Blokkades horen permanent te worden weggeschreven, anders zijn ze na de herstart verdwenen: de Source-titels kennen daarvoor banid en writeid plus addip en writeip; wat uw build meebrengt, toont find ban.
8. Serverlijst, whitelist en het eigen adres
Een openbare Counter-Strike-server heeft een Game Server Login Token nodig, ingesteld via sv_setsteamaccount. Zonder dat token blijft hij ongeregistreerd en duikt hij in geen enkele openbare lijst op. Voor een vaste groep is precies dat effectief: sv_password instellen, afzien van de registratie en het adres alleen aan de eigen spelers geven. Voor een openbare server is dat geen optie: een server die niemand vindt, is net zo leeg als een server die offline staat. Een echte whitelist zit niet in de engine, die komt via uitbreidingen.
Aan het adres van de spelserver valt niets te veranderen, aan alles eromheen des te meer: vaak vindt een aanvaller meteen de hele omgeving, van de webserver via de host van de Discord-bot tot de toegang tot het paneel. Die adressen horen niet in dezelfde aankondiging als het serveradres en ook niet in oude DNS-records.
9. Vastleggen, zodat u tijdens de aanval niet hoeft te gokken
Tijdens een aanval telt vooral één vraag: hoeveel komt er binnen en op welke poort. Drie commando's volstaan:
ip -s link show eth0
nstat -az | grep -i udp
tcpdump -ni eth0 -c 200 "udp port 27015 and udp[8:4] = 0xffffffff"
Het eerste commando toont pakketten, fouten en verworpen verkeer per interface; voer het twee keer uit met tien seconden ertussen, dan hebt u een snelheid in plaats van een absolute waarde. De derde regel toont uitsluitend de verbindingsloze pakketten, dus precies de soort die een opvraagvloed misbruikt. Houd die opname kort, want ze kost onder belasting zelf rekentijd. Loopt de teller in enkele seconden vol terwijl er nauwelijks iemand verbonden is, dan hebt u uw antwoord.
Waar de eigen bescherming ophoudt
Nu het eerlijke deel. Alles wat tot hier is beschreven, werkt pas als de pakketten op uw netwerkkaart zijn aangekomen. Bij de kleinst mogelijke pakketgrootte draagt een 1-Gbit/s-lijn ongeveer 1,49 miljoen pakketten per seconde, een 10-Gbit/s-lijn ongeveer 14,88 miljoen. Dat is de fysieke bovengrens, onafhankelijk van CPU, kernel en firewall.
Daartegenover staan echte aanvallen. Twee voorbeelden uit de praktijk bij KernelHost, beide in realtime gefilterd: een UDP-flood tegen een gameserver op 7777/UDP met meer dan 112,2 Gbit/s en meer dan 8,7 miljoen pakketten per seconde, en een multivectoraanval tegen een voiceserver op 9987/UDP met meer dan 473,4 Gbit/s en meer dan 41,5 miljoen pakketten per seconde.
Zet dat af tegen uw eigen lijn: 473,4 Gbit/s is ongeveer 470 keer zoveel als een aansluiting van 1 Gbit/s en nog altijd ongeveer 47 keer zoveel als een aansluiting van 10 Gbit/s. Uw regel kan nog zo correct zijn, hij wordt nooit uitgevoerd, want het verlies ontstaat al eerder, op de router ervoor. En ruim voordat de lijn vol zit, is de CPU op, want elk pakket kost een gang door de netwerkstack, ook als het daarna wordt weggegooid.
Daarom voldoen de twee gangbare noodremmen geen van beide. Null-routing (blackholing) haalt het aangevallen IP-adres uit het netwerk en beëindigt weliswaar de aanval, maar ook uw server. Een reactieve omleiding kost in de omschakeltijd precies de minuten waarin de match wordt beslist. Effectief is alleen een filtering die permanent in het netwerk vóór de server draait.
Wat KernelHost daartegenover zet
De permanente bescherming die op elke server draait
De DDoS-bescherming van KernelHost is in twee lagen opgebouwd en permanent actief, zonder dat u iets hoeft in te schakelen. De eerste laag is een wereldwijd scrubbingnetwerk met 17 Tbps mitigatiecapaciteit, dat volumetrische aanvallen dicht bij hun bron opvangt, ruim voordat ze het datacenter bereiken. De tweede laag is een Arbor realtime filtering met 3,2 Tbps direct ter plaatse in Frankfurt am Main, die het fijne werk doet en complexe patronen op laag 3 tot en met 7 verwerpt.
Twee punten zijn doorslaggevend. Ten eerste draait de filtering permanent, er is dus geen omschakeltijd waarin uw spelers eruit vliegen. Ten tweede wordt er geen null-routing toegepast: het aangevallen IP-adres blijft in het netwerk, alleen de schadelijke pakketten vallen weg. De bescherming zit zonder meerprijs in elk serverpakket, zonder apart beschermingspakket en zonder installatie. De servers staan in het maincubes Premium Datacenter in Frankfurt am Main (Duitsland), aanbieder is KernelHost GmbH, gevestigd in Wenen (Oostenrijk). Welke games en protocollen gedekt zijn, somt het artikel Gameserver-DDoS-bescherming in realtime op.
Advanced DDoS Protection voor projecten die permanent onder vuur liggen
Sommige projecten worden wekenlang gericht aangevallen, met wisselende patronen en steeds precies op het tijdstip van de match. Voor die gevallen is er de Advanced DDoS Protection vanaf € 50,00 per maand, PrePaid en zonder minimale looptijd. Die biedt drie dingen die de inbegrepen permanente bescherming niet heeft:
- Een dedicated beschermd IP-adres. Uw server wordt binnen ons netwerk op dat adres omgezet, een verbouwing aan uw kant is niet nodig.
- Zelf te beheren beschermingsregels per poort en protocol. In het klantenpaneel bepaalt u welke poort met welk profiel wordt gefilterd, bijvoorbeeld 27015/UDP anders dan 27020/UDP. Wijzigingen werken in realtime, zonder ticket en zonder wachttijd.
- Een beschermingsprofiel dat bij het betreffende spel past. Voor Counter-Strike 2 en de Source-titels net zo goed als voor meer dan 40 andere games en protocollen, plus vrij in te vullen TCP- en UDP-profielen voor aangepaste servers.
Ook hier geldt het PrePaid-model: geen minimale looptijd, geen opzegtermijn, geen contract en geen installatiekosten. Is de aanvalsgolf voorbij, dan verlengt u gewoon niet.
De twee niveaus naast elkaar
| Kenmerk | Inbegrepen permanente bescherming | Advanced DDoS Protection |
|---|---|---|
| Prijs | In elk serverpakket inbegrepen, zonder meerprijs | vanaf € 50,00 per maand, PrePaid zonder minimale looptijd |
| Activering | Vanaf de eerste minuut actief, niets in te stellen | Bestellen, beschermd IP-adres ontvangen, server wordt omgezet |
| IP-adres | Server-IP uit het netwerk in Frankfurt | Extra dedicated beschermd IP-adres |
| Filtering | 17 Tbps wereldwijde scrubbing, plus 3,2 Tbps Arbor realtime filtering in Frankfurt am Main | Dezelfde filtering, plus eigen regels per poort en protocol |
| Regels wijzigen | Door KernelHost beheerd, fijnafstemming via ticket | Zelf in het klantenpaneel, in realtime actief |
| Gameprofielen | Meer dan 40 games en protocollen | Profiel per poort te kiezen, ook voor aangepaste servers |
| Null-routing tijdens een aanval | Nee | Nee |
| Geschikt voor | Elke server, vanaf de eerste match | Projecten die permanent en gericht onder vuur liggen |
Veelvoorkomende fouten en oplossingen
De server is uit de browser verdwenen, maar draait gewoon door: meestal staat 27015/UDP volledig dicht of is de ratelimiet te krap, en omdat spelverkeer en opvraging dezelfde poort delen, raakt een grove regel allebei. Werk in plaats daarvan met een vergelijking op de verbindingsloze pakketten. Ontbreekt de server terwijl de poort bereikbaar is, controleer dan sv_setsteamaccount.
Alle spelers hebben een hoge ping, terwijl de lijn niet vol zit: dat wijst op de pakketsnelheid en niet op volume. Bekijk de verworpen pakketten in ip -s link show en de UDP-tellers in nstat -az. Staat er in het logboek van het systeem nf_conntrack: table full, haal de spelpoort er dan met notrack uit.
De firewallregel klopt en werkt toch niet: dan zit de lijn vóór de server vol. Een regel die nooit wordt uitgevoerd, omdat het pakket al op de router ervoor sneuvelde, kan niets uitrichten. Vanaf dat punt helpt alleen nog filtering in het netwerk.
Na het scherp zetten van de firewall geen SSH-toegang meer: log in via de VNC-console in het klantenpaneel (IPMI of iDRAC is er niet) en zet de firewall daar uit.
De aanval stopt na een IP-wissel en komt na een tot twee dagen terug: dat is het normale beeld, want uw server publiceert het nieuwe adres zelf zodra hij weer geregistreerd is. Een IP-wissel levert uren op, geen oplossing.
De server crasht reproduceerbaar, terwijl de bandbreedte niet opvalt: meestal geen DDoS, maar een crashpatroon in een uitbreiding of een verouderde serverversie.
Er lopen vreemde beheerderscommando's op de server: geen DDoS, maar een gecompromitteerde RCON-toegang. Wijzig direct het wachtwoord en beperk de poort.
Als u op dit moment wordt aangevallen
Draait uw server al bij KernelHost, dan is de filtering permanent actief. Merkt u toch iets afwijkends, open dan een supportticket, zodat ons team de filterregels voor uw IP-adres bijstelt. Bij een lopende aanval bereikt u ons daarnaast via de WhatsApp-noodchat op +43 650 8209883.
Vermeld daarbij meteen vier gegevens: IP-adres, poort, periode in uw eigen tijdzone en wat u ziet (spelers vliegen eruit, server niet in de browser, hoge ping). Dat scheelt een ronde extra vragen, en die telt zodra er een match loopt.
Veelgestelde vragen
Mijn CS2-server is plotseling weg. Is dat een DDoS-aanval?
Kan ik de query-poort gewoon blokkeren?
Welke poorten heeft een CS2- of Source-server echt nodig?
Helpt een wissel van IP-adres tegen de aanval?
Waarom levert mijn firewallregel niets op?
Ik heb mijzelf met de firewall buitengesloten. Hoe kom ik terug?
Haalt KernelHost mijn IP-adres tijdens een aanval offline?
Wanneer heb ik de Advanced DDoS Protection nodig?
2026 KernelHost GmbH. Alle rechten voorbehouden. Deze handleiding is auteursrechtelijk beschermd. Publicatie op andere websites, geheel, gedeeltelijk of in bewerkte vorm, is zonder onze schriftelijke toestemming niet toegestaan. Citeren met bronvermelding en link is uitdrukkelijk welkom.

