Los servidores de juegos son uno de los objetivos más habituales de los ataques de denegación de servicio: basta con un jugador expulsado para que alguien intente tumbar la partida. En este tutorial prepararás un servidor con Ubuntu 24.04 para resistir los ataques pequeños y los abusos de un único origen: ajustarás el kernel, crearás un firewall con nftables que limita paquetes y conexiones por IP y aprenderás a observar el tráfico durante un ataque. También verás qué parte del trabajo tiene que hacer la red, porque ningún firewall local detiene un ataque que satura el enlace.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con un servidor de juegos ya instalado o por instalar.
- Un usuario no root con privilegios
sudo. - Acceso a la consola del servidor desde el panel, por si una regla de firewall te deja sin SSH.
- Los puertos de tu juego. En los ejemplos se usan
25565/tcp(Minecraft Java) y27015/udp(juegos basados en Source); sustitúyelos por los tuyos.
Qué puede y qué no puede hacer tu servidor
Conviene tener claro el reparto de responsabilidades antes de tocar nada:
| Tipo de ataque | Ejemplo | Dónde se mitiga |
|---|---|---|
| Volumétrico | Amplificación DNS, NTP o memcached, inundaciones UDP de varios Gbps | En la red, antes de llegar al servidor |
| De protocolo | SYN flood, paquetes TCP malformados | Red y kernel (SYN cookies, conntrack) |
| Desde pocas IP | Un cliente que envía miles de paquetes o abre cientos de conexiones | Firewall local con límites por IP |
| De aplicación | Consultas de estado o intentos de login masivos al propio juego | Firewall local y configuración del juego |
Todos los servicios de CubePath incluyen protección Standard AntiDDoS, que filtra en los routers de borde los ataques volumétricos y de amplificación más comunes. Para servidores de juegos expuestos existe Premium AntiDDoS, con perfiles específicos para juegos y reglas Edge ACL aplicadas en el borde de la red. Las guías de protección DDoS de CubePath explican cómo funciona cada nivel. Lo que configuras en este tutorial complementa esa capa y no la sustituye.
Paso 1: Ajustar el kernel para resistir SYN floods
Las SYN cookies permiten al kernel responder a nuevas conexiones TCP sin reservar memoria hasta que el cliente completa el saludo, lo que neutraliza los SYN floods moderados. El filtrado de ruta inversa descarta paquetes con direcciones de origen falsificadas que no podrían llegar por esa interfaz.
Crea un archivo propio en /etc/sysctl.d:
sudo nano /etc/sysctl.d/90-gameserver-ddos.conf
Añade este contenido:
# Respuesta a SYN floods
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_synack_retries = 2
# Descartar paquetes con origen falsificado
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# No responder a pings de broadcast ni aceptar redirecciones ICMP
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
Aplica todos los archivos de configuración:
sudo sysctl --system
Comprueba que los valores están activos:
sysctl net.ipv4.tcp_syncookies net.ipv4.conf.all.rp_filter
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
Notasi tu servidor tiene varias interfaces con rutas asimétricas (por ejemplo, una red privada y una pública con tráfico cruzado), usa
rp_filter = 2(modo flexible) para no descartar tráfico legítimo.
Paso 2: Instalar nftables y desactivar UFW
nftables es el framework de firewall de Linux en Ubuntu 24.04 y permite crear límites por IP de origen con sets dinámicos, algo que UFW no ofrece. Para evitar dos conjuntos de reglas compitiendo, usarás solo nftables.
Instala el paquete:
sudo apt update
sudo apt install nftables
Si UFW está activo, desactívalo. Las reglas del paso siguiente sustituyen a las suyas, incluida la de SSH:
sudo ufw status
sudo ufw disable
Paso 3: Crear el firewall con límites por IP
El conjunto de reglas sigue una política de denegación por defecto: solo entra el tráfico de conexiones ya establecidas, SSH y los puertos del juego. Sobre los puertos del juego se aplican dos límites por IP de origen:
- Un límite de paquetes por segundo para UDP, guardado en un set dinámico que caduca a los 60 segundos.
- Un límite de conexiones TCP simultáneas con
ct count, que impide que una sola IP agote los slots del servidor.
Abre el archivo que carga el servicio nftables:
sudo nano /etc/nftables.conf
Sustituye su contenido por el siguiente, adaptando los puertos:
#!/usr/sbin/nft -f
flush ruleset
define SSH_PORT = 22
define GAME_TCP = { 25565 }
define GAME_UDP = { 27015 }
table inet filter {
# Contadores de paquetes UDP por IP de origen
set udp_rate_v4 {
type ipv4_addr
flags dynamic, timeout
timeout 60s
size 65535
}
set udp_rate_v6 {
type ipv6_addr
flags dynamic, timeout
timeout 60s
size 65535
}
# Conexiones TCP simultáneas por IP de origen
set tcp_conn_v4 {
type ipv4_addr
flags dynamic
size 65535
}
set tcp_conn_v6 {
type ipv6_addr
flags dynamic
size 65535
}
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
ct state established,related accept
ct state invalid drop
# Paquetes TCP nuevos que no empiezan con SYN
tcp flags & (fin|syn|rst|ack) != syn ct state new drop
# ICMP limitado; IPv6 necesita Neighbor Discovery para funcionar
ip protocol icmp icmp type echo-request limit rate 5/second accept
ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit, nd-neighbor-advert, nd-router-advert, nd-router-solicit } accept
ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 5/second accept
# SSH con límite de conexiones nuevas
tcp dport $SSH_PORT ct state new limit rate 15/minute accept
# Juego TCP: máximo 5 conexiones simultáneas por IP
tcp dport $GAME_TCP ct state new add @tcp_conn_v4 { ip saddr ct count over 5 } counter drop
tcp dport $GAME_TCP ct state new add @tcp_conn_v6 { ip6 saddr ct count over 5 } counter drop
tcp dport $GAME_TCP ct state new accept
# Juego UDP: más de 300 paquetes/s sostenidos por IP se descartan
udp dport $GAME_UDP update @udp_rate_v4 { ip saddr limit rate over 300/second burst 600 packets } counter drop
udp dport $GAME_UDP update @udp_rate_v6 { ip6 saddr limit rate over 300/second burst 600 packets } counter drop
udp dport $GAME_UDP accept
# Registrar una muestra de lo descartado
limit rate 10/minute log prefix "nft-drop: " level info
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
Algunos puntos a tener en cuenta:
- El límite UDP depende del juego. Un cliente de un shooter a 64 ticks envía unos 64 a 128 paquetes por segundo, por lo que 300 deja margen. Mide el tráfico real de un jugador (paso 5) antes de bajarlo.
- Si varios jugadores comparten IP (una LAN party, un CGNAT de operador móvil), el límite de 5 conexiones TCP puede quedarse corto. Súbelo si recibes quejas.
- La cadena
forwardcon políticadropbloquea el tráfico reenviado. Si ejecutas el juego en Docker, no uses este archivo tal cual: Docker crea sus propias reglas y necesita reenvío. En ese caso aplica los límites en la cadenaDOCKER-USERo en el nivel de red.
Comprueba la sintaxis antes de cargar nada:
sudo nft -c -f /etc/nftables.conf
Si no hay salida, el archivo es válido. Activa el servicio para que las reglas se carguen en cada arranque y aplícalas ahora:
sudo systemctl enable --now nftables
sudo systemctl restart nftables
Importanteabre una segunda sesión SSH antes de cerrar la actual. Si no puedes entrar, usa la consola del panel y ejecuta
sudo nft flush rulesetpara volver a un firewall abierto mientras corriges el archivo.
Paso 4: Verificar las reglas
Lista el conjunto de reglas cargado:
sudo nft list ruleset
Deberías ver la tabla inet filter con las tres cadenas. Conéctate al juego desde tu equipo y, desde el servidor, consulta los sets dinámicos. Tu IP aparecerá en ellos mientras juegas:
sudo nft list set inet filter udp_rate_v4
table inet filter {
set udp_rate_v4 {
type ipv4_addr
size 65535
flags dynamic,timeout
timeout 1m
elements = { 198.51.100.24 limit rate over 300/second burst 600 packets expires 58s }
}
}
Los contadores de las reglas drop indican cuánto tráfico se ha descartado:
sudo nft list chain inet filter input | grep counter
En un servidor tranquilo, esos contadores deberían permanecer a cero o muy cerca.
Paso 5: Observar el tráfico durante un ataque
Cuando los jugadores reporten lag, lo primero es saber si el problema es el enlace, la CPU o un origen concreto. Instala un par de herramientas ligeras:
sudo apt install conntrack iftop
Revisa el número de conexiones rastreadas por el kernel frente al máximo:
sudo conntrack -C
cat /proc/sys/net/netfilter/nf_conntrack_max
Si el primer valor se acerca al segundo, la tabla de conntrack se está llenando y se descartarán conexiones nuevas, incluidas las legítimas.
Muestra el resumen de sockets TCP, útil para detectar un SYN flood (muchas conexiones en estado synrecv):
ss -s
ss -tn state syn-recv | wc -l
Mira en tiempo real qué IP consumen más ancho de banda en la interfaz pública (normalmente eth0; compruébalo con ip -br addr):
sudo iftop -i eth0 -n
Consulta la muestra de paquetes descartados en el registro del kernel:
sudo journalctl -k --grep "nft-drop" --since "10 min ago"
Con esta información puedes decidir:
- Pocas IP con mucho tráfico: el firewall ya las está limitando. Si insisten, bloquéalas temporalmente, por ejemplo
sudo nft add rule inet filter input ip saddr 203.0.113.50 drop(se pierde al reiniciar nftables). - Miles de IP distintas o el enlace saturado: el ataque es volumétrico. El firewall local no puede hacer nada útil porque el tráfico ya ha llenado la conexión. Aquí actúa la protección de red.
Paso 6: Reducir la superficie de ataque
Además del firewall, hay medidas que evitan ataques en lugar de mitigarlos:
- No expongas puertos de administración. RCON, paneles web y bases de datos deben escuchar solo en
127.0.0.1o aceptar únicamente tu IP. Por ejemplo, en Minecraft dejaenable-rcon=falseenserver.propertiessi no lo usas. - Limita las consultas de estado. Muchos juegos responden a consultas de estado por UDP que pueden usarse para amplificación. Desactívalas si no las necesitas (en Minecraft,
enable-query=false). - No publiques la IP de otros servicios en el mismo servidor. Si tu web o tu bot de Discord comparten IP con el juego, un ataque a uno tumba todos.
- Activa la protección adecuada en la IP del juego. Para servidores públicos con muchos jugadores, Premium AntiDDoS con el perfil de tu juego y una política Edge ACL de denegación por defecto filtra el tráfico antes de que llegue a tu VPS.
Solución de problemas
Los jugadores no pueden conectarse tras aplicar las reglas. Comprueba que el puerto y el protocolo en GAME_TCP o GAME_UDP coinciden con los del juego (sudo ss -tulpn muestra en qué puertos escucha). Muchos juegos usan varios puertos UDP, por ejemplo uno para el juego y otro para consultas.
Jugadores legítimos sufren cortes. Revisa los contadores de las reglas drop y el registro nft-drop. Si aparecen IP de jugadores, sube el límite de paquetes por segundo o de conexiones.
nft -c devuelve un error de sintaxis. Revisa llaves y comas en los sets. Si el error menciona ct count, confirma que usas el paquete de Ubuntu 24.04 (nft --version debe mostrar 1.0 o superior).
Conclusión
Tu servidor responde ahora a los SYN floods con cookies, descarta tráfico falsificado y malformado y limita a cada IP a un volumen razonable de paquetes y conexiones en los puertos del juego. Esto frena los abusos de pocos orígenes, mientras que los ataques volumétricos se filtran en la red. Como siguientes pasos, ajusta los límites con el tráfico real de tus jugadores, revisa si tu IP necesita Premium AntiDDoS con un perfil para tu juego y mantén el servidor actualizado.
