Proteger o servidor Garry's Mod contra ataques DDoS

Publicado a 28 min de leitura

No Garry's Mod, o tráfego de jogo e a consulta de servidor correm pela mesma porta 27015. Que regras no servidor fazem mesmo efeito, como proteger o RCON e os eventos de rede em Lua, e a partir de que dimensão de ataque só ajuda a filtragem na rede à frente.

Um servidor Garry's Mod que desaparece durante três minutos às oito da noite e volta logo a seguir raramente tem um problema de hardware. Na esmagadora maioria dos casos está a decorrer um ataque, e decorre precisamente quando há mais jogadores ligados. A proteção DDoS para Garry's Mod começa, por isso, por uma questão simples: saber que pacotes podem sequer chegar ao seu servidor. Este artigo mostra, por esta ordem, o que pode proteger por conta própria nos próximos dez minutos e sem gastar um cêntimo, onde estas medidas acabam do ponto de vista físico, e o que tem de acontecer depois disso na rede à frente do servidor.

Todas as indicações se referem a um servidor srcds em Debian 12, Debian 13, Ubuntu 22.04 LTS ou Ubuntu 24.04 LTS. O ficheiro de configuração está em garrysmod/cfg/server.cfg, os comandos estão escritos para root; como utilizador normal, anteponha sudo. Refere-se sempre à operação num servidor root ou dedicado próprio, não a um slot alugado a um fornecedor de gameservers.

Se o ataque estiver a decorrer neste momento: não altere agora nada na server.cfg e não reinicie o srcds. Guarde primeiro os valores medidos (secção 9), porque depois do ataque desaparecem. Um reinício custa-lhe os contadores e devolve o servidor à mesma enxurrada.

Porque é que um servidor Garry's Mod precisa de proteção DDoS

Um servidor Garry's Mod publica por iniciativa própria o seu endereço IP e a sua porta. Isso não é um descuido, é um requisito: quem não consta da lista de servidores não recebe jogadores novos. A entrada surge porque o servidor se regista no master server da Steam e responde depois a todas as consultas A2S que chegam do exterior. A pergunta nunca é, portanto, se um atacante encontra o seu endereço, mas apenas o que acontece quando dispara contra ele.

A isto junta-se o tipo de comunidades. O Garry's Mod não é jogado sobretudo em rondas, mas em mundos permanentes: uma comunidade DarkRP mantém contas de jogador, propriedade, empregos e progresso durante meses numa base de dados. Uma falha na sexta-feira à noite custa, por isso, mais do que uma partida perdida: custa jogadores habituais. É precisamente por isso que comunidades concorrentes, jogadores banidos e server booters comprados (serviços que, por poucos euros por mês, desencadeiam ataques contra um endereço qualquer) são os três motivos mais frequentes. O atacante não precisa, para isso, nem de competência nem de dinheiro digno de nota.

Do lado técnico juntam-se três particularidades. O tráfego de jogo corre sobre UDP, e o UDP não tem um estabelecimento de ligação que se possa exigir: os endereços de origem falsificam-se com facilidade. A consulta de servidor está na mesma porta que o jogo, pelo que um bloqueio grosseiro atinge sempre as duas coisas. E por cima de tudo está o Lua: cada addon do Workshop traz código próprio para dentro do mesmo processo, e basta um único evento de rede sem proteção para que um só cliente trave o servidor sem qualquer largura de banda. O que é, no fundo, um ataque DDoS fica explicado no artigo O que é um ataque DDoS?.

As portas que realmente contam no Garry's Mod

Por predefinição, um servidor Garry's Mod arranca na porta 27015, em UDP para o jogo com a respetiva consulta de servidor e em TCP para o RCON. O número altera-se no arranque com -port; com várias instâncias, vai-se subindo (27016, 27017 e por aí adiante). Uma linha de arranque típica é esta:

./srcds_run -game garrysmod -console \
  -port 27015 \
  +maxplayers 64 \
  +gamemode darkrp \
  +map rp_downtown_v4c_v2 \
  +sv_setsteamaccount O_SEU_TOKEN_GSLT \
  +host_workshop_collection 123456789 \
  -authkey A_SUA_CHAVE_STEAM_WEB_API

Daqui resulta toda a superfície de ataque. A tabela seguinte é a base de todas as regras de firewall mais abaixo:

Porta e protocolo Para quê Alterável através de Pertence à rede aberta
27015/UDP Tráfego de jogo e consulta A2S na mesma porta -port sim, é a única porta que tem mesmo de estar aberta
27015/TCP RCON, o protocolo Source RCON -port (o mesmo número do jogo) não, apenas para o seu próprio endereço
27005/UDP Porta do cliente, parte do jogador -clientport não, no servidor não é precisa qualquer regra
27020/UDP SourceTV +tv_port só se transmitir de facto
26901/UDP Registo no master server da Steam de saída não, não é precisa regra de entrada
80/TCP e 443/TCP FastDL através de sv_downloadurl, caso o servidor web esteja no mesmo host servidor web só se o FastDL estiver ali (melhor separar)
3306/TCP MySQL para o DarkRP e os dados dos jogadores (através do módulo mysqloo) bind-address não, exclusivamente 127.0.0.1
22/TCP Acesso SSH sshd_config sim, mas restrito

