O maior portal de MU Online do Brasil — desde 2003
Tutorial Avançado Servidor

Como criar servidor de MU Online Mobile — guia completo

Guia completo sobre servidores privados de MU Online Mobile — estrutura técnica, diferenças do PC, backend API, banco de dados, e conectividade de clientes Android/iOS.

EQ Equipe ViciadosMU · Atualizado em 1 jul 2026 · ⏱ 25 min de leitura

O MU Online Mobile é uma versão completamente diferente do MU PC — usa arquitetura web moderna em vez do protocolo binário TCP do MuServer clássico. Criar um servidor privado de MU Mobile envolve desenvolvimento de backend API, muito mais do que configurar arquivos .ini.

Atenção: A criação de servidores privados de MU Online Mobile envolve engenharia reversa do protocolo e modificação de APK. Este guia é de caráter exclusivamente educacional — descreve a arquitetura técnica para estudo e aprendizado sobre sistemas de jogos mobile.

Diferenças fundamentais: MU PC vs MU Mobile

AspectoMU PC (MuServer)MU Mobile
ProtocoloTCP binário (pacotes customizados)HTTP/HTTPS + WebSocket
BackendDataServer + GameServer + JoinServerAPI REST + Gateway WebSocket
Banco de dadosSQL Server (ODBC 32-bit)MySQL/PostgreSQL/MongoDB
Arquivos de config.ini (texto simples)JSON + banco de dados
Cliente.exe executável Windows.apk Android / App iOS
AutenticaçãoTabela MEMB_INFO no SQLJWT tokens / OAuth
ComunicaçãoPacotes binários customJSON sobre WebSocket
SegurançaMínima por padrãoSSL/TLS obrigatório

Arquitetura de um servidor MU Mobile

CLIENTE (APK modificado)
      │
      │ HTTPS API calls (REST)
      │ WSS WebSocket (tempo real)
      ▼
