BungeeCord IP forwarding lets a backend receive the real player IP, online UUID, and profile data even though its TCP connection comes from the proxy. Four values must agree—and the backend port must reject direct connections.
ip_forward: trueis not a firewall. The classic BungeeCord format has no proxy-specific signature secret. Anyone who reaches an exposed offline-mode backend can forge forwarding data and impersonate another player.
The four settings
| Location | File/field | Normal value |
|---|---|---|
| BungeeCord | config.yml → online_mode |
true |
| BungeeCord | config.yml → ip_forward |
true |
| backend | server.properties → online-mode |
false |
| backend | spigot.yml → settings.bungeecord |
true |
Current Paper also uses:
# config/paper-global.yml
proxies:
bungee-cord:
online-mode: true
This Paper value matches the proxy's online mode. It remains true while backend server.properties uses online-mode=false.
Why backup comes first
Without forwarding, an offline-mode backend derives a UUID from the player name. With correct forwarding, it receives the UUID from online authentication. Those values are different. Inventory, Ender Chest, ranks, or economy data can appear missing even while the old records still exist.
Before changing anything:
- back up worlds,
playerdata, permission data, and plugin databases; - test a restore;
- record old and expected UUIDs for one test player;
- inspect plugin-specific migration tools;
- never rename files blindly without understanding references and format.
Use the backup, clone, and rollback path in the version-switch guide.
Step 1: Configure the proxy
Stop BungeeCord cleanly and edit the current config.yml:
online_mode: true
ip_forward: true
Keep public authentication active at the proxy. Check listeners, servers, and priorities with the config.yml reference.
Step 2: Configure each backend
Fully stop each backend and set:
# server.properties
online-mode=false
# spigot.yml
settings:
bungeecord: true
For Paper, also set the proxies.bungee-cord.online-mode value shown above. Start backends first and BungeeCord second. A partial reload is not sufficient for this identity change.
Step 3: Close the backend path
Allow each backend TCP port only from the verified proxy path. Depending on your infrastructure, that can be loopback, a genuine private network/VPN, or a narrow firewall rule. In containers, an internal IP by itself is insufficient: another tenant on the same bridge must not be accepted as the proxy.
At game-serverhosting, the active guard binds supported BungeeCord backends to the concrete proxy instance and re-resolves its current container source. A stopped, missing, or ambiguous source remains drop-only. Same-node, cross-node, and external-backend paths were checked with a real proxy join plus blocked independent direct access. This is evidence for those tested paths, not a blanket guarantee for another provider's network.
The complete setup guide explains the topology choices.
Position BungeeGuard correctly
BungeeGuard adds a shared token to the legacy format. Use version 1.4.0 or newer. The project's security page documents token exposure affecting older BungeeCord setups; after upgrading an affected installation, rotate the token on proxy and backends.
- generate the token locally with sufficient entropy;
- never paste it into tickets, logs, screenshots, or Git;
- update proxy and all backends as one coordinated change;
- remove the old token only after a successful test;
- treat unknown or old versions as unverified.
BungeeGuard is useful on shared hosting, but does not replace an available firewall or private network as the first protection layer.
Verification: four separate signals
- Process: proxy and backend finish starting.
- TCP: the proxy reaches the backend listener.
- Lobby join: a real authenticated player reaches the backend through the proxy.
- Identity: the backend sees the expected online UUID and client IP, not an offline UUID or only the proxy IP.
Then run the negative test: an independent source must not reach the backend port. An open listener or successful ping alone is not a join proof.
Common failures
| Symptom | Cause | Next step |
|---|---|---|
| every player has the proxy IP | ip_forward or bungeecord disabled |
check both sides and fully restart |
| player has a fresh inventory | UUID mode changed | keep backup, compare UUIDs, migrate per plugin |
If you wish to use IP forwarding... |
backend expects data the proxy does not send | verify proxy value and active config |
| direct join under another name works | backend is publicly reachable | fix firewall/private network immediately |
| proxy also cannot reach backend | allow source is wrong or stale | re-evaluate the assigned proxy; do not broadly open |
| join fails after BungeeGuard update | inconsistent token | check versions without exposing token, rotate together |
For a missing entry target, use the fallback error guide. DNS still points at the proxy; use the domain and SRV guide.
Plugins and crossplay
Permission, ban, and economy plugins are especially UUID-sensitive. Back up their data and check whether they need proxy and backend components. The plugin guide explains the platform boundary.
In a proxy network, Geyser is installed only on the proxy. Bedrock UDP and Java TCP remain separate paths, and key.pem is secret. Configure Geyser/Floodgate only after the Java forwarding and negative paths pass.