Destas oito entradas, exatamente uma pertence sem restrições à rede aberta: a 27015/UDP. Tudo o resto ou fica limitado ao seu próprio endereço, ou ligado a 127.0.0.1, ou nem sequer chega a ser iniciado. O erro de raciocínio mais caro nesta matéria é supor que o Garry's Mod tem uma porta de consulta separada que se possa simplesmente fechar. Não tem.

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

Esta secção é a mais longa, e isso é intencional. Um servidor Garry's Mod bem configurado aguenta ataques pequenos e médios pelos seus próprios meios, independentemente de onde esteja alojado. Nada disto custa dinheiro, e a maior parte fica feita num quarto de hora.

1. Levantamento: o que está sequer à escuta

Antes de escrever uma única regra, veja o que o seu servidor oferece para o exterior. Não adivinhe, verifique:

ss -lntup

A coluna interessante é a do endereço local. 0.0.0.0:27015 e [::]:27015 significam "acessível a partir de toda a internet", 127.0.0.1:3306 significa "apenas local" e não precisa de regra de firewall. Num servidor DarkRP que foi crescendo ao longo do tempo, aparecem ali quase sempre mais serviços do que o esperado: MySQL, um servidor web para o FastDL, um painel, um bot de Discord, um segundo servidor de testes na 27016 e um serviço de voz há muito esquecido. A perspetiva do atacante obtém-se com um scan de portas a partir de fora:

nmap -Pn -sU -sT -p- --min-rate 1000 IP.DO.SEU.SERVIDOR

2. Deixar abertas apenas as portas de que o srcds precisa mesmo

Para o Garry's Mod basta uma única abertura para o exterior, mais o SSH e o acesso RCON restrito. Com o UFW fica assim, e exatamente por esta ordem, para que não se tranque a si próprio fora do servidor:

ufw allow 22/tcp comment 'SSH'
ufw allow 27015/udp comment 'Garrys Mod jogo e A2S'
ufw allow from 203.0.113.10 to any port 27015 proto tcp comment 'RCON'
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose

Substitua 203.0.113.10 pelo seu próprio endereço. O SourceTV na 27020/UDP só deve ser aberto se transmitir mesmo. As instruções completas, incluindo a via de regresso, estão em Configurar a firewall UFW sem se trancar fora do servidor. Se mesmo assim acontecer: os servidores root KVM e os servidores dedicados da KernelHost não têm IPMI nem iDRAC, e regressa ao servidor através da consola VNC na área de cliente. Essa consola não depende da stack de rede do sistema convidado, pelo que nenhuma regra de firewall dentro do sistema convidado a consegue bloquear.

A base de dados não pertence, em caso algum, à rede aberta. Verifique em /etc/mysql/mariadb.conf.d/50-server.cnf que ali consta:

bind-address = 127.0.0.1

3. Limitar a consulta A2S sem cair da lista de servidores

É aqui que está o erro que custa mais servidores Garry's Mod. Como o tráfego de jogo e a consulta de servidor ocupam a mesma porta, um bloqueio genérico ou um rate limit demasiado apertado na 27015/UDP expulsa os próprios jogadores e termina o ataque por conta do atacante. O ponto de partida correto é distinguir entre pacotes de consulta e pacotes de jogo.

O motor traz três variáveis de consola para isso, e elas ficam na server.cfg. Os valores predefinidos são conservadores, mas estão definidos:

sv_max_queries_sec 3
sv_max_queries_sec_global 60
sv_max_queries_window 30

sv_max_queries_sec limita as consultas respondidas por endereço de origem (predefinição 3 por segundo), sv_max_queries_sec_global impõe um teto à soma de todos os endereços (predefinição 60 por segundo) e sv_max_queries_window fixa a janela de média (predefinição 30 segundos). Estes valores protegem o CPU de gerar respostas inúteis. Não impedem que os pacotes cheguem, e quem apertar demasiado o valor global desaparece da lista de servidores durante o ataque, porque também as consultas dos sites de listagens ficam sem resposta.

Um nível abaixo, o tráfego de consultas pode ser separado com rigor. Todos os pacotes sem ligação do motor Source começam com quatro bytes preenchidos (0xffffffff), enquanto o tráfego dos jogadores já ligados não leva esse cabeçalho. É exatamente sobre isso que se pode aplicar um rate limit por endereço de origem com o nftables:

table inet gmod {
    chain input {
        type filter hook input priority -10; policy accept;
        udp dport 27015 @th,64,32 0xffffffff \
            meter a2sflood { ip saddr limit rate over 8/second burst 20 packets } drop
    }
}

O ficheiro carrega-se com nft -f. A prioridade -10 faz com que a regra atue antes da cadeia de filtragem do UFW, e @th,64,32 lê os primeiros quatro bytes a seguir ao cabeçalho UDP. Com o iptables clássico, uma comparação u32 faz exatamente o mesmo:

iptables -A INPUT -p udp --dport 27015 \
  -m u32 --u32 "0>>22&0x3C@8=0xFFFFFFFF" \
  -m hashlimit --hashlimit-name gmod_a2s --hashlimit-mode srcip \
  --hashlimit-above 8/sec --hashlimit-burst 20 -j DROP

Um pormenor que quase todos os guias na internet omitem: não é só a consulta de servidor que é sem ligação, o estabelecimento da ligação também o é. Um jogador que entra envia vários pacotes com o mesmo cabeçalho antes de estar dentro do jogo. Um limite demasiado apertado tranca, por isso, os jogadores novos do lado de fora, mesmo com o servidor acessível. Comece com margem (8 a 15 pacotes por segundo e por endereço) e só aperte o limite depois de ter medido uma semana de funcionamento normal.

4. Proteger o RCON ou desligá-lo por completo

Nos servidores Source, o RCON é um alvo apetecido, e por três razões ao mesmo tempo. Primeiro, está no mesmo número de porta que o jogo, só que em TCP, pelo que se encontra sem procurar. Segundo, o protocolo Source RCON transmite a palavra-passe em texto simples, sem TLS e sem troca de chaves: quem lê o tráfego fica com ela. Terceiro, o ganho é máximo, porque quem tem RCON pode mudar o mapa, banir todos os jogadores, alterar a configuração e parar o servidor. Um atacante que tome o RCON já nem precisa de largura de banda.

Nunca deixe rcon_password vazia nem escolhida a olho, um valor saído de openssl rand -base64 32 chega. Contra tentativas de início de sessão, o motor traz um travão:

rcon_password "AQUI_UMA_PALAVRA_PASSE_LONGA_ALEATORIA"
sv_rcon_minfailures 3
sv_rcon_maxfailures 5
sv_rcon_minfailuretime 30
sv_rcon_banpenalty 1440

Com isto, um endereço fica bloqueado durante um dia após três tentativas falhadas em 30 segundos. Dois avisos a este respeito. Primeiro, é exatamente este mecanismo que também tranca do lado de fora o seu próprio painel de administração, se ali estiver guardada uma palavra-passe antiga: aquilo que os operadores comunicam como "o RCON deixou de funcionar de repente" é, na maioria das vezes, o bloqueio que eles próprios provocaram. Segundo, a restrição na firewall do passo 2 continua a ser mais eficaz, porque nem sequer deixa a tentativa chegar à aplicação. Quem só precisa do RCON de vez em quando deixa a porta fechada e trabalha através de um encaminhamento de portas por SSH:

ssh -N -L 27015:127.0.0.1:27015 root@IP.DO.SEU.SERVIDOR

5. Limitar as mensagens de rede em Lua, a falha caseira mais frequente

Uma parte considerável das falhas de Garry's Mod comunicadas como DDoS não o é. São sobrecargas de Lua, desencadeadas por um único cliente ligado com uns poucos kilobits por segundo. A razão está na construção da biblioteca net: assim que um addon regista um evento de rede com util.AddNetworkString e fica à escuta com net.Receive, qualquer cliente pode disparar esse evento em ciclo. Sem um limite próprio, o servidor executa cada uma das mensagens. A Facepunch documentou isto várias vezes nos seus próprios relatórios de erro e não previu qualquer solução no motor: o limite é expressamente tarefa do autor do addon.

Verifique por isso, em cada addon próprio e em cada addon comprado, três coisas: um limite máximo por jogador e por segundo, uma verificação do comprimento da mensagem, e que o jogador seja determinado do lado do servidor a partir do segundo parâmetro em vez do conteúdo da mensagem. Um padrão sólido é este:

util.AddNetworkString("khrp_buy")

local budget = {}

net.Receive("khrp_buy", function(len, ply)
    if not IsValid(ply) then return end
    if len > 256 then return end

    local now = CurTime()
    local b = budget[ply]

    if not b or now - b.start >= 1 then
        b = { start = now, count = 0 }
        budget[ply] = b
    end

    b.count = b.count + 1
    if b.count > 10 then return end

    KHRP.HandleBuy(ply, net.ReadString())
end)

hook.Add("PlayerDisconnected", "khrp_budget_cleanup", function(ply)
    budget[ply] = nil
end)

A isto juntam-se duas linhas na server.cfg. No Garry's Mod, sv_allowcslua está por predefinição em 1 e permite que os clientes executem código próprio com lua_run_cl e lua_openscript_cl: num servidor público, o valor pertence a 0. E sv_kickerrornum desliga os clientes que gerem mais erros do lado do cliente do que o número indicado (predefinição 0, ou seja, desativado):

sv_allowcslua 0
sv_kickerrornum 25

6. Separar do servidor de jogo os conteúdos do Workshop e o FastDL

No Garry's Mod, os addons do Workshop não são um tema de contorno, são a norma: uma comunidade DarkRP liga a sua coleção com +host_workshop_collection e os clientes descarregam esses conteúdos diretamente da Steam. Isso não pesa na sua linha. A chave de -authkey é uma chave Steam Web API e deve ser tratada como uma palavra-passe: no script de arranque, não num repositório público e não num canal de Discord.

