Como detectar e banir bots automaticamente no MU Online
Monte um pipeline de detecção automática de bots no seu servidor de MU Online combinando análise de padrões no banco, CAPTCHA in-game, telemetria de pacotes e banimento agendado, sem inundar jogadores legítimos com falsos positivos.
Bots são a praga silenciosa dos servidores de MU Online. Enquanto você dorme, um único usuário de bot roda dez clientes em spots de XP, acumula Zen e itens raros, derruba os preços do mercado e desestimula os jogadores legítimos que jogam na mão. Em 72 horas um servidor sem defesa vira terra arrasad
Bots são a praga silenciosa dos servidores de MU Online. Enquanto você dorme, um único usuário de bot roda dez clientes em spots de XP, acumula Zen e itens raros, derruba os preços do mercado e desestimula os jogadores legítimos que jogam na mão. Em 72 horas um servidor sem defesa vira terra arrasada economicamente. A tentação é ativar um banimento automático agressivo — e o resultado costuma ser pior: falsos positivos banem o jogador hardcore que passa 16 horas farmando de forma honesta, geram reclamações e queimam a reputação do servidor. A saída correta é um pipeline em camadas: coletar sinais de forma automática, pontuar cada conta, desafiar os suspeitos com CAPTCHA e reservar o ban permanente para os casos inequívocos. Este guia mostra como montar esse pipeline. Todos os nomes de tabela, colunas e thresholds são exemplos que variam por season/emulador — calibre com os dados reais do seu servidor.
Pré-requisitos
- SQL Server Management Studio (SSMS) conectado ao banco
MuOnline. - SQL Server Agent habilitado para jobs agendados.
- Acesso administrativo ao GameServer e ao ConnectServer.
- Conhecimento do schema do seu build: nomes de
MEMB_INFO,MEMB_STAT,Character, colunas de conexão e de XP. - Um ambiente de teste (ou conta de teste) para validar antes de rodar em produção.
- Backup completo do banco antes de qualquer alteração.
- Idealmente, suporte a CAPTCHA/anti-bot nativo no emulador ou um módulo anti-cheat.
> Rode todo o pipeline em modo de log (sem banir) por pelo menos 48 a 72 horas antes de ativar qualquer ban automático. Essa fase de calibração é o que separa um sistema que protege de um que destrói a base de jogadores.
A filosofia: detecção em camadas com pontuação
Nenhum sinal isolado prova que uma conta é bot. Um jogador pode farmar muito; outro pode ficar online o dia todo; um terceiro pode repetir a mesma rota. O que denuncia o bot é a combinação desses sinais. Por isso o pipeline atribui pontos a cada indício e só age quando a soma cruza um limiar. A tabela abaixo mostra um esquema de pontuação de exemplo.
| Sinal detectado | Pontos | Justificativa |
|---|---|---|
| Kills/hora acima do teto humano sustentado por 2h+ | 30 | Volume impossível na mão |
| Sessão contínua acima de 20 horas | 25 | Bot 24/7 |
| Variância de posição quase nula | 20 | Rota fixa automatizada |
| Zero mensagens de chat em sessão longa | 10 | Ausência de comportamento social |
| Falha em CAPTCHA in-game | 40 | Sinal quase inequívoco |
| Múltiplos clientes no mesmo IP acima do limite | 15 | Fazenda de bots |
Com esse esquema, uma conta que apenas farma muito acumula 30 pontos — suspeita, mas não banível. Se ela também mantém sessão de 22 horas (25) e falha no CAPTCHA (40), chega a 95 e vira caso claro. Os pesos e limiares variam por season/emulador; ajuste-os observando as contas do topo do seu ranking legítimo.
Passo 1 — Criar a infraestrutura de pontuação
Comece com duas tabelas: uma de eventos de detecção e uma de pontuação acumulada por conta.
USE MuOnline;
GO
CREATE TABLE dbo.Bot_Score (
AccountID VARCHAR(10) PRIMARY KEY,
TotalScore INT NOT NULL DEFAULT 0,
LastUpdate DATETIME DEFAULT GETDATE(),
Status TINYINT DEFAULT 0 -- 0=monitorando,1=desafiado,2=banido,3=falso positivo
);
GO
CREATE TABLE dbo.Bot_Event (
EventID INT IDENTITY(1,1) PRIMARY KEY,
AccountID VARCHAR(10) NOT NULL,
CharName VARCHAR(10) NULL,
Signal VARCHAR(60) NOT NULL, -- ex.: KILLS_HORA, SESSAO_LONGA
Points INT NOT NULL,
Detail VARCHAR(200) NULL,
CreatedAt DATETIME DEFAULT GETDATE()
);
GO
Cada vez que uma checagem encontra um sinal, ela grava um evento em Bot_Event e soma os pontos em Bot_Score. Isso preserva o rastro de evidência — indispensável se um jogador contestar o ban.
Passo 2 — Detecção comportamental via SQL
A camada mais barata e poderosa é a análise comportamental no próprio banco. A stored procedure abaixo varre contas online e registra os sinais principais.
USE MuOnline;
GO
CREATE PROCEDURE dbo.SP_Bot_Scan
AS
BEGIN
SET NOCOUNT ON;
-- Sinal 1: kills/hora acima do teto, sustentado por 2h+
INSERT INTO dbo.Bot_Event (AccountID, CharName, Signal, Points, Detail)
SELECT c.AccountID, c.Name, 'KILLS_HORA', 30,
'PkCount=' + CAST(c.PkCount AS VARCHAR)
FROM Character c
INNER JOIN MEMB_STAT s ON c.AccountID = s.memb___id
WHERE s.ConnectStat = 1
AND DATEDIFF(HOUR, s.ConnectTM, GETDATE()) >= 2
AND (c.PkCount / NULLIF(DATEDIFF(HOUR, s.ConnectTM, GETDATE()), 0)) > 1000;
-- Sinal 2: sessao continua acima de 20 horas
INSERT INTO dbo.Bot_Event (AccountID, CharName, Signal, Points, Detail)
SELECT s.memb___id, c.Name, 'SESSAO_LONGA', 25,
CAST(DATEDIFF(HOUR, s.ConnectTM, GETDATE()) AS VARCHAR) + 'h'
FROM MEMB_STAT s
INNER JOIN Character c ON s.memb___id = c.AccountID
WHERE s.ConnectStat = 1
AND DATEDIFF(HOUR, s.ConnectTM, GETDATE()) > 20;
-- Consolidar pontuacao
MERGE dbo.Bot_Score AS tgt
USING (
SELECT AccountID, SUM(Points) AS Pts
FROM dbo.Bot_Event
WHERE CreatedAt >= DATEADD(HOUR, -24, GETDATE())
GROUP BY AccountID
) AS src
ON tgt.AccountID = src.AccountID
WHEN MATCHED THEN
UPDATE SET TotalScore = src.Pts, LastUpdate = GETDATE()
WHEN NOT MATCHED THEN
INSERT (AccountID, TotalScore) VALUES (src.AccountID, src.Pts);
PRINT 'Bot scan concluido: ' + CAST(GETDATE() AS VARCHAR);
END;
GO
Repare que a consolidação usa uma janela de 24 horas: pontos antigos expiram, evitando que um jogador acumule suspeita eterna por um dia atípico de farm.
Passo 3 — Agendar o scan no SQL Server Agent
- No SSMS, expanda SQL Server Agent → clique com o direito em Jobs → New Job.
- Nome:
Bot_Scan_Automatico. - Aba Steps → New Step: tipo
Transact-SQL, databaseMuOnline, comandoEXEC dbo.SP_Bot_Scan;. - Aba Schedules → New Schedule: frequência diária, sub-frequência a cada 15 minutos.
- Confirme que o serviço
SQL Server Agentestá Em execução emservices.msc.
Um intervalo de 15 minutos equilibra frescor de detecção com carga no banco. Servidores muito grandes podem espaçar para 30 minutos.
Passo 4 — CAPTCHA in-game direcionado
O CAPTCHA é a camada de confirmação mais decisiva, porque um bot burro simplesmente não responde. O erro clássico é perguntar a todos os jogadores em intervalo fixo, o que irrita a base. A abordagem inteligente é disparar o desafio apenas para contas com pontuação suspeita.
Se o seu emulador tem anti-bot nativo com CAPTCHA (comum de Season 6 em diante), configure-o para gatilho por suspeita quando possível:
[AntiBot]
Enable = 1
QuestionEnable = 1
QuestionInterval = 1800 ; base de 30 min para suspeitos
QuestionTimeout = 120 ; tempo para responder (segundos)
WrongAnswerLimit = 2 ; erros antes de punir
Punishment = 1 ; 0=kick, 1=ban temp, 2=ban perma
As perguntas ficam em um arquivo de texto simples, uma por linha no formato pergunta,resposta:
Quanto e 6 mais 5?,11
Qual a cor do sangue?,vermelho
Quantos dias tem uma semana?,7
Qual mes vem depois de junho?,julho
Marque no seu pipeline quem foi desafiado e registre o resultado. Uma falha de CAPTCHA vale muitos pontos justamente por ser quase inequívoca:
-- Registrar falha de CAPTCHA (chamado pelo hook do emulador ou manualmente)
INSERT INTO dbo.Bot_Event (AccountID, CharName, Signal, Points, Detail)
VALUES ('contaSuspeita', 'NickBot', 'CAPTCHA_FALHOU', 40, '2 erros consecutivos');
> Mantenha as respostas sem acentos e case-insensitive. Muitos jogadores brasileiros digitam sem acento e capitalização inconsistente; exigir "Brasília" com acento gera falso positivo em gente honesta.
Passo 5 — Telemetria de pacotes e limite por IP
A camada de rede complementa a comportamental. No ConnectServer, limite conexões simultâneas por IP e proteja contra flood — fazendas de bots costumam rodar muitos clientes do mesmo endereço.
[ServerInfo]
MaxConnectionPerIP = 4 ; contas simultaneas por IP
PacketFloodProtection = 1
MaxPacketsPerSecond = 60 ; teto por conexao
Ajuste MaxConnectionPerIP com cuidado: LAN houses e famílias legitimamente compartilham IP. Um valor entre 3 e 5 costuma equilibrar. Detecção de injeção de memória, integridade do cliente (checksum do Main.exe) e leitura de velocidade dependem do módulo anti-cheat do seu build e não são cobertas por SQL puro.
Passo 6 — Banimento por limiar, com revisão
Agora a peça que fecha o pipeline: agir sobre a pontuação. Divida em dois níveis — desafio automático para pontuação média e ban com revisão para pontuação alta.
USE MuOnline;
GO
CREATE PROCEDURE dbo.SP_Bot_Enforce
AS
BEGIN
SET NOCOUNT ON;
-- Nivel 1: 50-89 pontos -> marcar para desafio de CAPTCHA
UPDATE dbo.Bot_Score
SET Status = 1
WHERE TotalScore BETWEEN 50 AND 89 AND Status = 0;
-- Nivel 2: 90+ pontos -> banir e desconectar
UPDATE m
SET m.bloc_code = 1
FROM MEMB_INFO m
INNER JOIN dbo.Bot_Score b ON m.memb___id = b.AccountID
WHERE b.TotalScore >= 90 AND b.Status IN (0,1);
UPDATE s
SET s.ConnectStat = 0
FROM MEMB_STAT s
INNER JOIN dbo.Bot_Score b ON s.memb___id = b.AccountID
WHERE b.TotalScore >= 90;
UPDATE dbo.Bot_Score
SET Status = 2
WHERE TotalScore >= 90 AND Status IN (0,1);
PRINT 'Enforce concluido: ' + CAST(GETDATE() AS VARCHAR);
END;
GO
Mesmo no nível 2, mantenha uma revisão humana no início: rode em modo log, veja quem seria banido e confira manualmente por alguns dias. Só depois libere a ação automática — e ainda assim revise a fila diariamente. Esse é o mesmo princípio de moderação responsável que se aplica a qualquer punição; se você ainda não estruturou os comandos de moderação, vale começar pelo básico de como criar servidor de MU Online e pela camada de ban manual antes de automatizar.
Passo 7 — Query de revisão e reversão de falso positivo
Toda manhã, revise quem o sistema pegou:
SELECT b.AccountID, b.TotalScore, b.Status,
STRING_AGG(e.Signal, ', ') AS Sinais
FROM dbo.Bot_Score b
LEFT JOIN dbo.Bot_Event e
ON e.AccountID = b.AccountID
AND e.CreatedAt >= DATEADD(HOUR, -24, GETDATE())
WHERE b.Status IN (1,2)
GROUP BY b.AccountID, b.TotalScore, b.Status
ORDER BY b.TotalScore DESC;
Se identificar um falso positivo, reverta e marque para o sistema não reincidir:
UPDATE MEMB_INFO SET bloc_code = 0 WHERE memb___id = 'contaHonesta';
UPDATE dbo.Bot_Score SET Status = 3, TotalScore = 0 WHERE AccountID = 'contaHonesta';
Erros comuns e soluções
| Problema | Causa provável | Solução |
|---|---|---|
| Muitos falsos positivos | Thresholds calibrados para outro perfil | Aumente o teto de kills/hora e o limiar de ban; observe o ranking legítimo |
| Bots passam despercebidos | Detecção de sinal único, bot randomiza movimento | Some múltiplos sinais; adicione CAPTCHA direcionado |
| Scan não insere eventos | Nome de coluna/tabela diferente no build | Confira o schema com INFORMATION_SCHEMA.COLUMNS |
| CAPTCHA irrita jogadores legítimos | Gatilho por intervalo fixo global | Dispare CAPTCHA só para contas com pontuação suspeita |
| Job não roda | SQL Server Agent parado ou sem permissão | Verifique services.msc e o histórico do job no SSMS |
| Ban não impede login | Coluna de bloqueio incorreta | Confirme o nome real (bloc_code, block_code, IsBlock) no schema |
| Conta banida segue online | Faltou zerar ConnectStat | Inclua o UPDATE de desconexão no enforce |
Checklist de lançamento
- Tabelas
Bot_ScoreeBot_Eventcriadas SP_Bot_Scanvalidada em ambiente de teste- Job
Bot_Scan_Automaticoagendado e Agent em execução - Esquema de pontuação calibrado com dados reais do servidor
- CAPTCHA in-game configurado e disparando por suspeita
- Perguntas do CAPTCHA sem acento e case-insensitive
- Limite de conexões por IP ajustado no ConnectServer
SP_Bot_Enforcerodando em modo log por 48-72h antes de banir- Rotina de revisão diária da fila de suspeitos definida
- Processo de reversão de falso positivo documentado
- Evidências (eventos) retidas por pelo menos 30 dias
- Backup do banco feito antes de ativar em produção
Detecção de bot que funciona não é a mais agressiva — é a mais disciplinada. Ao coletar sinais de forma automática, pontuar em camadas, desafiar antes de punir e reservar o ban para os casos claros, você limpa o servidor dos bots reais sem transformar cada jogador dedicado em vítima. Esse equilíbrio é o que mantém a economia saudável e a base de jogadores confiando no seu servidor.
Perguntas frequentes
Dá para banir bots de forma 100% automática sem risco?
Não com segurança total. Automação total gera falsos positivos que banem jogadores legítimos e destroem a reputação do servidor. A abordagem recomendada é automática na detecção e na coleta de evidência, mas com uma janela de revisão humana ou um sistema de pontuação com limiar alto antes do ban permanente. Ban 100% automático só é aceitável para sinais inequívocos, como resposta reprovada em CAPTCHA repetido.
Como diferencio um bot de um jogador dedicado que joga muitas horas?
Jogadores humanos têm variância: pausas irregulares, mudanças de spot, chat esporádico, tempos de reação que oscilam. Bots são metronômicos — mesma rota, mesmo intervalo entre kills, zero interação social, sessões contínuas de 20 horas ou mais. A detecção robusta cruza vários sinais em vez de olhar um só, justamente para não punir o jogador hardcore legítimo.
CAPTCHA in-game não irrita os jogadores?
Se mal calibrado, sim. A chave é a frequência e o gatilho. Em vez de perguntar a todos a cada 20 minutos, dispare o CAPTCHA só para contas que já acumularam pontos de suspeita por outros sinais. Assim o jogador honesto raramente vê uma pergunta, enquanto o suspeito é desafiado com frequência. O intervalo ideal varia por season/emulador e pelo perfil do seu público.
Bots conseguem burlar a detecção por padrão de movimento?
Bots avançados adicionam ruído aleatório para imitar humanos, o que derrota detecção baseada só em um sinal. Por isso a defesa eficaz é em camadas: mesmo que o bot randomize o movimento, ele tende a falhar no CAPTCHA, manter sessões longas demais ou gerar volume de kills impossível. Nenhuma camada isolada é suficiente; o conjunto é o que funciona.
Preciso de anti-cheat externo ou o banco resolve?
O banco resolve a camada comportamental (kills/hora, tempo online, padrões de XP) e é onde você começa. Mas telemetria de pacotes, verificação de integridade do cliente e detecção de injeção de memória exigem suporte do emulador ou de um módulo anti-cheat externo. A cobertura completa combina análise SQL com o que o seu build oferece de proteção no lado do cliente.