LOAD BALANCER / NGINX
      │
      ├──► API SERVER (Node.js / Go / C#)
      │         │ autenticação, inventário, chat
      │         │
      │    ┌────▼──────────────────┐
      │    │ BANCO DE DADOS        │
      │    │ MySQL / PostgreSQL    │
      │    │ (contas, personagens, │
      │    │  itens, guildas)      │
      │    └───────────────────────┘
      │
      └──► GAME SERVER (engine)
                │ lógica de combate
                │ sincronização de posição
                │ eventos do mundo
                ▼
           BANCO CACHE (Redis)
           (estado em tempo real)

Pré-requisitos técnicos

Para desenvolver um servidor MU Mobile é necessário:

ÁreaConhecimento / Tecnologia
Backend webNode.js + Express, Go, ou C# ASP.NET
Banco de dadosMySQL 8.x ou PostgreSQL 14+
Cache/real-timeRedis (para estado de jogo)
ProtocoloWebSocket (socket.io ou ws)
SegurançaSSL/TLS, JWT
Reverse engineeringAPK tools (apktool, jadx)
MobileAndroid Studio (para modificar APK)
LinuxNginx, systemd, configuração de servidor

Passo 1 — Entender o protocolo do cliente

O primeiro desafio é descobrir como o cliente mobile se comunica com o servidor:

Ferramenta de análise de tráfego

Para analisar o protocolo sem modificar código:

# Captura de tráfego com proxy (mitmproxy)
pip install mitmproxy
mitmproxy --listen-port 8888

# No Android, configure o proxy para 192.168.1.X:8888
# Abra o MU Mobile → o tráfego aparece no mitmproxy

O que observar

Tipicamente você vai ver:
1. POST /api/auth/login    → autenticação da conta
2. GET  /api/character     → dados do personagem
3. WSS  wss://game.server.com/game  → canal de jogo em tempo real

Payload de login (JSON exemplo):
{
  "username": "usuario123",
  "password": "hash_da_senha",
  "device_id": "uuid-do-dispositivo",
  "version": "2.3.1"
}

Passo 2 — Banco de dados MySQL para MU Mobile

O MU Mobile usa MySQL (ou PostgreSQL) em vez do SQL Server:

-- Criar banco de dados
CREATE DATABASE mu_mobile CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

CREATE USER 'mu_mobile_app'@'localhost' IDENTIFIED BY 'SenhaMobileApp!';
GRANT ALL PRIVILEGES ON mu_mobile.* TO 'mu_mobile_app'@'localhost';
FLUSH PRIVILEGES;

-- Estrutura básica de tabelas

USE mu_mobile;

-- Tabela de contas
CREATE TABLE accounts (
  id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  username   VARCHAR(32) NOT NULL UNIQUE,
  password   VARCHAR(128) NOT NULL,   -- bcrypt hash
  email      VARCHAR(255),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  last_login TIMESTAMP,
  ban_until  TIMESTAMP NULL,
  INDEX idx_username (username)
);

-- Tabela de personagens
CREATE TABLE characters (
  id           INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  account_id   INT UNSIGNED NOT NULL REFERENCES accounts(id),
  name         VARCHAR(16) NOT NULL UNIQUE,
  class        TINYINT NOT NULL,         -- 0=DK, 1=DW, 2=Elf...
  level        SMALLINT DEFAULT 1,
  experience   BIGINT DEFAULT 0,
  strength     SMALLINT DEFAULT 26,
  agility      SMALLINT DEFAULT 20,
  vitality     SMALLINT DEFAULT 24,
  energy       SMALLINT DEFAULT 16,
  hp           INT DEFAULT 100,
  mp           INT DEFAULT 50,
  map_id       SMALLINT DEFAULT 0,
  pos_x        SMALLINT DEFAULT 125,
  pos_y        SMALLINT DEFAULT 125,
  created_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  last_saved   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_account (account_id)
);

-- Tabela de itens do inventário
CREATE TABLE inventory (
  id           INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  character_id INT UNSIGNED NOT NULL REFERENCES characters(id),
  slot         TINYINT NOT NULL,
  item_group   TINYINT NOT NULL,
  item_id      SMALLINT NOT NULL,
  level        TINYINT DEFAULT 0,
  durability   TINYINT DEFAULT 100,
  options      VARBINARY(16) DEFAULT NULL,   -- opções binárias do item
  INDEX idx_character (character_id)
);

-- Tabela de guildas
CREATE TABLE guilds (
  id           INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name         VARCHAR(16) NOT NULL UNIQUE,
  score        INT DEFAULT 0,
  created_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Passo 3 — API Backend (Node.js + Express)

Exemplo de estrutura básica de API para MU Mobile:

// server.js — exemplo de backend Node.js
const express = require('express');
const ws = require('ws');
const mysql = require('mysql2/promise');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');

const app = express();
app.use(express.json());

const db = await mysql.createPool({
  host: 'localhost',
  database: 'mu_mobile',
  user: 'mu_mobile_app',
  password: 'SenhaMobileApp!'
});

// Endpoint de autenticação
app.post('/api/auth/login', async (req, res) => {
  const { username, password } = req.body;

  const [rows] = await db.query(
    'SELECT id, password, ban_until FROM accounts WHERE username = ?',
    [username]
  );

  if (!rows.length) {
    return res.status(401).json({ error: 'Conta não encontrada' });
  }

  const account = rows[0];

  // Verificar ban
  if (account.ban_until && new Date(account.ban_until) > new Date()) {
    return res.status(403).json({ error: 'Conta banida' });
  }

  // Verificar senha
  const validPassword = await bcrypt.compare(password, account.password);
  if (!validPassword) {
    return res.status(401).json({ error: 'Senha incorreta' });
  }

  // Gerar token JWT
  const token = jwt.sign(
    { account_id: account.id, username },
    process.env.JWT_SECRET,
    { expiresIn: '24h' }
  );

  // Atualizar last_login
  await db.query('UPDATE accounts SET last_login = NOW() WHERE id = ?', [account.id]);

  res.json({ token, account_id: account.id });
});

// Endpoint de lista de personagens
app.get('/api/characters', authenticateToken, async (req, res) => {
  const [chars] = await db.query(
    'SELECT id, name, class, level, map_id FROM characters WHERE account_id = ?',
    [req.user.account_id]
  );
  res.json({ characters: chars });
});

// Middleware de autenticação JWT
function authenticateToken(req, res, next) {
  const token = req.headers['authorization']?.split(' ')[1];
  if (!token) return res.sendStatus(401);

  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
}

app.listen(3000, () => console.log('API rodando na porta 3000'));

WebSocket para comunicação em tempo real

// game-server.js — servidor WebSocket para o jogo
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3001 });