Quem custa largura de banda é o segundo caminho. Tudo o que não venha do Workshop (mapas próprios, sons, materiais) passa pelo canal de download. Sem sv_downloadurl, esse canal corre pela própria porta de jogo e concorre diretamente com o tráfego de jogo. Com o FastDL, corre por HTTP. Se esse servidor web estiver no mesmo host e no mesmo endereço IP, os dois partilham a mesma linha: uma onda de entradas ou um ataque à 80/TCP atinge então também o jogo. Estes valores fazem sentido:

sv_downloadurl "https://fastdl.seu-dominio.pt/garrysmod/"
sv_allowdownload 1
sv_allowupload 0
net_maxfilesize 64

sv_allowupload 0 retira aos clientes a possibilidade de enviarem ficheiros próprios para o servidor e fecha assim um caminho que não é preciso nem é controlado. net_maxfilesize limita em megabytes o tamanho dos ficheiros transferidos pelo canal de jogo. Coloque o FastDL, se possível, noutro host ou por trás de um nome próprio, para que a carga não fique no mesmo endereço que a porta de jogo.

7. Travar a enxurrada de entradas e o esgotamento de lugares

O esgotamento de lugares é um ataque que não precisa de largura de banda: o atacante ocupa todos os lugares livres com ligações automatizadas, de modo que os jogadores reais veem a casa cheia. No Garry's Mod acresce que cada entrada custa trabalho ao servidor, porque a lista de recursos e o gamemode são negociados muito antes de o jogador estar dentro do jogo.

Contra isso resultam quatro coisas. Primeira, um limite máximo realista: pôr +maxplayers mais alto do que o seu gamemode aguenta só aumenta a superfície de ataque. Segunda, sv_timeout, que define ao fim de quantos segundos sem mensagem um cliente é desligado (120 nas configurações mais divulgadas): quem quiser livrar-se mais depressa de meias ligações penduradas baixa o valor. Terceira, o rate limit sobre os pacotes sem ligação do passo 3, porque o estabelecimento da ligação passa justamente por aí. Quarta, para grupos fechados, uma palavra-passe de servidor:

sv_password "grupo_habitual_2026"
sv_timeout 90
sv_filterban 1
sv_region 3

O Garry's Mod não traz uma whitelist a sério, essa chega através de extensões como o ULX ou de uma verificação própria no hook CheckPassword. E uma coisa tem de ficar clara: uma whitelist protege a sua lógica de jogo, não a sua linha. Um atacante que inunda o seu servidor nem sequer quer entrar. Os pacotes dele são recusados, mas mesmo assim chegaram, e é precisamente esse o ponto.

8. Aliviar o kernel: seguimento de ligações e buffer de receção

Este passo explica falhas que parecem um ataque de volume sem o serem. O kernel cria entradas no seguimento de ligações (conntrack) para o tráfego UDP e, com endereços de origem falsificados, cada endereço significa uma entrada nova. Quando a tabela enche, o kernel descarta pacotes sem distinguir: o ataque e os seus jogadores caem em conjunto, e no log do sistema aparece "nf_conntrack: table full". O estado atual e o limite máximo são mostrados por:

sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max

O passo mais eficaz é não deixar sequer que o tráfego de jogo seja seguido, porque o motor gere as suas próprias sessões:

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
    }
}

Com o iptables, o equivalente é iptables -t raw -A PREROUTING -p udp --dport 27015 -j NOTRACK e a mesma linha para OUTPUT com --sport. A porta passa depois a precisar de uma abertura explícita, porque sem seguimento deixa de atuar qualquer regra que verifique um estado existente. Se, além disso, os pacotes chegarem mais depressa do que o srcds os levanta, o buffer de receção transborda, e para os jogadores isso parece perda de pacotes com a linha livre:

net.core.rmem_max = 16777216
net.core.rmem_default = 1048576
net.core.netdev_max_backlog = 16384

Estas linhas pertencem a um ficheiro em /etc/sysctl.d/ e ficam ativas com sysctl --system. Se são mesmo necessárias, é o próprio kernel que o revela: se UdpRcvbufErrors subir em nstat -az, então fazem efeito. Se o contador ficar a zero, o ajuste não muda nada. Isto é reserva, não é proteção.

9. Guardar valores medidos enquanto tudo funciona normalmente

O passo mais importante é aquele que quase ninguém dá com antecedência: criar uma base de comparação. Sem um valor normal, depois de um incidente não consegue dizer se 40 000 pacotes por segundo foram muitos ou se era simplesmente sábado à noite. Calcule uma vez o valor normal do seu servidor: 64 jogadores com cl_cmdrate 66 geram cerca de 4200 pacotes de entrada por segundo, e tudo o que esteja claramente acima disso exige explicação. Com apt-get install -y vnstat sysstat, a medição fica sempre a correr. Durante um incidente bastam quatro comandos:

sar -n DEV 1 10
ip -s link show eth0
nstat -az | grep -i udp
tcpdump -ni eth0 -c 200 "udp port 27015 and udp[8:4] = 0xffffffff"

