Proteger servidores RAGE MP e alt:V contra ataques DDoS

Publicado a 16 min de leitura

O RAGE MP escuta na 22005 UDP e na 22006 TCP, o alt:V na 7788. Este guia mostra passo a passo o que consegue proteger por conta própria e a partir de que ponto só ajuda uma filtragem na rede à frente do servidor.

Um servidor multijogador de GTA é um alvo agradecido para quem ataca: depende de um único endereço IP, a sua porta consta de uma lista pública de servidores e qualquer falha fica visível para todos os jogadores ao mesmo tempo. Este artigo mostra primeiro o que consegue mesmo alcançar no próprio servidor e, a seguir, com igual clareza, onde é que essas possibilidades terminam.

Se ainda não tem a certeza de que está sequer a decorrer um ataque, comece por medir: Detetar um ataque DDoS descreve o diagnóstico passo a passo. As bases técnicas estão em O que é um ataque DDoS.

Porque é que são justamente o RAGE MP e o alt:V a ser atingidos com tanta frequência

A cena de roleplay à volta do GTA V é pequena, pública e muito disputada. Um servidor vive dos seus jogadores habituais e, quando as falhas se prolongam, esses jogadores estão rapidamente noutro Discord. É isso que torna os ataques atrativos: não é preciso ter êxito durante horas, bastam alguns minutos à melhor hora de jogo, na noite de inauguração ou durante um wipe anunciado.

A isto acresce que ninguém precisa de procurar muito. Ambas as plataformas anunciam o seu servidor numa lista pública de servidores, se assim o quiser: o RAGE MP através de announce no conf.json, o alt:V através de announce e token no server.toml. Quem consta dessa lista está a publicar o endereço IP e a porta. Por isso, um servidor acabado de registar recebe muitas vezes as primeiras tentativas automatizadas de ligação logo na primeira hora, muito antes de aparecer o primeiro jogador a sério.

A terceira razão é de natureza técnica: o tráfego de jogo corre sobre UDP. O UDP não tem um estabelecimento de ligação que o remetente tenha de aguardar, pelo que o endereço de origem se falsifica com facilidade. Quem conhecer a sua porta pode bombardeá-la sem nunca receber resposta e sem mostrar o próprio endereço.

As portas de que se trata

Antes de escrever a primeira regra, convém saber para que serve cada porta. Ambas as plataformas precisam de mais do que uma.

ServiçoPortaProtocoloPara quê
RAGE MP, tráfego de jogo22005UDPligação dos clientes ao servidor de jogo
RAGE MP, ficheiros do cliente22006TCPservidor HTTP integrado, sempre a porta de jogo mais 1
alt:V, tráfego de jogo7788UDPligação dos clientes ao servidor de jogo
alt:V, ficheiros do cliente7788TCPentrega dos recursos, desde que não se utilize um CDN
SSH22TCPa sua administração, não a dos jogadores
MariaDB, Redis3306, 6379TCPpertencem a 127.0.0.1, não à internet

Há duas particularidades importantes. No RAGE MP, a porta HTTP está fixamente ligada à porta de jogo e é sempre a seguinte: se mudar a porta de jogo para 22015, a porta dos ficheiros acompanha para 22016. No alt:V, o tráfego de jogo e a entrega de ficheiros partilham o mesmo número de porta, uma vez sobre UDP e outra sobre TCP. Quem manda entregar os ficheiros do cliente através de uma rede de distribuição de conteúdos (opções useCdn e cdnUrl no server.toml) retira a parte TCP da própria linha. O tráfego de jogo sobre UDP fica intocado.

O que pode fazer por conta própria antes de gastar dinheiro

Os passos seguintes não travam um ataque volumétrico, coisa que nenhum software no servidor consegue fazer. Eliminam, no entanto, tudo o que fica abaixo disso: scans de portas, floods de ligações vindos de poucas origens, ataques à base de dados em vez do jogo e o abuso da sua própria porta de ficheiros. É a maior parte daquilo que incomoda um servidor pequeno no dia a dia e custa apenas meia hora.

