How to segregate your MU Online server's database network
Isolate the accounts, characters, and items database of your MU Online server into its own network, with IP-restricted access, least-privilege service accounts, and encryption in transit.
The database is the most critical asset of any private MU Online server: it holds accounts, passwords (hashed), characters, items, transaction history, and moderation logs. A database leak or compromise isn't just a technical incident — it's the end of the community's trust in the server. Segregatin
The database is the most critical asset of any private MU Online server: it holds accounts, passwords (hashed), characters, items, transaction history, and moderation logs. A database leak or compromise isn't just a technical incident — it's the end of the community's trust in the server. Segregating the database network means treating it with a level of isolation and control above the rest of the infrastructure, even if the overall network is already segmented. This tutorial details how to do this in practice: network isolation, least-privilege service accounts, encryption in transit, and secure backup.
Why the database deserves extra isolation
Even in an already-segmented infrastructure (public ConnectServer, internal GameServer, internal database), the database is usually the only component where a compromise has a catastrophic, irreversible impact — items and Zen can be recreated, but leaked account data (even hashed) and purchase history cannot. That's why the database justifies an extra layer: its own network, access accounts more restricted than those used by the GameServer for other purposes, and stricter auditing of who accesses it and when.
Isolating the database in its own subnet
Even inside an already-segmented VPC, put the database in a dedicated subnet, with no outbound route to the internet (egress blocked by default, except for explicitly allowed backup destinations):
VPC: 10.0.0.0/16
├── Public Subnet: 10.0.1.0/24
├── Application Subnet: 10.0.2.0/24 → GameServer
└── Database Subnet: 10.0.3.0/24 → MSSQL/MySQL (no route to the internet)
The absence of an outbound route to the internet means that even if the database is compromised, an attacker can't easily exfiltrate data directly outward — they would first need to compromise another component with an outbound route, adding an extra layer of difficulty.
Database-specific firewall rules
| Allowed source | Port | Purpose |
|---|---|---|
| GameServer internal IP | 1433 (MSSQL) / 3306 (MySQL) | Read/write of accounts, characters, items |
| Site internal IP (read-only) | Same port, account with SELECT permission only | Displaying ranking and public data |
| Internal backup server | Same port or replication port | Scheduled backup routine |
| Any other source | — | Blocked |
No rule should ever open the database port to 0.0.0.0/0 (any source) — this is the most common and most severe misconfiguration found in compromised private servers.
Least-privilege service accounts
A frequent mistake is using the database admin account (sa on MSSQL, root on MySQL) directly in the GameServer's configuration. Instead, create dedicated service accounts per purpose:
-- MSSQL: service account for the GameServer, with specific permissions
CREATE LOGIN gameserver_svc WITH PASSWORD = 'StrongRandomPassword!2026';
CREATE USER gameserver_svc FOR LOGIN gameserver_svc;
ALTER ROLE db_datareader ADD MEMBER gameserver_svc;
ALTER ROLE db_datawriter ADD MEMBER gameserver_svc;
-- No DROP, ALTER, or server control permission
-- Separate, read-only account for the site/ranking
CREATE LOGIN site_readonly WITH PASSWORD = 'AnotherStrongPassword!2026';
CREATE USER site_readonly FOR LOGIN site_readonly;
ALTER ROLE db_datareader ADD MEMBER site_readonly;
With this separation, even if the site's credential leaks (for example, through a CMS vulnerability), the attacker can only read data, never alter characters, items, or Zen balance.
Differentiating application and administration accounts
| Account | Use | Permissions |
|---|---|---|
gameserver_svc | Used by the GameServer process | Read/write on game tables, no DDL |
site_readonly | Used by the site for ranking/statistics | Read-only |
dba_admin | Used manually by admins for maintenance | Full privilege, but login restricted by IP and with MFA when possible |
backup_svc | Used by the scheduled backup job | Backup permission only (db_backupoperator), not data read |
Never reuse the same credential across different purposes — this eliminates the ability to trace which component performed which action in the event of an incident.
Encrypting the connection in transit
Enable TLS on the connection between the GameServer/site and the database, especially if the components aren't on the same physical machine. For MSSQL, this is configured in SQL Server Configuration Manager (Force Encryption) and in the GameServer's connection string:
[Database]
Server=10.0.3.10
Database=MuOnline
User=gameserver_svc
Password=StrongRandomPassword!2026
Encrypt=yes
TrustServerCertificate=no
For MySQL, use require_secure_transport=ON in the server configuration and ssl-mode=REQUIRED in the client connection string. TLS's performance cost is low compared to the risk of credentials and data traveling in plain text within the internal network.
Secure, isolated backup
The backup job should run within the same private segment as the database, never pulled from outside via an inbound connection. The recommended flow:
- The database server (or an internal backup server in the same segment) runs the backup locally, generating the
.bak/dump file. - An outbound (egress) firewall rule, not an inbound one, allows that server to send the file to an external destination (cloud storage, another datacenter).
- The external destination has its own access control (encryption at rest, versioning, retention).
#!/bin/bash
# Runs locally within the database segment
BACKUP_FILE="/backups/mu_$(date +%Y%m%d).bak"
sqlcmd -S localhost -Q "BACKUP DATABASE MuOnline TO DISK='$BACKUP_FILE'"
# Send to external storage via egress opened specifically for this destination
aws s3 cp "$BACKUP_FILE" s3://mu-backups-private/ --sse AES256
Never open an inbound port on the database segment just to let an external script "pull" the backup — this reintroduces exactly the exposure segregation was meant to eliminate.
Auditing database access
Enable logging of connections and sensitive queries (login, DDL, permission changes) on the database itself:
-- MSSQL: login auditing
CREATE SERVER AUDIT MuServerAudit
TO FILE (FILEPATH = 'C:\AuditLogs\')
WITH (ON_FAILURE = CONTINUE);
CREATE SERVER AUDIT SPECIFICATION MuLoginAudit
FOR SERVER AUDIT MuServerAudit
ADD (FAILED_LOGIN_GROUP), ADD (SUCCESSFUL_LOGIN_GROUP)
WITH (STATE = ON);
Review these logs periodically (ideally with automatic alerting) to detect login attempts with unexpected accounts or from unusual IPs.
Separating environments (production, staging, development)
Never share the same database between production and test environments. A staging database should run in its own subnet, with synthetic data or an anonymized copy of production (no real passwords, no payment data), preventing an error in a test script from affecting real players.
| Environment | Network | Data |
|---|---|---|
| Production | Dedicated private subnet, restricted access | Real player data |
| Staging | Separate subnet, isolated from production | Anonymized copy or synthetic data |
| Local development | Developer's machine, no external access | Synthetic data only |
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Database reachable from any IP | Firewall rule with source 0.0.0.0/0 | Restrict to specific sources (GameServer, backup, read-only site) |
| Admin credential used by the GameServer | Initial setup using sa/root directly | Create a service account with minimal permissions (db_datareader/db_datawriter) |
| Data traveling without encryption | TLS not enabled in the connection string | Enable Encrypt=yes/ssl-mode=REQUIRED depending on the DBMS |
| Backup exposes an inbound port on the database segment | External script "pulling" the backup via inbound connection | Run the backup locally and send it via egress opened specifically for that |
| Staging environment using the production database | No separate test database provisioned | Provision an isolated staging database with synthetic or anonymized data |
Database network segregation checklist
- Database in its own subnet, with no default outbound route to the internet.
- Firewall allowing only specific sources (GameServer, backup, read-only site).
- Least-privilege service accounts, separated by purpose.
- TLS enabled on the connection between the application and the database.
- Backup run locally within the segment, sent via controlled egress.
- Login and sensitive action auditing enabled on the database.
- Production, staging, and development environments fully separated.
With the database properly isolated, also review the segmentation of the other infrastructure components — see the GameServer network segmentation tutorial to make sure the whole chain, from the client to the most sensitive data, is protected consistently.
Frequently asked questions
What's the difference between segmenting the GameServer network and segregating the database network?
They're complementary. Segmenting the GameServer network isolates the application components (ConnectServer, GameServer, site) from each other; segregating the database network goes further, treating the database as the most critical asset and applying additional specific controls — encryption, least-privilege service accounts, isolated backup.
Do I need a fully physically separate database server?
Not necessarily physically separate, but logically isolated — in its own subnet, with no direct route to the internet, with a firewall restricting who can connect. On cloud providers, this is done with private subnets and security groups, at no additional hardware cost.
Is it worth encrypting the connection between the GameServer and the database?
Yes, especially if the two components aren't on the same physical machine or if the internal network isn't fully trusted (e.g. a shared network from a hosting provider). TLS on the database connection (MSSQL/MySQL) has a low performance cost and prevents credentials and data from traveling in plain text.
How do I back up a database that's isolated with no internet access?
Configure the backup job to run locally on the database server itself, or on a dedicated backup server within the same private segment, sending the generated files to an external destination (cloud storage, another datacenter) through a specific outbound firewall rule, not an inbound one.
Is an administrator-privilege database account (sa/root) really a problem if only the GameServer uses it?
Yes. If the GameServer is compromised (through a code vulnerability, for example), an attacker with access to the admin database credential can do anything — drop tables, exfiltrate everything, create persistent access accounts. A service account with minimal permissions limits the possible damage even in that scenario.