O primeiro mostra pacotes e bytes por segundo, o segundo os contadores de descarte da interface, o terceiro os contadores de erro UDP do kernel. A quarta linha mostra exclusivamente os pacotes sem ligação, ou seja, precisamente a classe que uma enxurrada de consultas explora: se o contador disparar em segundos enquanto quase ninguém está ligado, já tem a sua resposta. Limite sempre o tcpdump com -c, porque uma captura a plena carga sobrecarrega ainda mais um servidor que já está sobrecarregado. Como interpretar os valores está em Detetar um ataque DDoS no servidor.

O que é a falha de reflexão A2S e se ela ainda me afeta

A reflexão A2S é um ataque em que o seu servidor não é o alvo, mas sim a ferramenta. O atacante envia uma pequena consulta com o endereço de origem falsificado a milhares de gameservers, e as respostas deles, bastante maiores, convergem todas na verdadeira vítima. Historicamente, um pedido A2S_INFO tinha 25 bytes (4 bytes 0xFFFFFFFF, 1 byte 0x54, mais 20 bytes para a cadeia de caracteres "Source Engine Query"), enquanto a resposta tinha várias centenas de bytes. O US-CERT lista o protocolo da Steam entre os ataques de amplificação com um fator de 5,5, o que significa: um gigabit do lado do atacante transforma-se em 5,5 gigabits do lado da vítima.

A Valve fechou esta falha a partir de novembro de 2020, e por dois caminhos. Desde então, os pacotes de consulta sem ligação têm de ser preenchidos pelo remetente até aos 1200 bytes, com o que o pedido passa a ser maior do que a resposta e o fator de amplificação cai abaixo de 1. Durante a transição, os operadores podiam forçar antecipadamente o comportamento mais restrito com a variável de ambiente STEAM_GAMESERVER_MIN_CONNECTIONLESS_PACKET_SIZE=1200. Além disso, em A2S_PLAYER e A2S_RULES o servidor deixou de responder logo com dados e passou a responder com um challenge (S2C_CHALLENGE), que quem pergunta tem de devolver num segundo pedido. Quem falsifica o endereço de origem nunca chega a ver esse challenge.

Daqui resultam duas coisas para si. Mantenha o binário do servidor atualizado, porque a proteção está na base Steam Gameserver e não na sua configuração. E não confunda reflexão com uma enxurrada de consultas contra si próprio: contra a segunda forma só ajuda o rate limit do passo 3 e, para além disso, a filtragem na rede à frente do servidor.

Onde estas medidas acabam: largura de banda e taxa de pacotes

Agora a parte que nenhum ficheiro de configuração resolve. Tudo o que ficou descrito até aqui corre no seu servidor, ou seja, no fim da linha. Uma regra de firewall decide sobre um pacote que já passou pelo cabo. Pode descartá-lo, mas não pode fazer com que ele não tenha sido enviado.

Faça as contas connosco. Um gameserver típico está ligado a 1 Gbit/s, o que corresponde a 125 megabytes por segundo, e a linha fica cheia assim que alguém enviar mais do que isso. A segunda grandeza costuma chegar primeiro ao limite: com pacotes do tamanho mínimo de 64 bytes, cabem em 1 Gbit/s cerca de 1,49 milhões de pacotes por segundo e em 10 Gbit/s cerca de 14,88 milhões. Um kernel de servidor normal processa, consoante o CPU e a placa de rede, algumas centenas de milhares deles antes de começar a descartar. Um ataque que nem sequer enche um terço da sua linha pode, portanto, deixar o seu servidor inoperacional, porque o tempo de processamento se gasta a descartar. Quem opera servidores vive isto como "a utilização nem sequer estava alta e mesmo assim toda a gente teve picos de lag".

Indicador Valor
Pedido A2S_INFO, tamanho histórico 25 bytes
Fator de amplificação do protocolo da Steam (US-CERT) 5,5
Tamanho mínimo dos pacotes de consulta sem ligação desde 2020 1200 bytes
Tráfego normal: 64 jogadores com cmdrate 66 cerca de 4200 pacotes de entrada por segundo
1 Gbit/s com pacotes de 64 bytes cerca de 1,49 milhões de pacotes por segundo (125 megabytes por segundo)
10 Gbit/s com pacotes de 64 bytes cerca de 14,88 milhões de pacotes por segundo
Dimensão típica de ataque contra gameservers de comunidade 5 a 50 Gbit/s
Pico medido em servidores da KernelHost 473,4 Gbit/s com 41,5 milhões de pacotes por segundo

Para dar uma ideia das ordens de grandeza que ocorrem na realidade: em servidores da KernelHost foram filtrados, entre outros, um UDP flood com mais de 112,2 Gbit/s e mais de 8,7 milhões de pacotes por segundo contra um gameserver, bem como um ataque multivetor com mais de 473,4 Gbit/s e mais de 41,5 milhões de pacotes por segundo contra um servidor de voz. 473,4 Gbit/s são cerca de 470 vezes uma ligação de 1 Gbit/s e ainda assim cerca de 47 vezes uma ligação de 10 Gbit/s. Para isso não existe nenhuma definição local. Os ataques volumétricos têm de terminar na rede à frente do servidor.

O que a KernelHost põe do outro lado

A proteção permanente incluída em todos os pacotes de servidor