Passo 1: levantamento do que está à escuta para o exterior

ss -tulnp

A coluna interessante é a do endereço local. Tudo o que ali estiver em 0.0.0.0 ou [::] é acessível a partir da internet, tudo o que estiver em 127.0.0.1 apenas localmente. Num servidor de roleplay típico aparecem depressa, além do jogo, uma base de dados, um cache, um painel web e por vezes um servidor de voz. Cada um destes serviços é uma superfície de ataque própria e nenhum deles tem de estar aberto só porque está a correr.

Passo 2: restringir a firewall às portas realmente necessárias

Num servidor RAGE MP são três aberturas: SSH, porta de jogo e porta de ficheiros. Permita sempre primeiro a sua porta SSH, caso contrário a última linha tranca-o fora do servidor:

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 22005/udp
ufw allow 22006/tcp
ufw enable

No alt:V, as duas regras do jogo são estas:

ufw allow 7788/udp
ufw allow 7788/tcp

Verifique depois com ufw status verbose se estão mesmo abertas só estas portas e repita o ss -tulnp. A configuração detalhada, incluindo IPv6 e as armadilhas habituais que o deixam trancado fora, está em Configurar a firewall UFW.

Passo 3: retirar da rede a base de dados e o cache

Na maioria dos gamemodes, o MariaDB e o Redis correm na mesma máquina que o servidor de jogo e não precisam, portanto, de endereço na internet. Para isso, a configuração do MariaDB (no Debian e no Ubuntu, /etc/mysql/mariadb.conf.d/50-server.cnf) leva esta linha:

bind-address = 127.0.0.1

E o /etc/redis/redis.conf leva estas:

bind 127.0.0.1 ::1
protected-mode yes

A seguir reinicie ambos os serviços e confirme com ss -tulnp. Um cache aberto e sem palavra-passe não é um problema de DDoS, é uma via de invasão, e é alvo de scans 24 horas por dia.

Passo 4: limitar as taxas de ligação na porta de ficheiros

A porta TCP dos ficheiros do cliente é o sítio onde um rate limit no servidor faz mesmo efeito, porque aqui existe um estabelecimento de ligação verdadeiro e, com ele, um endereço de origem em que se pode confiar razoavelmente. Bastam duas regras, aqui para o RAGE MP na porta 22006:

iptables -A INPUT -p tcp --dport 22006 --syn -m connlimit --connlimit-above 20 --connlimit-mask 32 -j DROP
iptables -A INPUT -p tcp --dport 22006 --syn -m hashlimit --hashlimit-name gtahttp --hashlimit-mode srcip --hashlimit-above 30/sec --hashlimit-burst 60 -j DROP

A primeira regra limita as ligações abertas em simultâneo por endereço de origem, a segunda limita as tentativas de ligação por segundo. Para o alt:V, coloque 7788 nos dois sítios. Três notas a este respeito: o ufw limit é aqui demasiado grosseiro e só conhece TCP, os valores numéricos deve adaptá-los ao tamanho dos seus ficheiros do cliente, e as regras só sobrevivem a um reinício com o iptables-persistent ou como entrada em /etc/ufw/before.rules.

Na porta de jogo UDP, em contrapartida, a mesma técnica adianta pouco, porque ali os remetentes são falsificados: um bloqueio por endereço de origem não atinge ninguém, a não ser por acaso um jogador verdadeiro. O que deve antes vigiar é o seguimento de ligações do kernel:

cat /proc/sys/net/netfilter/nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max

Se o primeiro valor se aproximar do segundo, o kernel descarta pacotes independentemente de pertencerem a um ataque ou a um jogador. No log do sistema aparece então nf_conntrack: table full, dropping packet.

Passo 5: usar os recursos próprios das duas plataformas

Ambos os núcleos de servidor trazem definições pensadas precisamente contra o abuso de ligações, e que de fábrica estão no valor mais permissivo. No RAGE MP isso diz respeito a três chaves no conf.json:

{
    "bind": "0.0.0.0",
    "port": 22005,
    "announce": true,
    "maxplayers": 200,
    "disallow-multiple-connections-per-ip": true,
    "limit-time-of-connections-per-ip": 1000,
    "enable-http-security": true
}

Isto é um excerto, as restantes chaves ficam inalteradas. O disallow-multiple-connections-per-ip impede várias ligações em simultâneo a partir do mesmo endereço, o limit-time-of-connections-per-ip impõe um intervalo mínimo entre duas tentativas de ligação (0 desliga o limite) e o enable-http-security ativa as verificações adicionais do servidor HTTP integrado. Confirme a unidade de tempo do valor do meio na documentação da sua versão de servidor antes de o aumentar. E conte com o facto de a primeira opção trancar fora os colegas de jogo que partilham a mesma ligação, ou seja, casas partilhadas, famílias e redes de empresa.

No alt:V, as opções correspondentes estão no server.toml:

host = '0.0.0.0'
port = 7788
players = 200
announce = true
duplicatePlayers = 4
connectionQueue = true
useEarlyAuth = true

O duplicatePlayers limita quantos jogadores com o mesmo endereço IP podem estar ligados em simultâneo. O valor predefinido é 4096, ou seja, na prática não é limite nenhum. O connectionQueue coloca as tentativas de ligação numa fila de espera em vez de as processar todas de uma só vez. O useEarlyAuth coloca um início de sessão à frente do servidor de jogo: o cliente tem de iniciar sessão antes de entrar no seu mundo de jogo, o que descarta à partida os floods de ligações mais simples. O endereço da página de início de sessão consta de earlyAuthUrl.

Passo 6: uma whitelist enquanto durar a emergência

Quando um ataque passa pela mecânica de jogo, ou seja, por tentativas de ligação em massa em vez de largura de banda pura, uma whitelist é a medida mais eficaz a curto prazo. No alt:V, para funcionar em modo fechado basta uma password no server.toml. Em código, a forma mais simples é esta, aqui para o RAGE MP:

const whitelist = new Set(['JogadorUm', 'JogadorDois']);

mp.events.add('playerJoin', (player) => {
    if (!whitelist.has(player.name)) {
        player.kick('O servidor está encerrado de momento.');
    }
});

E a mesma lógica para o alt:V:

import * as alt from 'alt-server';

const whitelist = new Set(['JogadorUm', 'JogadorDois']);

alt.on('playerConnect', (player) => {
    if (!whitelist.has(player.name)) {
        player.kick('O servidor está encerrado de momento.');
    }
});

Ambos os exemplos são propositadamente simples e têm um limite claro: o nome de exibição não é um identificador forte. Quem mantiver uma whitelist de forma permanente faz melhor em verificar o identificador do início de sessão prévio ou uma gestão de contas própria. Mas sobretudo vale isto: um kick só acontece depois de a ligação ter chegado ao servidor. Contra pacotes que já estão a encher a linha, não serve de nada.

Passo 7: a entrada na lista de servidores e a higiene do endereço IP

Desligar a entrada na lista de servidores (announce em false) parece uma solução rápida e quase nunca é. Quem já tem o seu endereço IP continua a chegar até si, e os seus jogadores deixam de o encontrar. O passo só faz sentido em conjunto com uma mudança de endereço IP, porque só então o atacante perde o seu alvo.

A longo prazo rende mais a arrumação nos sítios por onde o endereço acaba por se saber: manter o site e o fórum noutra máquina, apagar registos DNS antigos (também mail, ftp e nomes de teste do início do projeto), não correr bots de Discord nem indicadores de estado a partir do servidor de jogo e separar o servidor de voz. Ainda assim, o endereço de um servidor de jogo não se consegue esconder por completo: o tráfego de jogo sobre UDP tem de chegar diretamente até si, e uma rede de distribuição de conteúdos colocada à frente dos sites não muda isso. O que ajuda aqui não é o disfarce, é um endereço que tenha uma filtragem por trás.