// Mapa de jogadores conectados
const players = new Map();

wss.on('connection', (socket, request) => {
  let playerId = null;

  socket.on('message', (data) => {
    const message = JSON.parse(data);

    switch (message.type) {
      case 'ENTER_GAME':
        // Validar token e carregar personagem
        playerId = message.character_id;
        players.set(playerId, { socket, position: { x: 125, y: 125 } });
        break;

      case 'MOVE':
        // Processar movimento
        if (players.has(playerId)) {
          players.get(playerId).position = message.position;
          // Broadcast da posição para jogadores próximos
          broadcastToNearby(playerId, { type: 'PLAYER_MOVED', id: playerId, position: message.position });
        }
        break;

      case 'ATTACK':
        // Processar ataque
        processAttack(playerId, message.target_id, message.skill_id);
        break;
    }
  });

  socket.on('close', () => {
    players.delete(playerId);
    // Salvar personagem no banco
    saveCharacter(playerId);
  });
});

function broadcastToNearby(fromId, message) {
  const from = players.get(fromId);
  if (!from) return;

  // Calcular raio de 15 tiles
  for (const [id, player] of players) {
    if (id === fromId) continue;
    const dist = Math.hypot(
      player.position.x - from.position.x,
      player.position.y - from.position.y
    );
    if (dist <= 15) {
      player.socket.send(JSON.stringify(message));
    }
  }
}

Passo 4 — Modificar o APK para servidor privado

Atenção: Esta seção descreve o processo técnico por razões educacionais. A modificação do APK oficial da Webzen para fins comerciais ou de distribuição pode violar os termos de serviço.

Ferramentas necessárias

# Instalar apktool (descompila/recompila APK)
# Baixar apktool.jar do repositório oficial

# Instalar jadx (descompila .dex para Java legível)
# Disponível em github.com/skylot/jadx

# Instalar zipalign e apksigner (do Android SDK)

Processo de modificação

# 1. Descompilar o APK
java -jar apktool.jar d MUMobile.apk -o mu_mobile_decompiled/

# 2. Procurar URLs do servidor na pasta decompilada
grep -r "webzen.com" mu_mobile_decompiled/
grep -r "muweb.com" mu_mobile_decompiled/
grep -r "api.mu" mu_mobile_decompiled/

# 3. As URLs geralmente estão em:
# - smali/com/webzen/... → código decompilado
# - assets/config.json  → configuração
# - res/raw/            → arquivos raw
# - res/values/strings.xml

# 4. Substituir a URL do servidor oficial
# Exemplo:
# "https://api.mu-mobile.webzen.com" → "https://meuservidor.com"
sed -i 's/api.mu-mobile.webzen.com/meuservidor.com/g' mu_mobile_decompiled/assets/config.json

# 5. Recompilar o APK modificado
java -jar apktool.jar b mu_mobile_decompiled/ -o MUMobile_private.apk

# 6. Assinar o APK (necessário para instalar no Android)
# Criar keystore
keytool -genkeypair -v -keystore mu_private.keystore -alias mu -keyalg RSA -keysize 2048 -validity 10000