A proteção DDoS da KernelHost está montada em dois níveis e permanentemente ativa, sem que tenha de ligar, encomendar ou configurar seja o que for:

  • Nível 1: 17 Tbps de capacidade de mitigação na rede global de scrubbing. Os ataques volumétricos são limpos perto da sua origem, antes sequer de chegarem ao datacenter.
  • Nível 2: filtragem Arbor em tempo real com 3,2 Tbps em Frankfurt am Main. Mesmo à frente do servidor são reconhecidos e descartados os padrões específicos de cada protocolo, pacote a pacote.

Duas características são decisivas. A proteção corre em permanência e não precisa de reagir primeiro a um ataque, pelo que não existe um tempo de comutação durante o qual os seus jogadores caem. E não é usado null-routing: o seu endereço IP mantém-se na rede e só os pacotes nocivos são descartados. Quem retira o endereço IP da rede consegue, para si, o mesmo resultado que o atacante. A localização é Frankfurt am Main. Que jogos e protocolos estão cobertos é o que enumera Proteção DDoS para servidores de jogos em tempo real.

Advanced DDoS Protection para comunidades sob fogo permanente

Alguns projetos não são atacados de forma ocasional, mas sim de forma dirigida e ao longo de semanas, com padrões que vão mudando e sempre exatamente à hora de maior afluência. Para esses existe a Advanced DDoS Protection a partir de 50,00 EUR por mês, PrePaid e sem prazo mínimo. A diferença não está em mais capacidade, mas sim no controlo:

  • IP de proteção dedicado a partir do núcleo de Frankfurt, para o qual o seu servidor é comutado dentro da nossa própria rede. Do seu lado não é preciso qualquer alteração.
  • Regras de proteção autogeríveis por porta e por protocolo na área de cliente: define o que é permitido na 27015/UDP e o que é permitido na 27015/TCP, sem ter de escrever um ticket para isso.
  • As alterações entram em vigor em tempo real, pelo que pode afinar durante um ataque em curso em vez de esperar pela próxima janela de manutenção.
  • Perfil de proteção adequado a cada jogo, para o Garry's Mod e os restantes títulos Source, tal como perfis TCP e UDP livres para servidores modificados e aplicações próprias.

Também aqui vale o modelo PrePaid: sem prazo mínimo, sem período de aviso prévio, sem contrato e sem taxa de instalação. Quando a onda de ataques passar, basta não renovar. Quem tem o seu servidor Garry's Mod noutro sítio obtém esta proteção mudando-se para a KernelHost, porque a filtragem é feita na nossa própria rede e não em infraestrutura alheia.

Os dois níveis de proteção em comparação

Característica Proteção DDoS permanente incluída Advanced DDoS Protection
Preço incluída em todos os pacotes de servidor, sem sobretaxa a partir de 50,00 EUR por mês, PrePaid
Ativação ativa a partir da disponibilização, nada a configurar encomendar, receber o IP de proteção, o servidor é comutado
Capacidade de filtragem 17 Tbps de scrubbing global mais filtragem Arbor em tempo real com 3,2 Tbps em Frankfurt am Main a mesma filtragem em dois níveis
Endereço IP o endereço IP do seu servidor IP de proteção dedicado adicional
Conjunto de regras perfis automáticos, sem necessidade de configuração regras próprias por porta e por protocolo na área de cliente
Alterações acompanham automaticamente entram em vigor em tempo real, mesmo durante um ataque
Perfil de jogo perfis otimizados para os jogos correntes, incluindo o Garry's Mod perfil selecionável por porta, também para servidores modificados
Null-routing durante o ataque não não
Prazo ligado ao pacote de servidor PrePaid, sem prazo mínimo, sem período de aviso prévio, sem taxa de instalação

Para a maioria das comunidades de Garry's Mod, a proteção permanente incluída chega, em conjunto com uma configuração de servidor limpa. A Advanced DDoS Protection é a resposta para quando alguém leva a coisa a peito.

Erros frequentes e respetivas soluções

"O servidor está a correr, mas desapareceu da lista de servidores": na maioria dos casos, a 27015/UDP foi bloqueada de forma genérica ou o rate limit ficou demasiado apertado. Como o tráfego de jogo e a consulta partilham a mesma porta, uma regra grosseira atinge as duas coisas. Trabalhe antes com a comparação sobre os pacotes sem ligação. Se o servidor continuar invisível apesar de a porta estar acessível, verifique sv_setsteamaccount: sem um Game Server Login Token válido, um servidor Garry's Mod é fortemente desvalorizado na lista, e cada servidor precisa de um token próprio.

"A minha regra de iptables está correta e mesmo assim não faz efeito": há três causas frequentes. A regra está atrás das cadeias do UFW e nunca chega a ser alcançada; desapareceu no último reinício (nesse caso ajudam apt-get install -y iptables-persistent e netfilter-persistent save ou uma entrada em /etc/ufw/before.rules); ou o ataque é volumétrico e a regra trabalha corretamente numa linha que já está cheia. Verifique com iptables -L INPUT -n -v se os contadores de correspondências sobem. Se ficarem a zero, a regra não está a ser alcançada.

