How to set up a TCP proxy to hide your MU server's real IP
Learn how to place a TCP proxy in front of your MU Online server to hide the game machine's real IP and survive DDoS attacks.
Hiding the game server's real IP is one of the first serious defenses a MU Online administrator needs to implement. As soon as promotion begins, the public address circulates in forums, screenshots, and clients, and with it come the denial-of-service attacks. If that address points directly to the m
Hiding the game server's real IP is one of the first serious defenses a MU Online administrator needs to implement. As soon as promotion begins, the public address circulates in forums, screenshots, and clients, and with it come the denial-of-service attacks. If that address points directly to the machine running the GameServer and the database, a single well-aimed attack knocks all players offline and even threatens the integrity of the data. The classic solution is to insert a TCP proxy between the internet and the game machine: players connect to the proxy, the proxy relays the traffic to the real server through a private path, and the real IP never appears to the public.
In this tutorial you'll build that layer from scratch, understand why it works, configure port forwarding for the ConnectServer and the GameServers, armor the game machine with a firewall, and avoid the most common IP leaks. The port values, IPs, and file names here are examples and vary by provider/version of your emulator, but the concepts are real and apply to any Season.
What a TCP proxy is and why it hides the IP
A TCP proxy is an intermediary server that accepts connections on a port, opens a second connection to the real destination, and copies the bytes from one side to the other. To the MU client, the proxy is the server: the entire handshake, the login, and the game traffic pass through it. The machine that actually processes the game world only receives connections coming from the proxy, through an address the public doesn't know.
The practical effect is that the announced IP (the one that goes in the client, on the site, and in the ServerList) is the proxy's IP, a cheap and disposable machine. The origin IP (the game machine with the database, accounts, and items) stays hidden behind a firewall. If the proxy goes down under attack, you swap the proxy machine without losing anything; the game server stays untouched. It's the difference between losing an expendable piece and losing the crown.
There are three common approaches for this layer, summarized below.
| Approach | How it works | When to use |
|---|---|---|
| Dedicated L4 proxy (HAProxy/nginx stream) | You run the proxy software on a separate VPS | Full control, low cost, more manual work |
| GRE/tunnel + provider's filtered IP | The provider delivers a protected IP and tunnels to you | Stronger protection, depends on a specialized provider |
| Simple forwarding (iptables DNAT/socat) | A kernel rule or lightweight binary relays the port | Small setups, tests, lab |
This tutorial focuses on the first approach because it's the most instructive and reproducible, with notes on the others.
Prerequisites
Before you start, have on hand:
- A separate VPS for the proxy, in the same region as the game server, with a dedicated public IP. It doesn't need to be powerful: a modest CPU and good network are enough. A common example: 1 vCPU, 1-2 GB of RAM, 1 Gbps network (varies by provider).
- The game server already working, with the ConnectServer, JoinServer, and at least one GameServer running and tested on the local network or via the direct IP. If you're still building this, see the how to create a MU Online server guide before proceeding.
- Administrative access to both machines (RDP/SSH depending on the OS).
- The list of TCP ports your emulator uses. Frequent examples: ConnectServer on 44405, GameServer on 55901/55902, JoinServer on an internal port. Confirm in your emulator's configuration files, since they vary by version.
- Basic knowledge of firewalls (Windows Firewall or iptables/nftables) and of editing MU's configuration files (ServerList, GameServerInfo).
Note down the private IP that will link the proxy and the game machine. Ideally, use a private network between the two VPS (many providers offer an internal VLAN). If there's no private network, use the game machine's public IP, but restrict it by firewall to accept only the proxy's IP.
Step 1 — Provision and prepare the proxy VPS
Create the proxy VPS and, as soon as it's up, do the basic hygiene:
- Update the operating system (security packages current).
- Create an administrative user and disable direct root login by password, preferring a key.
- Install the proxy software. On Linux, HAProxy is the most robust choice for TCP; alternatives are nginx with the stream module or socat for simple forwarding.
- Note the public IP (it will be the announced IP) and the private IP of the internal network with the game machine.
Example of installing HAProxy on a Debian-based distribution:
sudo apt update
sudo apt install -y haproxy
haproxy -v # confirms the installed version
The exact version number and package names vary by distribution, so treat this as an example.
Step 2 — Map MU's ports on the proxy
Now you declare, on the proxy, each port the public needs to reach and where it should be relayed. Each MU service becomes a block of "listen on the public port, send to the game server's private IP".
An example HAProxy configuration (/etc/haproxy/haproxy.cfg) for the ConnectServer and two GameServers:
global
log /dev/log local0
maxconn 20000
defaults
mode tcp
timeout connect 5s
timeout client 1m
timeout server 1m
log global
option tcplog
# ConnectServer
frontend cs_front
bind *:44405
default_backend cs_back
backend cs_back
server cs1 10.0.0.20:44405 check
# GameServer 1
frontend gs1_front
bind *:55901
default_backend gs1_back
backend gs1_back
server gs1 10.0.0.20:55901 check
# GameServer 2
frontend gs2_front
bind *:55902
default_backend gs2_back
backend gs2_back
server gs2 10.0.0.20:55902 check
Here, 10.0.0.20 is the game machine's example private IP. Ports 44405, 55901, and 55902 are examples; use the real ones from your emulator. The mode tcp is essential — MU doesn't speak HTTP, so the proxy has to operate at layer 4, simply relaying bytes.
After saving, validate and reload:
haproxy -c -f /etc/haproxy/haproxy.cfg # checks the syntax
sudo systemctl restart haproxy
If you use socat for a quick test of a single port, the equivalent is:
socat TCP-LISTEN:44405,fork,reuseaddr TCP:10.0.0.20:44405
socat is great for validating the concept, but I don't recommend it in production because it has no health check, connection limits, or managed restart.
Step 3 — Armor the game machine with a firewall
This step is the one that really protects the real IP. The proxy is useless if the game machine keeps accepting connections from anywhere via the public IP. The game machine's firewall must accept MU's ports only from the proxy's IP.
On Linux with nftables/iptables, the principle is: deny everything on the game ports and allow an exception for the proxy.
# iptables example — allows MU ports only from the proxy's IP (10.0.0.10)
iptables -A INPUT -p tcp -s 10.0.0.10 --dport 44405 -j ACCEPT
iptables -A INPUT -p tcp -s 10.0.0.10 --dport 55901 -j ACCEPT
iptables -A INPUT -p tcp -s 10.0.0.10 --dport 55902 -j ACCEPT
iptables -A INPUT -p tcp --dport 44405 -j DROP
iptables -A INPUT -p tcp --dport 55901 -j DROP
iptables -A INPUT -p tcp --dport 55902 -j DROP
On Windows Server (common in emulators based on MU executables), use the Windows Firewall with Advanced Security:
- Create an inbound rule for each MU port.
- Under "Scope", restrict the remote IP address to the proxy's IP.
- Block any other source for those ports.
- Keep RDP restricted to your administration IP, never open to the world.
The golden rule: if a player can connect by pointing the client at the game machine's real IP, your armoring has failed. Test this from the outside.
Step 4 — Adjust the ServerList and the announced IP
The MU client first connects to the ConnectServer, which returns a server list with addresses. If that list contains the game machine's real IP, all the effort goes down the drain: the server itself hands over the secret. Therefore, everything announced to the client must point to the proxy's IP.
The points that tend to leak the real IP:
- The ConnectServer's configuration file (ServerList) that lists the GameServers.
- The client's
main.dll/config with the ConnectServer's IP embedded. - The website and the launcher, which sometimes have the IP hardcoded.
- Publicly exposed logs or status pages.
Adjust every reference to the proxy's public IP. In the client, the configured IP must be the proxy's; in the ConnectServer's ServerList, each GameServer's address must also be the proxy's IP (with the corresponding port the proxy listens on). File names vary by emulator and Season, so locate the equivalent in your version.
Step 5 — Test from outside the network
Testing from inside your own network is deceptive. Do the test the way a player would, from an external connection:
- Point a clean client at the proxy's IP and confirm login, character selection, and entering the world.
- Check the latency: a few extra milliseconds are normal; dozens more indicate the proxy is too far away.
- Deliberately try to connect to the game machine's real IP — it should fail. If it connects, the firewall is loose.
- Run a simple port scanner against the real IP to confirm that the MU ports appear closed from the outside.
A quick expected-result verification table:
| Test | Target | Expected result |
|---|---|---|
| Normal login | Proxy IP | Success |
| Direct connection | Game machine's real IP | Refused/timeout |
| Port scan | Real IP | MU ports closed |
| Latency | Proxy IP | A few ms above direct |
Step 6 — Harden the proxy against abuse
The proxy is now the public face, so it too needs care. Good practices:
- Connection limit per IP: HAProxy allows a
stick-tableto count and block IPs that open too many connections, mitigating simple connection-layer floods. - maxconn tuned: prevents the proxy from exhausting memory under a spike.
- Short timeouts for idle connections, freeing resources.
- Logs enabled so you can identify attack patterns and abusive IPs.
- Fail2ban or equivalent to ban IPs with repeated anomalous behavior.
Example of a stick-table to limit simultaneous connections per IP in HAProxy:
backend gs1_back
stick-table type ip size 100k expire 30s store conn_cur
tcp-request connection track-sc0 src
tcp-request connection reject if { sc0_conn_cur gt 30 }
server gs1 10.0.0.20:55901 check
The 30 connections per IP limit is an example; adjust it according to your players' legitimate behavior, which varies by client version.
Step 7 — Redundancy and quick proxy swap
The real value of this architecture appears when the proxy is attacked. Since it's disposable, prepare to swap it quickly:
- Keep the proxy configuration versioned (a file you can reapply in minutes on a new VPS).
- Have a second IP or a second proxy VPS ready to step in.
- Use DNS with a low TTL pointing to the proxy, if the client resolves by hostname, to redirect players without updating the client.
- Consider two simultaneous proxies on distinct ConnectServers to avoid a single point of failure.
The ideal swap is: proxy A goes down under attack, you bring up proxy B with the same config file, point the DNS/ConnectServer at B, and players return, all without ever exposing the game machine.
Common errors and fixes
| Error | Symptom | Fix |
|---|---|---|
| ServerList with the real IP | Players discover and attack the real IP | Change all announced addresses to the proxy's IP |
| Game machine's firewall open | Direct connection to the real IP works | Restrict MU ports to the proxy's IP only and drop the rest |
Proxy in mode http | Login hangs, traffic corrupted | Use mode tcp in HAProxy; MU is not HTTP |
| GameServer port not mapped | Login works but you can't enter the world | Add a frontend/backend for each GameServer port |
| High latency | Ping rises a lot after the proxy | Place the proxy in the same region as the game machine |
| RDP/SSH exposed | Brute force attempts on the proxy | Restrict administrative access to your IP and use a key |
| No connection limit | A simple flood takes the proxy down | Configure stick-table and maxconn |
Launch checklist
- Proxy VPS provisioned in the same region as the game machine
- Private network (or restricted firewall) between the proxy and the game server
- HAProxy installed and config validated with
haproxy -c - All MU ports (ConnectServer, JoinServer, each GameServer) mapped
- Game machine's firewall accepts MU ports only from the proxy's IP
- ServerList and announced IP point to the proxy, never to the real IP
- Client, site, and launcher with no real IP embedded
- External test: login through the proxy works
- External test: direct connection to the real IP fails
- External scan confirms MU ports closed on the real IP
- Stick-table and maxconn configured against flooding
- Proxy config versioned for a quick swap
- Second backup proxy/IP prepared
Conclusion
A well-configured TCP proxy is the boundary between a server that survives the first wave of attacks and one that shuts down on the first busy weekend. The logic is simple: expose a sacrificial machine, hide the valuable machine, and close the firewall so the real IP never appears to the public. Once done, you gain time, resilience, and the peace of mind of swapping the proxy without touching the heart of the server. Treat the ports, IPs, and versions in this guide as examples and adapt them to your Season, but keep the principles: machine separation, firewall armoring, and zero IP leakage in the ServerList.
Frequently asked questions
Do I need a proxy if my server is small?
Yes, even small servers are attack targets. A cheap proxy already hides the real IP and prevents a single attacker from taking your game machine down directly.
Does the proxy increase players' ping?
It adds a few milliseconds, usually between 2 and 15 ms if the proxy is near the game machine. Choosing a provider in the same region reduces that impact to a minimum.
Can I use the same proxy for the ConnectServer and the GameServer?
Yes, you map several TCP ports on the same proxy. It's common to forward the ConnectServer, JoinServer, and each GameServer's ports through the same public address.
Can a player still discover the real IP even with a proxy?
If the configuration is correct and the firewall blocks everything that doesn't come from the proxy, no. Leaks happen through config errors, such as the server announcing its internal IP in the ServerList.
Does a TCP proxy replace a professional anti-DDoS service?
For large attacks, no. It hides the IP and absorbs small attacks, but high volumes require dedicated mitigation at the edge or a provider with protection included.