Passo 8: recolher valores medidos antes de a coisa ficar séria

Na hora da verdade conta aquilo que consegue documentar. Prepare com antecedência os comandos com que regista, em segundos, a taxa de pacotes de entrada e a situação das ligações:

IF=$(ip -o route get 1.1.1.1 | awk '{print $5}')
A=$(cat /sys/class/net/$IF/statistics/rx_packets) || exit 1; sleep 1; B=$(cat /sys/class/net/$IF/statistics/rx_packets); echo "$((B-A)) pacotes/s de entrada em $IF"
ss -s

Anote estes valores uma vez em funcionamento normal, à hora de maior afluência, porque sem um valor de comparação qualquer número medido durante um ataque não vale nada. Se o seu servidor de jogo correr como serviço systemd, junte também journalctl -u <nome-do-serviço> -n 200: os floods de ligações deixam ali, normalmente, um rasto claro. Há uma limitação que convém conhecer: no servidor só mede aquilo que passou. Se houver uma filtragem à frente, o número fiável está no gráfico de tráfego da área de cliente e não em /proc.

Onde estas medidas deixam de chegar

Qualquer regra no servidor só faz efeito depois de o pacote ter chegado. É esta a frase decisiva. Uma firewall decide sobre pacotes que já passaram pela sua linha, e é precisamente essa linha o alvo de um ataque volumétrico.

As ordens de grandeza: um servidor isolado está normalmente ligado a 1 Gbit/s. Com os pacotes mais pequenos, isso corresponde a cerca de 1,5 milhões de pacotes por segundo, fisicamente não passa mais. Para entupir esta linha ninguém precisa de um ataque recorde, bastam 2 a 5 Gbit/s. Para comparar, um ataque realmente medido na rede de Frankfurt da KernelHost: mais de 473,4 Gbit/s e mais de 41,5 milhões de pacotes por segundo contra um único serviço. Isso é cerca de 470 vezes uma linha de gigabit, e mesmo uma ligação de 10 Gbit/s continua a estar 47 vezes abaixo disso.

Se a linha estiver cheia, já é o router à frente que descarta, e sem olhar ao pacote em concreto. Os seus jogadores ficam então na mesma fila de espera que o ataque. Nenhum iptables, nenhum plugin e nenhum CPU mais forte mudam isso, porque o estrangulamento está à frente do servidor. Acresce que, nos floods UDP, os endereços de origem são falsificados: simplesmente não há ninguém que faça sentido bloquear.

Por isso, só é eficaz uma filtragem que fique na rede à frente da sua linha e que aí tenha capacidade suficiente para o ataque não a saturar.

O que a KernelHost coloca do outro lado

A proteção permanente que já corre em todos os servidores

Na KernelHost (KernelHost GmbH, com sede em Viena, na Áustria), em todos os servidores está permanentemente ativa uma proteção DDoS de dois níveis, sem encomenda, sem configuração e sem sobretaxa:

  • Nível 1: rede global de scrubbing com 17 Tbps de capacidade de mitigação. Os ataques volumétricos são travados perto da sua origem, antes sequer de chegarem ao datacenter.
  • Nível 2: filtragem Arbor em tempo real com 3,2 Tbps. Está instalada no local, no datacenter maincubes em Frankfurt am Main (Alemanha), e faz o trabalho fino mesmo à frente do seu servidor, pacote a pacote.

Igualmente importante é aquilo que não acontece: não se recorre a null-routing. O seu endereço IP mantém-se na rede durante um ataque, caem apenas os pacotes nocivos. Para um servidor de roleplay a diferença é considerável, porque um endereço colocado em null-routing é, para os seus jogadores, indistinguível de um ataque bem-sucedido. Se durante um incidente deixar de conseguir entrar por SSH, chega na mesma ao sistema através da consola VNC na área de cliente, que funciona independentemente da ligação de rede do servidor.

Advanced DDoS Protection para projetos atacados de forma continuada