# Assinar
apksigner sign --ks mu_private.keystore --out MUMobile_private_signed.apk MUMobile_private.apk

Passo 5 — Nginx como proxy reverso (SSL)

# /etc/nginx/sites-available/mu-mobile
server {
    listen 443 ssl;
    server_name meuservidor.com;

    ssl_certificate     /etc/ssl/certs/meuservidor.crt;
    ssl_certificate_key /etc/ssl/private/meuservidor.key;

    # API REST
    location /api/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # WebSocket do jogo
    location /game {
        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

Passo 6 — Diferenças de gameplay para configurar

Ao contrário do MU PC, no MU Mobile a maioria das configurações fica no banco de dados:

-- Configuração de taxas (exemplo)
CREATE TABLE server_config (
  config_key   VARCHAR(64) PRIMARY KEY,
  config_value VARCHAR(255)
);

INSERT INTO server_config VALUES
  ('exp_rate',         '5'),
  ('drop_rate',        '2'),
  ('exc_drop_rate',    '10'),
  ('max_level',        '400'),
  ('max_resets',       '20'),
  ('reset_level',      '400'),
  ('pvp_enabled',      '1'),
  ('events_enabled',   '1');

-- Ler configuração no backend:
-- SELECT config_value FROM server_config WHERE config_key = 'exp_rate';

Diferenças chave para quem vem do MU PC

MU PCMU Mobile
Arquivos .ini de configuraçãoConfiguração no banco ou JSON
SQL Server (ODBC 32-bit)MySQL/PostgreSQL
DataServer.exeAPI REST backend
GameServer.exeGame Engine (Node.js/Go/C#)
ConnectServer.exeLoad balancer (Nginx)
JoinServer.exeAutenticação JWT
Porta TCP 44405Portas 80/443 (HTTP/HTTPS)
Protocolo binárioJSON sobre WebSocket
Runtime VC++Node.js, Go ou .NET runtime

Realidade do desenvolvimento

Criar um servidor privado de MU Mobile completo requer:

  • Meses de desenvolvimento (vs dias para MU PC com distribuição pronta);
  • Conhecimento de desenvolvimento web full-stack;
  • Habilidade em engenharia reversa do protocolo;
  • Infraestrutura de VPS Linux com SSL;
  • Entendimento de segurança de APIs (autenticação, rate limiting, etc.);
  • Manutenção contínua quando o cliente oficial recebe updates.

Para aprendizado de programação de servidores de jogos, o MU PC (MuServer) é muito mais acessível como ponto de partida. O MU Mobile é um projeto avançado que requer experiência prévia em desenvolvimento backend.

Dica: Se o objetivo é estudar desenvolvimento de servidores de jogos, comece com o MU PC (MuServer) para aprender a estrutura base, depois avance para entender protocolos web ao estudar a arquitetura do MU Mobile. A curva de aprendizado é muito menor no PC.

Perguntas frequentes

É possível criar um servidor privado de MU Mobile?

Tecnicamente sim, mas é significativamente mais complexo do que o MU PC. O cliente mobile usa API REST/WebSocket em vez de protocolo binário direto, e requer backend web completo.

MU Mobile usa o mesmo servidor que MU PC?

Não. São arquiteturas completamente diferentes. MU Mobile usa API web (HTTP/HTTPS + WebSocket), enquanto MU PC usa protocolo binário TCP direto.

Qual linguagem de programação o backend do MU Mobile usa?

Depende da implementação, mas em geral usa Node.js, Go, ou C# com ASP.NET para a API. Algumas implementações comunitárias usam PHP com WebSocket.

É necessário modificar o APK para conectar a um servidor privado?

Sim — o APK oficial aponta para os servidores da Webzen. Para conectar a um servidor privado, é necessário modificar o APK para apontar para o IP/URL do servidor privado.

EQ

Equipe ViciadosMU

Equipe editorial do ViciadosMU — portal de MU Online no ar desde 2003.

Continue lendo

Artigos relacionados