Proteggere i server SA-MP e open.mp dagli attacchi DDoS
SA-MP e open.mp gestiscono gioco, query e RCON su un'unica porta UDP. Questa guida mostra che cosa puoi mettere in sicurezza da solo e da quale dimensione di attacco in poi serve soltanto il filtraggio nella rete a monte.
Un progetto SA-MP o open.mp cresce quasi sempre secondo lo stesso schema: il numero di giocatori sale, il server risale la lista e pochi giorni dopo le connessioni cadono una dopo l'altra. La parte più lunga di questa guida descrive che cosa puoi cambiare da solo sul tuo server senza spendere nulla. Poi vediamo dove queste misure si fermano dal punto di vista tecnico, e solo alla fine che cosa mette in campo KernelHost.
Perché proprio SA-MP e open.mp vengono colpiti così spesso
La scena è ristretta e molto competitiva. Tanti server roleplay e freeroam si contendono gli stessi giocatori, e nessuno si fa troppi scrupoli a buttare un concorrente fuori dalla lista per qualche ora. A questo si aggiungono i giocatori bannati e i tentativi di estorsione contro i progetti che hanno un proprio shop.
Dal punto di vista tecnico, il gioco rende la vita facile a chi attacca. Tutto il traffico di gioco passa da UDP, e UDP non prevede alcuna apertura di connessione che costi qualcosa all'attaccante; in più gli indirizzi mittente si possono falsificare. La voce nella lista pubblica indirizzo e porta, quindi non serve nemmeno una ricognizione preliminare. E poiché la maggior parte dei progetti gira su un unico server, il server di gioco, il database, il pannello utenti e spesso anche il server voce condividono lo stesso indirizzo: un colpo solo li mette fuori uso tutti insieme.
Le porte e i protocolli di cui si parla
- Server SA-MP: UDP 7777 come impostazione predefinita, modificabile con
portnel fileserver.cfg. - Server open.mp: anche qui UDP 7777 come impostazione predefinita, modificabile con
network.portnel fileconfig.json. - Query: la stessa porta UDP. Non esiste una porta di interrogazione separata. Browser dei server, pagine di stato e bot Discord si rivolgono alla stessa porta su cui si gioca.
- RCON: sempre la stessa porta UDP, come opcode a sé all'interno del protocollo di query, in chiaro.
- L'inserimento nella lista avviene in uscita verso la rispettiva lista dei server, in entrata non serve aprire nulla.
- Tutto il resto sulla stessa macchina: SSH su TCP 22, MariaDB o MySQL su TCP 3306, il pannello utenti su TCP 80 e 443.
La conseguenza: non puoi separare l'accesso query dal gioco con il firewall, perché stanno tutti e due sulla stessa porta. Chi blocca UDP 7777 chiude fuori i propri giocatori.
Una richiesta di query comincia con undici byte: quattro byte di identificativo, quattro byte di indirizzo del server, due byte di porta e un byte di opcode. L'opcode decide la risposta: i restituisce le informazioni sul server, r le regole, c un elenco breve dei giocatori, d un elenco dettagliato con nome, punteggio e ping di ogni giocatore, p rimanda indietro quattro byte per la misura del ping, x è RCON. Su un server molto frequentato, undici byte di richiesta producono diversi kilobyte di risposta. Questo rende un accesso query aperto interessante due volte: come bersaglio e come amplificatore contro terzi. Che cosa ci sia dietro questo schema di attacco lo spiega l'articolo Che cos'è un attacco DDoS?.
Che cosa puoi fare da solo prima di spendere soldi
I passaggi che seguono non costano nulla e funzionano contro gli attacchi di tutti i giorni: ondate di join, ondate di query e singole sorgenti con una frequenza di pacchetti elevata. Tutti i comandi presuppongono root, altrimenti anteponi sudo.
1. Inventario: che cosa è davvero in ascolto?
ss -lnup
ss -lntp
Quello che ascolta su 127.0.0.1 o ::1 non ha bisogno di alcuna regola firewall. Quello che compare su 0.0.0.0 o [::] è raggiungibile dall'esterno e deve avere una ragione precisa.
2. Chiudere tutto ciò che il gioco non usa
Un filtro di pacchetti non elimina un attacco volumetrico, ma riduce la superficie di attacco. Una configurazione di partenza solida con UFW:
ufw allow 22/tcp comment 'SSH'
ufw allow 7777/udp comment 'SA-MP / open.mp'
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose
L'ordine non è casuale: le regole di autorizzazione vanno prima dell'attivazione, altrimenti ti chiudi fuori da solo. I dettagli, con la relativa via di ritorno, stanno nell'articolo Configurare il firewall UFW. Sui server root KVM e sui server dedicati di KernelHost, in caso di emergenza raggiungi il sistema tramite la console VNC nell'area clienti.
Il database non deve stare sulla rete aperta. Se ss -lntp | grep 3306 mostra un 0.0.0.0:3306, imposta bind-address = 127.0.0.1 e riavvia il servizio. Lega a un indirizzo fisso anche il server di gioco, in SA-MP con bind e in open.mp con network.bind.
3. Disinnescare l'accesso query senza chiudere fuori i giocatori
In server.cfg SA-MP ha l'interruttore query 0, con cui il server smette di rispondere a qualsiasi interrogazione. Funziona, ma il prezzo è alto: il server sparisce dal browser dei server, numero di giocatori e regole non sono più leggibili, le pagine di stato e i bot Discord lo mostrano offline. Per una cerchia chiusa è un'opzione, per un progetto che vuole crescere no. In open.mp la stessa impostazione sta nella sezione network di config.json; verifica il nome esatto della chiave nella tua versione invece di tirare a indovinare.
La strada realistica è quindi limitare invece di spegnere. Questa regola di filtro mostra in tempo reale solo i pacchetti che portano l'identificativo di query:
tcpdump -ni any -c 100 'udp port 7777 and udp[8:4] = 0x53414d50'
Quali indirizzi mittente mandano più traffico sulla porta di gioco:
tcpdump -nn -q -c 2000 'udp dst port 7777' 2>/dev/null \
| awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head -20
4. Impostare i rate limit nello stack di rete
Con nftables limiti la frequenza di pacchetti per ogni indirizzo mittente. Il set di regole che segue crea una tabella propria, così non intralcia UFW:
nft add table inet gameguard
nft add chain inet gameguard input '{ type filter hook input priority -150 ; policy accept ; }'
nft add rule inet gameguard input udp dport 7777 meter perip '{ ip saddr limit rate over 60/second burst 120 packets }' drop
nft list table inet gameguard
Conviene aggiungere anche un tetto per l'intera porta, così che un'ondata molto distribuita non passi attraverso la fessura lasciata da tante sorgenti singole:
nft add rule inet gameguard input udp dport 7777 limit rate over 20000/second burst 5000 packets drop
Con iptables lo stesso risultato si ottiene con il modulo hashlimit:
iptables -N SAMPGUARD
iptables -A INPUT -p udp --dport 7777 -j SAMPGUARD
iptables -A SAMPGUARD -m hashlimit --hashlimit-name samp --hashlimit-mode srcip \
--hashlimit-above 60/sec --hashlimit-burst 120 --hashlimit-htable-expire 30000 -j DROP
Queste cifre sono valori di partenza, non una raccomandazione per il tuo server. Un singolo giocatore produce già qualche decina di pacchetti al secondo solo con la sincronizzazione della posizione; la cadenza la regoli in SA-MP con onfoot_rate, incar_rate e weapon_rate. La situazione diventa critica quando più giocatori stanno dietro allo stesso indirizzo, per esempio nella stessa casa oppure dietro il carrier NAT di un operatore mobile. Un limite troppo stretto butta fuori proprio quei giocatori, e il risultato somiglia a un attacco. Prima misura, poi imposta il valore e infine osserva le disconnessioni.
5. Valori limite in server.cfg e config.json
Le due implementazioni portano con sé i propri limiti di protezione, che spesso restano sui valori predefiniti. Per SA-MP, in server.cfg:
lanmode 0
query 1
announce 1
rcon 0
conncookies 1
connseedtime 300000
minconnectiontime 1000
messageslimit 500
messageholelimit 3000
ackslimit 3000
playertimeout 10000
In open.mp gli stessi parametri stanno in config.json:
{
"network": {
"port": 7777,
"bind": "",
"use_lan_mode": false,
"cookie_reseed_time": 300000,
"minimum_connection_time": 1000,
"messages_limit": 500,
"message_hole_limit": 3000,
"acks_limit": 3000,
"player_timeout": 10000,
"limits_ban_time": 60000
},
"rcon": {
"enable": false
}
}
Che cosa fanno questi valori:
- I cookie di connessione (
conncookiesovverocookie_reseed_time) chiedono al client di rispondere a una controdomanda prima che venga occupato uno slot. Un indirizzo mittente falsificato quella controdomanda non la vede mai e quindi non può rispondere. Sono il freno integrato più efficace contro le ondate di connessioni, lasciali attivi. - La distanza minima tra due tentativi di connessione (
minconnectiontimeovverominimum_connection_time, in millisecondi) impedisce che lo stesso indirizzo apra nuove connessioni al ritmo di una al secondo. Contro i join dei bot è la seconda leva importante. - I limiti su messaggi, buchi e conferme (
messageslimit,messageholelimit,ackslimit) stabiliscono quanto può inviare una connessione già stabilita. Proteggono dai client manipolati, non dal volume. - Il timeout (
playertimeout,player_timeout) decide per quanto tempo una connessione silenziosa tiene occupato uno slot. Un valore basso libera i posti più in fretta durante un'ondata di join, ma butta fuori prima i giocatori con una linea scadente. La durata del blocco (limits_ban_timein open.mp) stabilisce per quanto resta escluso un indirizzo sospetto.
Due avvertenze: config.json deve restare JSON valido, una virgola di troppo impedisce l'avvio. E open.mp completa da sé le impostazioni mancanti all'avvio, quindi modifica il file a server fermo.
Ancora una parola su RCON: la password viaggia in chiaro su UDP ed è leggibile lungo tutto il percorso. Se RCON non ti serve, disattivalo con rcon 0 ovvero "enable": false, altrimenti vale la regola: password lunga e casuale, e accesso solo attraverso una VPN.
6. Difesa nel gamemode e nei plugin
SA-MP richiama OnIncomingConnection prima che venga occupato uno slot giocatore. Lì puoi tenere il conto e bloccare temporaneamente gli indirizzi sospetti:
public OnIncomingConnection(playerid, ip_address[], port)
{
if (ConnectAttemptsTooHigh(ip_address))
{
BlockIpAddress(ip_address, 60000);
}
return 1;
}
ConnectAttemptsTooHigh è di proposito una funzione di conteggio tua: le soglie sensate dipendono dal tuo numero di giocatori. BlockIpAddress si aspetta la durata del blocco in millisecondi, UnBlockIpAddress lo revoca prima della scadenza. La lista dei blocchi sta nella RAM e dopo un riavvio è vuota.
In più, in ogni progetto servono due strumenti. Il plugin crashdetect indica, in caso di crash, la funzione coinvolta e la riga nel gamemode; senza il plugin un errore di runtime nel tuo stesso codice, visto da fuori, sembra un attacco. Un anti-cheat curato come Nex-AC copre le manipolazioni lato client, ma lavora esclusivamente sui giocatori già connessi e dentro la logica di gioco. Un'ondata di pacchetti falsificati non diventa mai un giocatore e passa quindi accanto all'anti-cheat. Sono due problemi diversi.
Tieni inoltre aggiornati gli include e i plugin: diversi metodi noti per far cadere un server SA-MP si basano su valori fuori dall'intervallo valido passati a funzioni native. E non passare mai input dei giocatori non verificati a SendRconCommand o a una query sul database.
7. La voce nella lista dei server e il tuo indirizzo reale
La voce nella lista ti rende trovabile, sia per i giocatori sia per chi attacca. Con announce 0 sparisci da entrambe le liste, e con esse anche dal flusso spontaneo di nuovi giocatori. È una scelta da soppesare, non un trucco segreto.
Mettere davanti un dominio non serve: il client risolve il nome una volta sola e poi parla direttamente con l'indirizzo, e quel nome lo può risolvere chiunque. Controlla piuttosto che cos'altro tradisce il tuo indirizzo: vecchi record A e AAAA nel DNS, il pannello utenti sulla stessa macchina, l'indicatore di stato di un bot Discord, un'interfaccia web del database lasciata aperta, certificati TLS con hostname vecchi e i messaggi sui forum dei primi tempi.
Da qui deriva una regola che molti progetti imparano troppo tardi: quando ti sposti su un indirizzo protetto, cambia contemporaneamente anche l'indirizzo di origine. Altrimenti il vecchio resta in ogni database degli scanner, e l'attacco aggira la protezione.
8. Whitelist e funzionamento a porte chiuse
Sulla porta di gioco una whitelist è raramente praticabile, perché i giocatori arrivano da indirizzi sempre diversi. Una password del server (password in entrambe le implementazioni) trasforma il server in una cerchia chiusa senza alcuna fatica, mentre la voce nella lista resta. Per gli accessi amministrativi la whitelist è invece obbligatoria, quindi per SSH, database, pannello e, se lo mantieni, RCON:
ufw allow from 203.0.113.10 to any port 22 proto tcp comment 'Admin'
ufw delete allow 22/tcp
ufw status numbered
Se l'indirizzo della tua connessione cambia spesso, una VPN è più pulita di una lista di eccezioni che continua a crescere.
9. Registrare i log: prima misurare, poi agire
SA-MP scrive il proprio log nel file server_log.txt dentro la directory del server, open.mp nel file configurato nella sezione logging. Quali indirizzi bussano più spesso:
grep "Incoming connection" server_log.txt \
| grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' \
| sort | uniq -c | sort -rn | head -20
Un numero elevato di cookie di connessione richiesti indica un'ondata di join:
grep -c "requests connection cookie" server_log.txt
Il valore più significativo però non sta nel log del gioco, ma nel kernel. Se il processo del server non preleva i pacchetti dal buffer di ricezione abbastanza in fretta, il kernel tiene il conto delle perdite:
nstat -az | grep -E 'Udp(InDatagrams|InErrors|NoPorts|RcvbufErrors)'
ip -s -s link show
Da qui nasce la distinzione più importante di tutte: se gli errori di buffer salgono mentre il carico della CPU resta basso, ti sta arrivando più traffico di quanto il processo riesca a smaltire. Se invece un core gira al massimo mentre il traffico sembra normale, il problema sta nel gamemode e non nella rete. Come tenere separati i due casi lo spiega l'articolo Riconoscere un attacco DDoS sul server.
Dove queste misure si fermano
Tutti i passaggi visti finora agiscono soltanto quando i pacchetti hanno già percorso la tua linea: il kernel li scarta dopo l'arrivo. Questo fissa un tetto rigido che non ha nulla a che vedere con la qualità delle tue regole.
Una linea da 1 Gbit/s, con i pacchetti più piccoli possibili, accetta circa 1,49 milioni di pacchetti al secondo, di più fisicamente non passa. Per confronto, due attacchi misurati e filtrati su server KernelHost: oltre 473,4 Gbit/s con oltre 41,5 milioni di pacchetti al secondo contro un server voce su UDP 9987, e oltre 112,2 Gbit/s con oltre 8,7 milioni di pacchetti al secondo contro un game server su UDP 7777. Il primo caso è circa 473 volte la banda e circa 28 volte la frequenza di pacchetti che una linea da 1 Gbit/s riesce ad assorbire. Nemmeno un filtro perfetto sul server cambia qualcosa, perché i pacchetti non arrivano proprio fino a lì: la linea a monte è satura, e insieme a essa cadono anche i pacchetti dei tuoi giocatori.
Altri due limiti scattano ancora prima. Primo, il server di gioco legge la porta in un unico thread di esecuzione. Un'ondata di query può tenere quel thread così occupato che i pacchetti di sincronizzazione dei giocatori veri scadono nel buffer di ricezione molto prima che la linea sia satura. Il processo non va in crash, diventa solo lento, e i giocatori vedono il rubberbanding. Secondo, con UDP gli indirizzi mittente sono falsificabili; i blocchi per indirizzo colpiscono allora persone estranee e non toccano affatto chi attacca.
In sintesi, senza giri di parole: il tuo lavoro sul server decide se passa un attacco piccolo. Se passa un attacco grande lo decide la rete davanti al server.
Che cosa mette in campo KernelHost
Inclusa su ogni server: la protezione permanente a due livelli
Ogni server di KernelHost sta dietro a un filtraggio a due livelli sempre attivo:
- Livello 1: rete di scrubbing globale con 17 Tbps di capacità di mitigazione. Gli attacchi volumetrici vengono intercettati e ripuliti vicino alla loro origine, prima ancora che raggiungano il datacenter di Francoforte sul Meno.
- Livello 2: filtraggio Arbor in tempo reale da 3,2 Tbps direttamente in loco a Francoforte sul Meno. Subito davanti al server vengono riconosciuti gli schemi specifici di protocollo e scartati pacchetto per pacchetto.
Tre caratteristiche sono decisive. La protezione è sempre attiva, quindi non esiste una fase di rilevamento durante la quale il tuo server va offline. Non viene usato alcun null-routing: l'indirizzo sotto attacco resta in rete, cadono soltanto i pacchetti dannosi, mentre le connessioni dei giocatori veri proseguono. E non costa nulla in più, perché è compresa in ogni pacchetto server, dal server root KVM al game server fino al server dedicato. Il filtraggio avviene sui livelli 3, 4 e 7 su qualsiasi porta TCP o UDP, quindi anche su UDP 7777. Tutto questo gira nel datacenter maincubes a Francoforte sul Meno, in Germania, gestito da KernelHost GmbH con sede a Vienna, in Austria. Quali giochi e protocolli abbiano un profilo dedicato lo mostra l'articolo Protezione DDoS per game server in tempo reale.
Per i progetti sotto attacco continuo: Advanced DDoS Protection
Certi progetti non vengono colpiti ogni tanto, ma in modo mirato e per settimane intere. Per questi casi c'è la Advanced DDoS Protection a partire da 50,00 € al mese, PrePaid e senza durata minima. Aggiunge tre cose alla protezione permanente:
- Un IP di protezione dedicato dal nucleo di Francoforte. Il tuo server viene spostato su quell'indirizzo all'interno della rete KernelHost, dalla tua parte non devi modificare nulla.
- Regole di protezione gestibili da te per porta e protocollo nell'area clienti. Le modifiche hanno effetto in tempo reale, senza ticket e senza attese, quindi puoi correggere il tiro anche nel mezzo di un attacco.
- Un profilo di protezione adatto al gioco. Profili già pronti per oltre 40 giochi, servizi e protocolli, tra cui SA-MP e open.mp oltre alle applicazioni TCP e UDP personalizzate. Anche il pannello utenti, il server voce e la VPN stanno dietro allo stesso indirizzo protetto.
I due livelli a confronto
| Caratteristica | Protezione permanente inclusa | Advanced DDoS Protection |
|---|---|---|
| Prezzo | senza sovrapprezzo in ogni pacchetto server | da 50,00 € al mese, PrePaid |
| Attivazione | attiva dalla consegna, non c'è nulla da configurare | ordini, ricevi l'IP di protezione, il server viene spostato |
| Capacità di filtraggio | 17 Tbps di scrubbing globale, più 3,2 Tbps di filtraggio Arbor in tempo reale a Francoforte sul Meno | la stessa infrastruttura, con in più regole tue |
| Indirizzo | IP del server compreso nel pacchetto | IP di protezione dedicato aggiuntivo |
| Gestione delle regole | preconfigurata e automatica | gestibile da te nell'area clienti per porta e protocollo, le modifiche hanno effetto in tempo reale |
| Profili di protezione | riconoscimento automatico degli schemi | profilo selezionabile per gioco, oltre 40 giochi e protocolli |
| Null-routing | no | no |
| Adatta a | il caso normale, anche con attacchi occasionali | progetti colpiti in modo continuo e mirato |
| Durata | legata al pacchetto server | PrePaid, nessuna durata minima, nessun preavviso di disdetta |
Errori frequenti e soluzioni
"Il server non c'è più, quindi è un attacco." Verifica prima di tutto se il processo è ancora in esecuzione. Un errore di runtime nel gamemode, visto da fuori, ha esattamente lo stesso aspetto. Con crashdetect la causa finisce nel log, senza il plugin puoi solo tirare a indovinare.
"Abbiamo bloccato la porta di query." Una porta di query separata non esiste. Chi blocca UDP 7777 blocca il gioco. Quello che si intende è o query 0 (il server sparisce dalla lista) oppure un rate limit sulla stessa porta.
"Abbiamo cambiato IP e siamo di nuovo online." Se non chiudi la falla, il nuovo indirizzo torna pubblico nel giro di poche ore. I vecchi record DNS, il pannello sulla stessa macchina e l'indicatore di stato di un bot Discord lo tradiscono senza fallo.
"Abbiamo impostato un rate limit di 20 pacchetti al secondo per indirizzo." È troppo stretto. Già un singolo giocatore sta sopra quella soglia, e più giocatori dietro allo stesso indirizzo NAT si dividono la stessa quota. Così butti fuori i tuoi stessi giocatori.
"Ci siamo chiusi fuori con il firewall." Un riavvio non serve, perché UFW ripristina le sue regole all'avvio. Su KernelHost apri la console VNC nell'area clienti ed esegui lì ufw disable. Sui server root KVM e sui server dedicati non esistono IPMI o iDRAC, la strada passa dalla console VNC.
"La password di RCON sta nella chat del team." RCON viaggia in chiaro su UDP ed è leggibile lungo tutto il percorso. Se non ti serve, disattivalo, altrimenti vale la regola: password lunga e casuale, e accesso solo attraverso una VPN.
"Aspettiamo semplicemente che l'attacco finisca." Gli attacchi che funzionano vengono ripetuti. Documenta orario, durata, valori di picco e porte colpite. Sono esattamente i dati che servono anche a un ticket di supporto, perché il filtraggio venga affinato in modo mirato.
Se sei sotto attacco proprio adesso
Se il tuo progetto gira già su KernelHost, il filtraggio è permanentemente attivo e non devi attivare nulla. Se noti comunque delle anomalie, apri un ticket di supporto indicando periodo, porta e comportamento osservato, così le regole per il tuo indirizzo vengono affinate. Durante un attacco in corso ci raggiungi anche tramite la chat WhatsApp di emergenza al numero +43 650 8209883.
Domande frequenti
Su quale porta gira un server SA-MP o open.mp?
Posso bloccare l'accesso query senza bloccare il server?
Il mio server non c'è più: attacco o crash?
Quali impostazioni frenano subito un'ondata di join?
Basta un firewall sul server contro gli attacchi DDoS?
Serve a qualcosa cambiare indirizzo IP?
La protezione DDoS di KernelHost è compresa nel prezzo?
Quando conviene la Advanced DDoS Protection?
2026 KernelHost GmbH. Tutti i diritti riservati. Questa guida è protetta dal diritto d'autore. La ripubblicazione su altri siti web, anche parziale o in forma modificata, non è consentita senza il nostro consenso scritto. Le citazioni con indicazione della fonte e un link sono le benvenute.

