minecraft_protocol: foundation + per-version protocol docs 1.7.10->26.2
8 topical docs (overview, data types, lifecycle, handshake, status/ping, login+encryption, configuration, version-differences) + proxy-forwarding set + 16 per-version release-line docs, sourced from minecraft.wiki, ViaVersion (source + commits), minecraft-data, node-minecraft-protocol, Velocity, BungeeCord. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# BungeeGuard
|
||||
|
||||
A **hardening of [legacy forwarding](bungeecord-legacy.md)**, not a new transport. Legacy's fatal flaw is that anyone who can reach the backend port can forge the `\0`-delimited identity string and connect as anyone. BungeeGuard fixes that by smuggling a **shared secret token** into the forwarded data; the backend plugin refuses the login unless the token matches. It bridges backends that **only support legacy forwarding** up to "can't be trivially forged," without requiring [modern/Velocity](velocity-modern.md) support.
|
||||
|
||||
It is **third-party** — not part of Spigot/Paper core or the Mojang protocol. The original is the [BungeeGuard plugin](https://github.com/lucko/BungeeGuard) (lucko), installed on both the proxy and every backend.
|
||||
|
||||
## How it works
|
||||
|
||||
BungeeGuard reuses the exact legacy wire format — the four `\0`-separated handshake-address segments (`realHost\0clientIP\0uuidNoDashes\0propertiesJSON`). The trick is in the **properties JSON**: it appends one **synthetic game-profile property** named **`bungeeguard-token`** whose value is the shared secret.
|
||||
|
||||
A game-profile property is a `{name, value, signature?}` object — the same shape as the Mojang `textures` property. BungeeGuard injects an extra one:
|
||||
|
||||
```json
|
||||
[
|
||||
{ "name": "textures", "value": "...", "signature": "..." },
|
||||
{ "name": "bungeeguard-token","value": "<the shared secret>" }
|
||||
]
|
||||
```
|
||||
|
||||
On the backend, the BungeeGuard plugin (replacing the stock legacy parser) reads the player's properties, finds the `bungeeguard-token` entry, and compares its value against the secret it was configured with. Match → accept and strip the token; mismatch or absent → reject the connection. The real IP/UUID/skin are still taken from the same legacy segments.
|
||||
|
||||
Velocity has this mode built in (`player-info-forwarding-mode = "legacy"` is bare legacy; `"bungeeguard"` adds the token). Its source builds the address identically to legacy and just adds the token property:
|
||||
|
||||
> ```java
|
||||
> private static final String BUNGEE_GUARD_TOKEN_PROPERTY_NAME = "bungeeguard-token";
|
||||
> ...
|
||||
> final GameProfile.Property property = new GameProfile.Property(
|
||||
> BUNGEE_GUARD_TOKEN_PROPERTY_NAME,
|
||||
> new String(forwardingSecret, StandardCharsets.UTF_8),
|
||||
> "");
|
||||
> return createLegacyForwardingAddress(serverAddress, playerAddress, profile,
|
||||
> properties -> ImmutableList.<GameProfile.Property>builder()
|
||||
> .addAll(properties).add(property).build());
|
||||
> ```
|
||||
>
|
||||
> — `Velocity/proxy/src/main/java/com/velocitypowered/proxy/connection/PlayerDataForwarding.java:52` (name) + `:175-196` (`createBungeeGuardForwardingAddress`)
|
||||
|
||||
So a BungeeGuard handshake address is exactly a legacy one with one extra property in the JSON array.
|
||||
|
||||
## Security: better than legacy, weaker than modern
|
||||
|
||||
| | bare legacy | BungeeGuard | modern (Velocity) |
|
||||
|---|---|---|---|
|
||||
| Forge-able by anyone reaching the port | **Yes** | No (needs the token) | No (needs the secret) |
|
||||
| Secret/token crosses the wire | n/a | **Yes — token sent in cleartext** inside the connection | No (only an HMAC crosses) |
|
||||
| Tamper-proofs IP/UUID/props | No | **No** — only gate-keeps; the identity fields are still unsigned plaintext | **Yes** — whole payload is HMAC'd |
|
||||
| Backend requirement | core `bungeecord:true` | BungeeGuard plugin | Paper/Fabric modern support |
|
||||
|
||||
The crucial limitation: BungeeGuard is **authentication of the connection, not authentication of the payload**. It proves "whoever sent this knows the token," but the IP/UUID/properties themselves are not signed — once the token check passes, those fields are trusted as-is, exactly like legacy. And the token is transmitted **in cleartext** in the handshake. So:
|
||||
|
||||
- If the connection between proxy and backend is **not** encrypted/private, a network observer can lift the token and then forge freely.
|
||||
- The token is a single shared value across all backends; leaking it from any one host compromises all.
|
||||
|
||||
It is a real improvement over bare legacy (you no longer rely solely on a firewall) and the right choice for a backend that **cannot** do modern forwarding. But when every backend supports it, **[modern/Velocity forwarding](velocity-modern.md) is strictly stronger** — it signs the payload with an HMAC and never puts the secret on the wire.
|
||||
|
||||
## When to use it
|
||||
|
||||
- A backend (old Spigot, a plugin platform, a Fabric server without modern-forward support) only speaks **legacy**, and you can't firewall it tightly enough to trust bare legacy.
|
||||
- You're migrating a BungeeCord/Waterfall network and want hardening without switching every backend to Velocity-native forwarding.
|
||||
|
||||
Otherwise prefer modern. See the [README comparison table](README.md#comparison).
|
||||
|
||||
---
|
||||
|
||||
**Sources**
|
||||
|
||||
- `Velocity/proxy/src/main/java/com/velocitypowered/proxy/connection/PlayerDataForwarding.java:52` (`bungeeguard-token` property name), `:175-196` (`createBungeeGuardForwardingAddress` — legacy address + token property), `:154-173` (shared `createLegacyForwardingAddress` it builds on).
|
||||
- [lucko/BungeeGuard](https://github.com/lucko/BungeeGuard) — the original third-party plugin (token property + backend check). <!-- VERIFY: plugin-side check logic from upstream README, not read from cloned source -->
|
||||
- See [bungeecord-legacy.md](bungeecord-legacy.md) for the underlying `\0`-delimited wire format BungeeGuard extends.
|
||||
Reference in New Issue
Block a user