"O meu servidor DarkRP engasga para toda a gente, mas a linha está livre": isso é quase sempre Lua e não um ataque à linha. Veja no log do servidor que evento de rede chega com uma frequência estranha e verifique se o addon correspondente tem um limite por jogador. Se sar -n DEV 1 10 e os contadores de descarte não mostrarem nada de especial, não foi um ataque DDoS.

"O RCON deixou de funcionar de repente": não é DDoS, é normalmente um bloqueio provocado por si próprio. Um painel de administração com uma palavra-passe antiga dispara sv_rcon_minfailures, e sv_rcon_banpenalty bloqueia o endereço durante o número de minutos definido. Corrija a palavra-passe, levante o bloqueio e limite depois a porta ao seu próprio endereço.

"Mudei de endereço IP e dois dias depois estava outra vez offline": é o caso normal. O seu servidor publica o novo endereço por iniciativa própria assim que volta a estar registado no master server, e um gameserver sem endereço público não tem jogadores. Mudar de endereço dá horas ou dias, não é uma solução.

"O meu fornecedor anterior bloqueou o meu endereço IP": isso é null-routing. Com isso o fornecedor protege a sua própria rede; para si, o resultado é idêntico ao de um ataque bem-sucedido, normalmente ainda durante horas depois. Na dúvida, pergunte se filtram ou se aplicam null-routing. A resposta decide mais sobre a sua disponibilidade do que qualquer indicação de hardware.

"No tcpdump não vejo nada de especial": se o tráfego já é filtrado na rede à frente, é natural que nada chegue ao servidor. Esse é o caso normal quando a filtragem funciona. O inverso também é verdade: se a linha estiver saturada, é possível que nem sequer consiga estabelecer a sessão SSH com que queria medir. Nesse caso utilize a consola VNC na área de cliente.

Em resumo

  • Um servidor Garry's Mod precisa exatamente de uma porta aberta: 27015/UDP. O tráfego de jogo e a consulta A2S correm ali em conjunto, uma porta de consulta separada não existe.
  • O RCON está na 27015/TCP, transmite a palavra-passe em texto simples e deve ser aberto exclusivamente para o seu próprio endereço ou alcançado através de um encaminhamento de portas por SSH.
  • Não limite a porta, limite os pacotes sem ligação com o cabeçalho 0xffffffff. Um bloqueio genérico na 27015/UDP expulsa os seus próprios jogadores.
  • A falha mais frequente do Garry's Mod não é um ataque DDoS, é um evento de rede sem limite: cada evento registado com util.AddNetworkString precisa de um limite máximo por jogador e por segundo.
  • Com pacotes de 64 bytes, uma linha de 1 Gbit/s transporta cerca de 1,49 milhões de pacotes por segundo. Acima disso, a perda acontece no router à frente, e qualquer regra local fica sem efeito.
  • Na KernelHost, a proteção permanente em 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 filtragem Arbor em tempo real com 3,2 Tbps em Frankfurt am Main, sem null-routing.
  • Quem é atacado de forma dirigida e permanente acrescenta a Advanced DDoS Protection a partir de 50,00 EUR por mês: IP de proteção dedicado, regras autogeríveis por porta e por protocolo, com efeito em tempo real.

Se o seu servidor já estiver na KernelHost, a filtragem está ativa sem que tenha de fazer o que quer que seja. Se ainda assim notar anomalias, abra um ticket de suporte, para que as regras de filtragem sejam afinadas para o seu endereço IP. Indique logo quatro dados: endereço IP, porta, período de tempo no seu fuso horário e o que está a observar (jogadores a serem expulsos, servidor fora da lista, picos de lag). Durante um ataque em curso pode ainda contactar-nos através do chat de emergência do WhatsApp em +43 650 8209883.

Quem opera outros títulos Source além do Garry's Mod encontra as bases comuns em Proteger servidores CS2 e Source contra ataques DDoS, e a forma de montar a base de raiz está em Instalar um servidor de jogos com o SteamCMD.

Perguntas frequentes