Alguns projetos não são atingidos uma única vez, mas ao longo de semanas. Para esse caso existe a Advanced DDoS Protection a partir de 50,00 € por mês, em PrePaid e sem prazo mínimo, sem período de aviso prévio, sem contrato e sem taxa de instalação. Estão incluídos:

  • um IP de proteção dedicado do núcleo de Frankfurt, para o qual o seu servidor é comutado sem qualquer alteração do seu lado,
  • regras de proteção que gere por si próprio, por porta e por protocolo, diretamente na área de cliente,
  • alterações que fazem efeito em tempo real, sem ticket e sem tempo de espera,
  • um perfil de proteção adequado a cada jogo, escolhido entre mais de 40 perfis para jogos, serviços e protocolos, entre eles o RageMP e o alt:V, além de perfis genéricos para aplicações TCP e UDP próprias.

A diferença prática está no controlo: decide por si próprio qual o perfil que corre na 22005 UDP e qual a regra que vale para a 22006 TCP, mesmo a meio de um ataque.

Os dois níveis em comparação

CaracterísticaProteção permanente incluídaAdvanced DDoS Protection
Ativaçãoativa de fábrica, nada a encomendaradicionável, IP de proteção logo após a encomenda
Capacidade17 Tbps de scrubbing global mais 3,2 Tbps de filtragem Arbor em tempo real em Frankfurt am Maina mesma infraestrutura de filtragem, mais um IP de proteção dedicado do núcleo de Frankfurt
Conjunto de regrasmantido pela KernelHost, automaticamentealém disso, gerível por si, por porta e por protocolo na área de cliente
Perfis de proteçãoautomáticos, otimizados para jogosescolhidos por si, mais de 40 perfis, incluindo RageMP e alt:V
Efeito das alteraçõesnão são necessáriasem tempo real, sem ticket
Null-routing durante um ataquenãonão
Custosem sobretaxa em todos os pacotes de servidora partir de 50,00 € por mês, PrePaid sem prazo mínimo
Indicado paratodos os projetosprojetos atacados de forma continuada e dirigida

Erros frequentes e respetivas soluções

Todas as portas abertas, porque de outra forma há sempre alguma coisa que não funciona: isto é quase sempre um diagnóstico errado. Anote com o ss -tulnp que serviço precisa de que porta e abra exatamente essas. Se a seguir faltar alguma coisa, a causa está normalmente num serviço que, de qualquer forma, só está ligado localmente.

Bloquear os endereços IP dos atacantes: num flood UDP os remetentes são falsificados. Com isso bloqueia endereços de terceiros sem culpa e, no pior dos casos, os seus próprios jogadores. Só faz sentido em ligações TCP com estabelecimento completo, ou seja, na porta de ficheiros.

Apenas colocar announce em false: o servidor desaparece da lista, mas o endereço IP continua o mesmo. Um ataque em curso prossegue sem alteração, só que os seus jogadores deixam de encontrar o servidor. Sem mudança de endereço, o passo não adianta nada.

Rate limit na porta de jogo UDP: as redes móveis e as ligações de empresa agregam muitos jogadores atrás de um único endereço. Um limite por endereço de origem expulsa ali jogadores verdadeiros, enquanto os remetentes falsificados do flood ficam intocados.

Mais CPU e mais RAM como resposta a um DDoS: ambos ajudam contra um gamemode sobrecarregado, não contra uma linha cheia. O estrangulamento está à frente do servidor e, aí, hardware mais forte não muda nada.

Reiniciar a meio do ataque: apaga todos os contadores de que precisaria para uma comunicação fiável, e o ataque prossegue depois na mesma. Recolha primeiro os valores medidos e só depois atue.

Base de dados aberta na internet porque o painel web corre noutra máquina: faça a ligação através de um túnel SSH ou de uma rede privada. Se isso não for possível, restrinja o acesso pelo menos ao único endereço de origem que dele precisa mesmo.

Se está a acontecer neste momento

