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,66 @@
|
||||
# Proxy Forwarding Modes
|
||||
|
||||
How a Minecraft proxy moves a player between backend servers — and how it securely tells each backend *who the player is*.
|
||||
|
||||
This is the most load-bearing section of the reference. Get forwarding wrong and you either (a) break logins, or (b) open your network to anyone connecting as anyone.
|
||||
|
||||
## What a proxy does
|
||||
|
||||
A Minecraft proxy (BungeeCord, Waterfall, [Velocity](https://github.com/PaperMC/Velocity)) sits in front of *N* backend servers (lobby, survival, minigames, modded, …). The player's client connects **once** to the proxy. The proxy speaks the full client-facing protocol — handshake, login, encryption, online-mode auth against Mojang — and then opens its *own* connection to a backend server and pumps packets between the two. When the player runs `/server survival`, the proxy silently tears down the backend connection and opens a new one to a different backend, all without the client reconnecting.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
actor C as "Client (player)"
|
||||
participant P as "Proxy (Velocity/BungeeCord)"
|
||||
participant L as "Backend: lobby (offline-mode)"
|
||||
participant S as "Backend: survival (offline-mode)"
|
||||
C->>P: "connect once (online-mode auth here)"
|
||||
P->>L: "open backend conn + forward identity"
|
||||
L-->>C: "play (via proxy relay)"
|
||||
Note over C,S: "player runs /server survival"
|
||||
P->>S: "open new backend conn + forward identity"
|
||||
S-->>C: "play (via proxy relay)"
|
||||
```
|
||||
|
||||
## Why forwarding exists
|
||||
|
||||
The proxy already authenticated the player against Mojang. The **backends must not** repeat that — they run in **offline mode** (`online-mode=false`), because:
|
||||
|
||||
- A backend in online mode would demand its *own* Mojang session handshake from the connecting party (the proxy), which the proxy can't satisfy on the player's behalf.
|
||||
- Running backends offline lets the proxy own a single client connection and freely re-point it.
|
||||
|
||||
But an offline-mode server, by itself, knows nothing real about who connected. It only sees a username string in `LoginStart`, and it derives an **offline UUID** from that name (see [online-offline-modes.md](online-offline-modes.md)). So the proxy must *forward* the player's real identity to the backend:
|
||||
|
||||
- real **client IP** (so the backend sees the player, not the proxy)
|
||||
- real **UUID** (the Mojang account UUID for premium players)
|
||||
- **username**
|
||||
- **game-profile properties** — the `textures` property (skin/cape) and, on newer versions, the player's signature/public key
|
||||
|
||||
And — critically — the backend must be able to **trust** that this forwarded identity actually came from the proxy and not from an attacker who found the backend's port. That trust mechanism is what distinguishes the modes.
|
||||
|
||||
## The menu of modes
|
||||
|
||||
| Mode | Doc | One-line |
|
||||
|---|---|---|
|
||||
| **none** | [online-offline-modes.md](online-offline-modes.md) | No forwarding. Backend uses the raw `LoginStart` name → offline UUID. Only safe if the backend is the edge. |
|
||||
| **legacy / bungeecord** | [bungeecord-legacy.md](bungeecord-legacy.md) | Proxy stuffs `ip\0uuid\0properties` into the handshake address field. **No crypto.** |
|
||||
| **bungeeguard** | [bungeeguard.md](bungeeguard.md) | Legacy + a shared secret token smuggled in the forwarded properties. Third-party. |
|
||||
| **modern / velocity** | [velocity-modern.md](velocity-modern.md) | Backend requests identity via a Login Plugin message; proxy replies with an **HMAC-SHA256-signed** payload. Gold standard. |
|
||||
|
||||
## Comparison
|
||||
|
||||
| Mode | Crypto? | Backend support needed | Spoofable if backend port exposed? | Forge-friendly |
|
||||
|---|---|---|---|---|
|
||||
| **none** | — | none (default offline behavior) | **Yes** — anyone can claim any name | n/a |
|
||||
| **legacy (BungeeCord)** | None | Spigot/Paper `settings.bungeecord: true` (or Fabric equiv.) | **Yes** — forge the `\0`-delimited string | Yes — `\0FML\0` marker rides in the handshake (see [forge-fml.md](forge-fml.md)) |
|
||||
| **bungeeguard** | Shared secret (plaintext token, compared by the backend plugin) | Legacy forwarding **+** BungeeGuard plugin on the backend | **No** (attacker lacks the token), *but* the token travels in plaintext inside the connection | Yes — same handshake-field transport as legacy |
|
||||
| **modern (Velocity)** | **HMAC-SHA256** over the payload, keyed by a shared secret | Paper `velocity.enabled`+`velocity.secret` (or Fabric/Forge mod that implements it) | **No** — attacker can't produce a valid HMAC without the secret | Needs care — see [forge-fml.md](forge-fml.md) (the FML handshake competes with the login-plugin channel) |
|
||||
|
||||
**Rule of thumb**: use **modern/Velocity** when every backend supports it; fall back to **bungeeguard** when a backend only speaks legacy; use bare **legacy** only inside a network where the backend ports are firewalled so *only the proxy* can reach them; use **none** only when the server is itself the internet edge in online mode.
|
||||
|
||||
> The "exposed port" risk is the whole point. With legacy and none, your only defense is the firewall — bind backends to localhost / a private interface and let only the proxy connect. With bungeeguard and modern, the protocol itself rejects forged identities. See [online-offline-modes.md](online-offline-modes.md#security-model) for why offline backends are open by default.
|
||||
|
||||
## Mapping to the automc platform
|
||||
|
||||
In the automc stack, each backend Minecraft server runs with a **Velocity sidecar** managed by `mc-wrapper` (the wrapper runs the proxy alongside the MC server in the same pod). `mc-wrapper`'s `PROXY_MODE` concept selects which of these forwarding modes the sidecar↔server pair uses — practically that means **modern/Velocity forwarding** (the [velocity-modern.md](velocity-modern.md) path) with a shared secret, since proxy and server are co-located and the wrapper provisions the secret. This doc set is the protocol-level reference behind that knob; the automc-specific wiring lives in the `mc-wrapper` repo, not here.
|
||||
Reference in New Issue
Block a user