Skip to content

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:

  1. Handshake & Login: The player authenticates with Velocity. Velocity initiates a standard TCP connection to Pumpkin and transmits SHandshake and SLoginStart.
  2. Channel Query: Recognizing that Velocity modern forwarding is enabled, Pumpkin pauses the login sequence and dispatches a CLoginPluginRequest on channel velocity:player_info.
  3. 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.
  4. 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 to Config / 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

  1. Open velocity.toml on your Velocity proxy and set:
    toml
    player-info-forwarding-mode = "modern"
    forwarding-secret-file = "forwarding.secret"
  2. Copy the generated secret string from forwarding.secret into pumpkin.toml:
    toml
    [networking.proxy]
    enabled = true
    
    [networking.proxy.velocity]
    enabled = true
    secret = "YOUR_VELOCITY_FORWARDING_SECRET_HERE"

Uitgebracht onder de MIT-licentie.