Recolha primeiro os valores medidos do passo 8, para que a sua comunicação seja fiável: momento com fuso horário, endereço IP e porta afetados, taxa de pacotes medida com indicação do sentido. Depois abra um ticket de suporte. Com um ataque em curso, pode ainda falar connosco pelo chat de emergência do WhatsApp, através do +43 650 8209883. A visão geral independente do fornecedor sobre os passos seguintes está em Proteger o servidor contra ataques DDoS.

Perguntas frequentes

De que portas precisam realmente o RAGE MP e o alt:V?
O RAGE MP usa a 22005 UDP para o tráfego de jogo e a 22006 TCP para os ficheiros do cliente, sendo a porta HTTP sempre a porta de jogo mais 1. O alt:V usa a 7788 para as duas coisas, uma vez sobre UDP e outra sobre TCP, desde que os recursos não sejam entregues através de um CDN. Tudo o resto, em especial a base de dados e o cache, pertence a 127.0.0.1 e não à internet.
O meu servidor está a ser atacado neste momento. O que ajuda já?
Se a linha estiver cheia, no próprio servidor pouco. Registe primeiro a taxa de pacotes de entrada e a situação das ligações com ss -s, anote o momento com o fuso horário, o endereço IP e a porta afetados, e comunique o incidente com esses valores. Se o ataque passar pela mecânica de jogo, ou seja, por tentativas de ligação em massa, ajuda a curto prazo uma whitelist ou uma palavra-passe no servidor.
Vale a pena bloquear os endereços IP dos atacantes?
Nos floods UDP não, porque os endereços de origem são falsificados. Com isso bloqueia terceiros sem culpa e, no pior dos casos, os seus próprios jogadores. Os bloqueios e os rate limits só fazem sentido onde a ligação é estabelecida por completo, ou seja, na porta TCP dos ficheiros do cliente.
Ajuda retirar o servidor da lista de servidores?
Só em conjunto com uma mudança de endereço IP. Colocar announce em false remove a entrada, mas o endereço continua o mesmo e quem já o tem continua a chegar até si. Os seus jogadores deixam então de encontrar o servidor e o ataque prossegue sem alteração.
Posso esconder o endereço IP do meu gameserver atrás de um CDN?
Não. O tráfego de jogo sobre UDP tem de chegar diretamente ao servidor, e uma rede de distribuição de conteúdos só consegue colocar-se à frente de sites e ficheiros. Eficaz é antes um endereço que tenha uma filtragem por trás, por exemplo um IP de proteção dedicado. Continua, ainda assim, a fazer sentido manter o site, o fórum, o bot do Discord e o servidor de voz noutra máquina.
Porque é que uma firewall no servidor não chega contra um DDoS?
Porque qualquer regra só faz efeito depois de o pacote ter chegado. Uma linha de 1 Gbit/s fica cheia, com os pacotes mais pequenos, a partir de cerca de 1,5 milhões de pacotes por segundo, e bastam 2 a 5 Gbit/s para a entupir. Se a linha estiver saturada, o router à frente descarta também os pacotes dos seus jogadores.
Já não consigo entrar no servidor por SSH. Como chego até ele?
Através da consola VNC na área de cliente. Funciona independentemente da ligação de rede do servidor e continua a funcionar quando a linha está saturada e já não se estabelece qualquer ligação SSH.
Quanto custa a proteção DDoS na KernelHost?
A proteção permanente de dois níveis está incluída em todos os pacotes de servidor sem sobretaxa: 17 Tbps de capacidade de mitigação na rede global de scrubbing e 3,2 Tbps de filtragem Arbor em tempo real em Frankfurt am Main. Para projetos atacados de forma continuada existe ainda a Advanced DDoS Protection, com IP de proteção dedicado e regras geridas por si, a partir de 50,00 € por mês, PrePaid sem prazo mínimo.

RAGE MP alt:V Multijogador GTA Proteção DDoS para gameservers Flood UDP Firewall Filtragem em tempo real Advanced DDoS Protection