Velocity Modern Forwarding
Velocity is a high-performance proxy created by PaperMC. It uses modern plugin messaging during the Login state to securely transmit player data with HMAC-SHA256 message authentication codes.
Pumpkin implements Velocity modern forwarding in crates/pumpkin/src/net/proxy/velocity.rs.
How Velocity Forwarding Operates
Unlike BungeeCord, which injects unauthenticated data into the handshake string, Velocity operates during the Login state over a dedicated plugin channel:
- Handshake & Login: The player authenticates with Velocity. Velocity initiates a standard TCP connection to Pumpkin and transmits
SHandshakeandSLoginStart. - Channel Query: Recognizing that Velocity modern forwarding is enabled, Pumpkin pauses the login sequence and dispatches a
CLoginPluginRequeston channelvelocity:player_info. - Payload Generation: Velocity bundles the player's remote address, UUID, username, and skin textures. It calculates a 32-byte HMAC-SHA256 signature across this payload using the shared secret.
- Signature Verification: Velocity sends
SLoginPluginResponse. Pumpkin validates the HMAC-SHA256 digest against its configured secret. If valid, Pumpkin overwrites the connection's network address and GameProfile and transitions toConfig/Play.
Wire Payload Structure
The payload in SLoginPluginResponse is structured as follows:
text
┌─────────────────────────────────────────────────────────────┐
│ 32-byte HMAC-SHA256 Signature │
├─────────────────────────────────────────────────────────────┤
│ Forwarding Protocol Version (VarInt: 1 - 4) │
├─────────────────────────────────────────────────────────────┤
│ Client Remote IP Address (String / IPv4 / IPv6) │
├─────────────────────────────────────────────────────────────┤
│ Player UUID (128-bit / UUID) │
├─────────────────────────────────────────────────────────────┤
│ Player Username (String) │
├─────────────────────────────────────────────────────────────┤
│ Profile Properties Count (VarInt) │
│ ├─ Property Name (String) │
│ ├─ Property Value (String) │
│ └─ Optional Signature (String) │
└─────────────────────────────────────────────────────────────┘Cryptographic Validation in Pumpkin
Inside crates/pumpkin/src/net/proxy/velocity.rs:
rust
use hmac::{Hmac, KeyInit, Mac};
use sha2::Sha256;
type HmacSha256 = Hmac<Sha256>;
// Extract signature and payload
let (signature, data_to_verify) = data.split_at(32);
// Initialize HMAC with secret from pumpkin.toml
let mut mac = HmacSha256::new_from_slice(secret.as_bytes())
.map_err(|_| VelocityError::FailedVerifyIntegrity)?;
mac.update(data_to_verify);
// Constant-time verification prevents timing attacks
mac.verify_slice(signature)
.map_err(|_| VelocityError::FailedVerifyIntegrity)?;If the signature does not match (e.g., if an attacker attempts to connect directly to the backend without knowing the secret), Pumpkin drops the connection immediately.
Configuration in pumpkin.toml
- Open
velocity.tomlon your Velocity proxy and set:tomlplayer-info-forwarding-mode = "modern" forwarding-secret-file = "forwarding.secret" - Copy the generated secret string from
forwarding.secretintopumpkin.toml:toml[networking.proxy] enabled = true [networking.proxy.velocity] enabled = true secret = "YOUR_VELOCITY_FORWARDING_SECRET_HERE"