Proteger servidores de SA-MP y open.mp frente a ataques DDoS
SA-MP y open.mp gestionan el juego, la query y RCON por un único puerto UDP. Esta guía muestra qué puedes asegurar tú mismo y a partir de qué tamaño de ataque solo ayuda el filtrado en la red que hay delante.
Un proyecto de SA-MP u open.mp suele crecer siempre igual: sube el número de jugadores, el servidor escala posiciones en la lista y, unos días después, las conexiones empiezan a caerse en cadena. La parte más larga de esta guía trata de lo que puedes cambiar tú mismo en tu servidor sin costes adicionales. Después viene dónde acaban técnicamente esas medidas y, solo entonces, qué pone KernelHost frente a los ataques.
¿Por qué SA-MP y open.mp reciben ataques tan a menudo?
La escena es pequeña y muy competitiva. Muchos servidores de roleplay y freeroam se disputan a los mismos jugadores, y tirar a un competidor fuera de la lista durante unas horas es algo que muchos hacen sin pensárselo dos veces. A eso se suman los jugadores baneados y los intentos de extorsión contra los proyectos que tienen tienda propia.
Técnicamente, el juego se lo pone fácil a quien ataca. Todo el tráfico de juego va por UDP, y UDP no tiene ningún establecimiento de conexión que le cueste algo al atacante; además, las direcciones de origen se pueden falsificar. La entrada en la lista publica la dirección y el puerto, así que no hace falta ningún trabajo previo de reconocimiento. Y como la mayoría de los proyectos corren en un único servidor, el servidor de juego, la base de datos, el panel de usuarios y muchas veces el servidor de voz comparten la misma dirección: un solo impacto lo tumba todo a la vez.
Los puertos y protocolos que entran en juego
- Servidor SA-MP: UDP 7777 por defecto, configurable con
portenserver.cfg. - Servidor open.mp: también UDP 7777 por defecto, configurable con
network.portenconfig.json. - Query: el mismo puerto UDP. No existe un puerto de consulta aparte. Los navegadores de servidores, las páginas de estado y los bots de Discord hablan con el mismo puerto por el que se juega.
- RCON: también el mismo puerto UDP, como un opcode propio dentro del protocolo de query, en texto plano.
- La entrada en la lista sale del servidor hacia la lista de servidores correspondiente, así que en sentido entrante no hay que abrir nada.
- Todo lo demás, en la misma máquina: SSH en TCP 22, MariaDB o MySQL en TCP 3306, y el panel de usuarios en TCP 80 y 443.
La consecuencia: no puedes separar con el firewall el acceso de query del juego, porque los dos están en el mismo puerto. Quien bloquea UDP 7777 deja fuera a sus propios jugadores.
Una petición de query empieza con once bytes: cuatro bytes de identificador, cuatro de dirección del servidor, dos de puerto y uno de opcode. El opcode decide la respuesta: i devuelve la información del servidor, r las reglas, c una lista corta de jugadores, d una lista detallada con nombre, puntuación y ping de cada jugador, p devuelve cuatro bytes para medir el ping y x es RCON. En un servidor con mucha gente, once bytes de petición generan varios kilobytes de respuesta. Eso hace que un acceso de query abierto resulte interesante por partida doble: como objetivo y como amplificador contra terceros. Lo que hay detrás de este patrón de ataque lo explica el artículo ¿Qué es un ataque DDoS?.
Lo que puedes hacer tú antes de gastar dinero
Los pasos siguientes no cuestan nada y funcionan contra los ataques del día a día: floods de join, floods de query y fuentes sueltas con una tasa de paquetes alta. Todos los comandos dan por supuesto que trabajas como root; si no, antepón sudo.
1. Inventario: ¿qué está escuchando en realidad?
ss -lnup
ss -lntp
Lo que escucha en 127.0.0.1 o ::1 no necesita ninguna regla de firewall. Lo que aparece en 0.0.0.0 o [::] es accesible desde fuera y tiene que estar justificado.
2. Cerrar todo lo que el juego no necesita
Un filtro de paquetes no resuelve un ataque volumétrico, pero reduce la superficie de ataque. Una configuración de partida sólida 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
El orden no es casual: las reglas de permiso van antes de activar el firewall, o te quedarás fuera de tu propio servidor. Los detalles y la vía de vuelta están en el artículo Configurar el firewall UFW. En los servidores root KVM y en los servidores dedicados de KernelHost llegas al sistema en caso de emergencia por la consola VNC del área de cliente.
La base de datos no pinta nada en la red abierta. Si ss -lntp | grep 3306 muestra un 0.0.0.0:3306, pon bind-address = 127.0.0.1 y reinicia el servicio. El servidor de juego también conviene enlazarlo a una dirección fija: en SA-MP con bind y en open.mp con network.bind.
3. Rebajar el riesgo del query sin dejar fuera a los jugadores
SA-MP tiene en server.cfg el interruptor query 0, con el que el servidor deja de responder a cualquier consulta. Funciona, pero se paga caro: el servidor desaparece del navegador de servidores, ya no se pueden leer ni el número de jugadores ni las reglas, y las páginas de estado y los bots de Discord lo muestran como fuera de línea. Para un círculo cerrado es una opción; para un proyecto que quiere crecer, no. En open.mp el cambio está en la sección network de config.json; comprueba el nombre exacto de la clave en tu versión en lugar de adivinarlo.
El camino realista es, por tanto, limitar en vez de apagar. Este filtro muestra en vivo solo los paquetes que llevan el identificador de query:
tcpdump -ni any -c 100 'udp port 7777 and udp[8:4] = 0x53414d50'
Qué direcciones de origen mandan más tráfico al puerto de juego:
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. Poner límites de tasa en el stack de red
Con nftables limitas la tasa de paquetes por dirección de origen. El siguiente conjunto de reglas crea una tabla propia para no estorbar a 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 añadir además un tope para el puerto entero, para que una avalancha muy repartida no se cuele por el hueco que dejan muchas fuentes individuales:
nft add rule inet gameguard input udp dport 7777 limit rate over 20000/second burst 5000 packets drop
Con iptables, el módulo hashlimit consigue lo mismo:
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
Estas cifras son valores de partida, no una recomendación para tu servidor. Un solo jugador genera ya unas cuantas decenas de paquetes por segundo solo con la sincronización de posición; la frecuencia la controlas en SA-MP con onfoot_rate, incar_rate y weapon_rate. La cosa se complica cuando varios jugadores comparten la misma dirección, por ejemplo en la misma casa o detrás del CGNAT de un operador móvil. Un límite demasiado estrecho echa justo a esos jugadores, y eso se parece mucho a un ataque. Primero medir, después fijar el valor y luego observar las desconexiones.
5. Valores límite en server.cfg y config.json
Las dos implementaciones traen sus propios límites de protección, que muchas veces se quedan tal cual vienen de fábrica. Para SA-MP, en server.cfg:
lanmode 0
query 1
announce 1
rcon 0
conncookies 1
connseedtime 300000
minconnectiontime 1000
messageslimit 500
messageholelimit 3000
ackslimit 3000
playertimeout 10000
En open.mp esos mismos parámetros están en 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
}
}
Qué hace cada uno de estos valores:
- Las cookies de conexión (
conncookiesocookie_reseed_time) exigen al cliente que responda a una comprobación antes de que se ocupe un slot. Una dirección de origen falsificada nunca llega a ver esa comprobación y, por tanto, tampoco puede responderla. Es el freno integrado más eficaz contra las avalanchas de conexiones, así que déjalo activado. - La distancia mínima entre intentos de conexión (
minconnectiontimeominimum_connection_time, en milisegundos) impide que la misma dirección abra conexiones nuevas una tras otra cada segundo. Contra los joins de bots es el segundo ajuste importante. - Los límites de mensajes, huecos y confirmaciones (
messageslimit,messageholelimit,ackslimit) acotan cuánto puede enviar una conexión ya establecida. Protegen frente a clientes manipulados, no frente al volumen. - El tiempo de espera (
playertimeout,player_timeout) determina cuánto tiempo bloquea un slot una conexión que ha quedado muda. Un valor bajo libera plazas más rápido durante un flood de joins, pero también echa antes a los jugadores con mala conexión. La duración del bloqueo (limits_ban_timeen open.mp) fija cuánto tiempo se queda fuera una dirección sospechosa.
Dos advertencias: config.json tiene que seguir siendo JSON válido, y una coma de más impide el arranque. Además, open.mp completa por su cuenta los valores que falten al arrancar, así que edita el archivo con el servidor parado.
Una nota más sobre RCON: la contraseña viaja en texto plano por UDP y se puede leer en todo el trayecto. Si no necesitas RCON, desactívalo con rcon 0 o "enable": false; si lo necesitas, usa una contraseña larga y aleatoria y accede solo a través de una VPN.
6. Defensa en el gamemode y en los plugins
SA-MP llama a OnIncomingConnection antes de que se ocupe un slot de jugador. Ahí puedes llevar la cuenta y bloquear temporalmente las direcciones sospechosas:
public OnIncomingConnection(playerid, ip_address[], port)
{
if (ConnectAttemptsTooHigh(ip_address))
{
BlockIpAddress(ip_address, 60000);
}
return 1;
}
ConnectAttemptsTooHigh es a propósito tu propia función de conteo: los umbrales razonables dependen de tu número de jugadores. BlockIpAddress espera la duración del bloqueo en milisegundos y UnBlockIpAddress lo levanta antes de tiempo. La lista de bloqueos vive en la RAM y queda vacía después de un reinicio.
Además, hay dos herramientas que no deberían faltar en ningún proyecto. El plugin crashdetect muestra, cuando el servidor se cae, la función afectada y la línea del gamemode; sin él, un error de ejecución en tu propio código se ve desde fuera igual que un ataque. Un anti-cheat bien mantenido como Nex-AC cubre las manipulaciones del lado del cliente, pero solo actúa sobre jugadores ya conectados y dentro de la lógica del juego. Una avalancha de paquetes falsificados nunca llega a convertirse en un jugador y pasa de largo. Son dos problemas distintos.
Mantén también al día los includes y los plugins: varios métodos conocidos para tumbar un servidor de SA-MP se basan en pasar a funciones nativas valores fuera del rango válido. Y no pases nunca entradas de jugador sin comprobar a SendRconCommand ni a una consulta de base de datos.
7. La entrada en la lista de servidores y tu dirección real
La entrada en la lista te hace localizable, tanto para los jugadores como para quien ataca. Con announce 0 desapareces de las dos listas y, con ello, también del flujo de jugadores que llegan por sí solos. Es una decisión que hay que sopesar, no un truco.
Poner un dominio por delante no sirve de nada: el cliente resuelve el nombre una sola vez y a partir de ahí habla directamente con la dirección, y ese nombre lo puede resolver cualquiera. Revisa mejor qué otras cosas delatan tu dirección: registros A y AAAA antiguos en el DNS, el panel de usuarios en la misma máquina, el indicador de estado de un bot de Discord, una interfaz web de base de datos abierta, certificados TLS con nombres de host antiguos y mensajes de foro de los primeros tiempos del proyecto.
De ahí sale una regla que muchos proyectos aprenden demasiado tarde: si te mudas a una dirección protegida, cambia al mismo tiempo la dirección de origen. Si no, la antigua sigue en todas las bases de datos de escaneo y el ataque pasa por al lado de la protección.
8. Whitelist y funcionamiento cerrado
En el puerto de juego, una whitelist rara vez resulta práctica, porque los jugadores llegan desde direcciones que van cambiando. Una contraseña de servidor (password en las dos implementaciones) convierte el servidor en un círculo cerrado sin ningún esfuerzo, y la entrada en la lista se mantiene. En cambio, para los accesos de administración la whitelist es obligatoria: SSH, base de datos, panel y, si decides conservarlo, RCON:
ufw allow from 203.0.113.10 to any port 22 proto tcp comment 'Admin'
ufw delete allow 22/tcp
ufw status numbered
Si tu propia dirección cambia con frecuencia, una VPN es más limpia que una lista de excepciones que no para de crecer.
9. Registrar: primero medir, después actuar
SA-MP escribe su log en server_log.txt, dentro del directorio del servidor, y open.mp en el archivo que hayas configurado en la sección logging. Qué direcciones llaman a la puerta con más frecuencia:
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 número alto de cookies de conexión solicitadas apunta a un flood de joins:
grep -c "requests connection cookie" server_log.txt
Pero el dato más revelador no está en el log del juego, sino en el kernel. Si el proceso del servidor no saca los paquetes del búfer de recepción con la rapidez suficiente, el kernel va contando las pérdidas:
nstat -az | grep -E 'Udp(InDatagrams|InErrors|NoPorts|RcvbufErrors)'
ip -s -s link show
De ahí sale la distinción más importante de todas: si los errores de búfer suben con la CPU poco cargada, te está llegando más tráfico del que el proceso puede atender. Si, en cambio, hay un núcleo al máximo mientras el tráfico parece normal, el problema está en el gamemode y no en la red. Cómo separar los dos casos lo explica el artículo Detectar un ataque DDoS en el servidor.
Dónde acaban estas medidas
Todos los pasos anteriores actúan cuando los paquetes ya han pasado por tu línea: el kernel los descarta después de que hayan llegado. Eso marca un techo duro que no tiene nada que ver con la calidad de tus reglas.
Una conexión de 1 Gbit/s admite, con el tamaño de paquete más pequeño posible, unos 1,49 millones de paquetes por segundo; físicamente no cabe más. Como comparación, dos ataques medidos y filtrados en servidores de KernelHost: más de 473,4 Gbit/s con más de 41,5 millones de paquetes por segundo contra un servidor de voz en UDP 9987, y más de 112,2 Gbit/s con más de 8,7 millones de paquetes por segundo contra un servidor de juego en UDP 7777. El primer caso equivale a unas 473 veces el ancho de banda y a unas 28 veces la tasa de paquetes que una línea de 1 Gbit/s puede llegar a absorber. Ni siquiera un filtro perfecto en el servidor cambia nada, porque los paquetes ni siquiera llegan hasta él: la conexión que hay delante está llena y con ella caen también los paquetes de tus jugadores.
Otros dos límites aparecen todavía antes. El primero: el servidor de juego lee el puerto en un único hilo de ejecución. Un flood de query puede tener ese hilo tan ocupado que los paquetes de sincronización de los jugadores reales caduquen en el búfer de recepción mucho antes de que la línea se sature. El proceso no se cae, solo se vuelve lento, y los jugadores ven rubberbanding. El segundo: en UDP las direcciones de origen se pueden falsificar, así que los bloqueos por dirección acaban afectando a terceros que no tienen nada que ver y no tocan al atacante.
Resumido sin adornos: tu trabajo en el servidor decide si pasa un ataque pequeño. Si pasa un ataque grande lo decide la red que hay delante del servidor.
Lo que KernelHost pone frente a los ataques
Incluido en cada servidor: la protección permanente en dos niveles
Todos los servidores de KernelHost están detrás de un filtrado en dos niveles, activo de forma permanente:
- Nivel 1: red global de scrubbing con 17 Tbps de capacidad de mitigación. Los ataques volumétricos se interceptan y se limpian cerca de su origen, antes incluso de que lleguen al centro de datos de Frankfurt am Main.
- Nivel 2: filtrado Arbor en tiempo real con 3,2 Tbps directamente sobre el terreno, en Frankfurt am Main. Justo delante del servidor se reconocen los patrones propios de cada protocolo y se descartan paquete a paquete.
Hay tres propiedades decisivas. La protección está activa de forma permanente, así que no existe ninguna fase de detección durante la cual tu servidor se quede fuera de línea. No se recurre a ningún null-routing: la dirección atacada sigue en la red, solo caen los paquetes dañinos y las conexiones de los jugadores reales continúan. Y no cuesta nada aparte, sino que está incluida en todos los paquetes de servidor, desde el servidor root KVM y el servidor de juego hasta el servidor dedicado. Se filtra en las capas 3, 4 y 7 en cualquier puerto TCP o UDP, así que también en UDP 7777. Todo esto funciona en el centro de datos maincubes de Frankfurt am Main (Alemania) y lo opera KernelHost GmbH, con sede en Viena (Austria). Qué juegos y protocolos tienen perfil propio lo muestra el artículo Protección DDoS para servidores de juego en tiempo real.
Para proyectos bajo fuego continuo: Advanced DDoS Protection
A algunos proyectos no los golpean de vez en cuando, sino de forma dirigida y durante semanas. Para esos casos existe la Advanced DDoS Protection desde 50,00 € al mes, PrePaid y sin permanencia mínima. Añade tres cosas a la protección permanente:
- Una IP de protección dedicada del núcleo de red de Fráncfort. Tu servidor se pasa a ella dentro de la red de KernelHost, así que por tu parte no tienes que reconstruir nada.
- Reglas de protección por puerto y protocolo que gestionas tú mismo en el área de cliente. Los cambios surten efecto en tiempo real, sin ticket y sin esperas, así que puedes reajustar en mitad de un ataque.
- Un perfil de protección a la medida del juego. Perfiles listos para más de 40 juegos, servicios y protocolos, entre ellos SA-MP y open.mp, además de aplicaciones TCP y UDP propias. El panel de usuarios, el servidor de voz y la VPN también caben detrás de la misma dirección protegida.
Los dos niveles en comparación
| Característica | Protección permanente incluida | Advanced DDoS Protection |
|---|---|---|
| Precio | sin recargo, en todos los paquetes de servidor | desde 50,00 € al mes, PrePaid |
| Activación | activa desde el aprovisionamiento, no hay nada que configurar | se pide, recibes la IP de protección y el servidor se pasa a ella |
| Capacidad de filtrado | 17 Tbps de scrubbing global, más 3,2 Tbps de filtrado Arbor en tiempo real en Frankfurt am Main | la misma infraestructura, ampliada con reglas propias |
| Dirección | la IP de servidor incluida en el paquete | IP de protección dedicada adicional |
| Gestión de reglas | preconfigurada y automática | gestionable por ti mismo en el área de cliente por puerto y protocolo, los cambios surten efecto en tiempo real |
| Perfiles de protección | detección automática de patrones | perfil elegible por juego, más de 40 juegos y protocolos |
| Null-routing | no | no |
| Recomendable para | el caso normal, también con ataques ocasionales | proyectos atacados de forma continua y dirigida |
| Permanencia | ligada al paquete de servidor | PrePaid, sin permanencia mínima y sin plazo de preaviso |
Errores frecuentes y soluciones
"El servidor no está, así que es un ataque." Comprueba primero si el proceso sigue en marcha. Un error de ejecución en el gamemode se ve desde fuera exactamente igual. Con crashdetect la causa aparece en el log; sin él, solo te queda adivinar.
"Hemos bloqueado el puerto de query." No existe un puerto de query aparte. Quien bloquea UDP 7777 bloquea el juego. Lo que se quiere decir es o bien query 0 (el servidor desaparece de la lista) o bien un límite de tasa en ese mismo puerto.
"Hemos cambiado la IP y ya estamos otra vez en línea." Si no cierras la fuga, la dirección nueva vuelve a ser pública en cuestión de horas. Los registros DNS antiguos, el panel en la misma máquina y el indicador de estado de un bot de Discord la delatan sin falta.
"Hemos puesto un límite de 20 paquetes por segundo y dirección." Es demasiado estrecho. Un solo jugador ya está por encima, y varios jugadores detrás de una misma dirección NAT comparten ese cupo. Con eso echas a tus propios jugadores.
"Nos hemos dejado fuera con el firewall." Reiniciar no sirve, porque UFW restaura sus reglas al arrancar. En KernelHost abres la consola VNC en el área de cliente y ejecutas allí ufw disable. En los servidores root KVM y en los servidores dedicados no hay IPMI ni iDRAC, el camino pasa por la consola VNC.
"La contraseña de RCON está en el chat del equipo." RCON va en texto plano por UDP y se puede leer en todo el trayecto. Si no lo necesitas, desactívalo; y si lo necesitas, usa una contraseña larga y aleatoria y accede solo a través de una VPN.
"Simplemente esperamos a que pase el ataque." Los ataques que funcionan se repiten. Documenta el momento, la duración, los valores máximos y los puertos afectados. Esos son justo los datos que necesita un ticket de soporte para poder ajustar el filtrado de forma dirigida.
Si te están atacando ahora mismo
Si tu proyecto ya está en KernelHost, el filtrado está activo de forma permanente y no tienes que encender nada. Si aun así notas algo raro, abre un ticket de soporte con el periodo, el puerto y el comportamiento que observas, para que se reajusten las reglas de tu dirección. Durante un ataque en curso puedes contactar además por el chat de emergencia de WhatsApp en el +43 650 8209883.
Preguntas frecuentes
¿En qué puerto funciona un servidor de SA-MP u open.mp?
¿Puedo bloquear el acceso de query sin bloquear el servidor?
Mi servidor no responde: ¿es un ataque o se ha caído?
¿Qué ajustes frenan de inmediato un flood de joins?
¿Basta un firewall en el servidor contra los ataques DDoS?
¿Sirve de algo cambiar la dirección IP?
¿La protección DDoS de KernelHost está incluida en el precio?
¿Cuándo merece la pena la Advanced DDoS Protection?
2026 KernelHost GmbH. Todos los derechos reservados. Esta guía está protegida por derechos de autor. Su publicación en otros sitios web, aunque sea de forma parcial o modificada, no está permitida sin nuestro consentimiento por escrito. Las citas con indicación de la fuente y un enlace son muy bienvenidas.