O meu servidor Garry's Mod está offline neste momento. Isto é um ataque DDoS?
Verifique primeiro a taxa de pacotes, não a carga do CPU. O comando sar -n DEV 1 10 mostra os pacotes e os bytes por segundo, ip -s link show eth0 mostra os contadores de descarte da interface e nstat -az mostra os contadores de erro UDP do kernel. Se os pacotes de entrada subirem muito acima do seu valor normal enquanto quase ninguém está ligado, é um ataque. Se os contadores de rede ficarem sem nada de especial e mesmo assim tudo engasgar, a causa está quase sempre no Lua: nesse caso é um addon ou um evento de rede sem proteção que devora o tempo de processamento, e nenhuma filtragem do mundo muda isso.
De que portas precisa mesmo um servidor Garry's Mod?
Exatamente uma: 27015/UDP, definida através do parâmetro de arranque -port. Por esta única porta passam em conjunto o tráfego de jogo e a consulta A2S da lista de servidores, porque no Garry's Mod não existe uma porta de consulta separada. O RCON está na 27015/TCP e deve ser aberto exclusivamente para o seu próprio endereço. A 27020/UDP só é precisa se transmitir através do SourceTV. A porta do cliente 27005/UDP parte do jogador e não precisa de qualquer regra no servidor. O MySQL para o DarkRP deve ficar ligado a 127.0.0.1 e nunca à rede aberta.
Posso bloquear a porta de consulta para acabar com a enxurrada de consultas?
Não, porque uma porta de consulta separada não existe. Quem bloqueia a 27015/UDP ou lhe aplica um rate limit genérico expulsa no mesmo gesto os seus próprios jogadores e desaparece da lista de servidores. O correto é um limite que atinja apenas os pacotes sem ligação: todas as consultas de servidor e todos os estabelecimentos de ligação do motor Source começam com os quatro bytes 0xffffffff, e o tráfego dos jogadores já ligados não leva esse cabeçalho. É exatamente sobre esse padrão que aplica um limite por endereço de origem com o nftables ou o iptables, tendo como valor de partida cerca de oito pacotes por segundo.
Porque é que o RCON é um alvo tão apetecido no Garry's Mod?
Porque o ganho é máximo e a barreira é baixa. O RCON está no mesmo número de porta que o jogo, só que em TCP, pelo que se encontra sem procurar. O protocolo Source RCON transmite a palavra-passe em texto simples, sem TLS e sem troca de chaves. E quem toma o RCON pode mudar o mapa, banir todos os jogadores, alterar a configuração e parar o servidor, tudo isso sem largura de banda nenhuma. Defina por isso uma palavra-passe longa e aleatória, ative sv_rcon_minfailures e sv_rcon_banpenalty, e abra a 27015/TCP apenas para o seu próprio endereço.
O que é a falha de reflexão A2S e ainda me afeta?
A reflexão A2S é um ataque em que o seu servidor não é o alvo, mas sim a ferramenta: o atacante consulta milhares de gameservers com o endereço de origem falsificado, e as respostas, bastante maiores, convergem na verdadeira vítima. Historicamente, um pedido A2S_INFO tinha 25 bytes, e o US-CERT lista o protocolo da Steam com um fator de amplificação de 5,5. A Valve fechou a falha a partir de novembro de 2020: os pacotes de consulta têm de ser preenchidos até aos 1200 bytes, e o A2S_PLAYER e o A2S_RULES passaram a exigir um challenge. Mantenha o binário do servidor atualizado e esta proteção fica a funcionar.
Porque é que a minha regra de firewall não serve de nada durante o ataque?
Porque só atua depois de o pacote já ter chegado. Com pacotes de 64 bytes, uma linha de 1 Gbit/s transporta cerca de 1,49 milhões de pacotes por segundo e uma linha de 10 Gbit/s cerca de 14,88 milhões. Se o ataque estiver acima disso, a perda acontece no router que está à frente, e a sua regra nunca chega a ser executada. Muito antes de a linha encher, o CPU já está no limite, porque cada pacote custa uma passagem pela stack de rede, mesmo que a seguir seja descartado. A partir desse ponto, só ajuda a filtragem na rede à frente do servidor.
O meu servidor DarkRP tem picos de lag, mas a linha está livre. A que se deve?
Nesse caso é quase sempre Lua e não um ataque à linha. Assim que um addon regista um evento de rede com util.AddNetworkString e fica à escuta com net.Receive, qualquer cliente ligado pode disparar esse evento em ciclo, e o servidor executa cada uma das mensagens. Um jogador com uns poucos kilobits por segundo chega para isso. A solução está no addon e não na firewall: um limite máximo por jogador e por segundo, uma verificação do comprimento da mensagem e a determinação do jogador do lado do servidor em vez do conteúdo da mensagem.
O meu servidor na KernelHost fica offline durante um ataque?
Não. Não é usado null-routing. O seu endereço IP mantém-se na rede e só os pacotes nocivos são descartados. A proteção está montada em dois níveis: 17 Tbps de capacidade de mitigação na rede global de scrubbing e uma filtragem Arbor em tempo real com 3,2 Tbps em Frankfurt am Main. Corre em permanência e não precisa de reagir primeiro a um ataque, pelo que não existe um tempo de comutação durante o qual os seus jogadores caem. Esta proteção permanente está incluída em todos os pacotes de servidor sem sobretaxa e fica ativa a partir do momento da disponibilização.
Quando é que preciso adicionalmente da Advanced DDoS Protection?
Quando a sua comunidade não é atacada de forma ocasional, mas sim de forma dirigida e ao longo de semanas, e quer controlar a filtragem por si próprio. Recebe um IP de proteção dedicado e gere as regras de proteção por porta e por protocolo na área de cliente, tratando por exemplo a 27015/UDP de forma diferente da 27015/TCP. As alterações entram em vigor em tempo real, pelo que pode afinar durante um ataque em curso. O preço começa em 50,00 EUR por mês, PrePaid, sem prazo mínimo, sem período de aviso prévio e sem taxa de instalação.

Garry's Mod Garrys Mod DDoS-Schutz DarkRP Source-Engine A2S-Query Gameserver-Schutz Port 27015 Advanced DDoS Protection