Skip to main content
The KYBER Proxy is a high-performance Rust service that acts as a WebSocket gateway, routing game client connections to private servers while handling authentication, connection management, and traffic optimization.

Overview

The Proxy serves as the critical networking layer that:
  • Accepts WebSocket connections from game clients
  • Validates JWT authentication tokens with JWKS
  • Routes traffic between clients and game servers
  • Manages connection lifecycle and reconnection logic
  • Provides real-time connection monitoring
  • Handles network protocol translation
The Proxy enables private server functionality by intercepting and redirecting game traffic without requiring EA’s official servers.

Tech Stack

Language

Rust (stable/nightly)

Runtime

Tokio async runtime

WebSockets

Tokio-Tungstenite

RPC

Tonic (gRPC)

Key Dependencies

Cargo.toml
[package]
name = "kyber_proxy"
version = "0.1.0"
edition = "2021"

[dependencies]
tokio = { version = "1.35", features = ["full"] }
tonic = "0.10.2"              # gRPC framework
prost = "0.12"                # Protocol Buffers
tokio-tungstenite = "0.21"    # WebSocket implementation
futures-util = "0.3"          # Async utilities
jsonwebtoken = "9.3"          # JWT validation
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.11", features = ["json"] }
log = "0.4"                   # Logging facade
env_logger = "0.11"           # Logger implementation
sentry = "0.45"               # Error tracking
dashmap = "5.5"               # Concurrent HashMap
percent-encoding = "2.3"      # URL encoding

Architecture

The Proxy uses an async, event-driven architecture:
src/
├── main.rs              # Entry point, WebSocket listener
├── user_manager.rs      # Connection state management
├── jwks.rs              # JWT key set management
├── grpc_client.rs       # gRPC API client
├── utils.rs             # Helper functions
└── proto/
    └── kyber.proto      # Protocol definitions

Core Components

use tokio::net::{TcpListener, TcpStream};
use tokio_tungstenite::accept_hdr_async;
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    env_logger::init();
    
    // Initialize Sentry for error tracking
    let _guard = sentry::init(("https://...", sentry::ClientOptions {
        release: sentry::release_name!(),
        send_default_pii: true,
        ..Default::default()
    }));
    
    // Load JWKS for JWT validation
    let jwks_url = env::var("JWKS_URL")?;
    let jwks_manager = Arc::new(JwksManager::new(jwks_url.clone()));
    jwks_manager.refresh_jwks_safe().await;
    
    // Start periodic JWKS refresh
    let refresh_interval = Duration::from_secs(3600);
    jwks_manager.clone().start_periodic_refresh(refresh_interval);
    
    // Bind WebSocket listener
    let addr = format!("{}:{}", 
        env::var("SERVER_IP").unwrap_or("0.0.0.0".to_string()),
        env::var("SERVER_PORT").unwrap_or("8080".to_string())
    );
    
    let socket = TcpListener::bind(&addr).await?;
    info!("Listening on: {}", addr);
    
    let user_manager = UserManager::new();
    
    // Accept connections
    while let Ok((stream, _)) = socket.accept().await {
        let manager = user_manager.clone();
        let jwks = jwks_manager.clone();
        tokio::spawn(async move {
            let _ = accept_connection(stream, manager, jwks).await;
        });
    }
    
    Ok(())
}

Authentication Flow

1

Client Connects

Client initiates WebSocket connection with JWT token in query parameter:
ws://proxy.kyber.gg:8080?token=eyJhbGciOiJSUzI1NiIs...
2

Token Validation

Proxy extracts and validates JWT:
  • Decodes header to get kid (key ID)
  • Fetches corresponding public key from JWKS
  • Validates signature and expiration
  • Extracts claims (user_id, server_id)
3

Connection Routing

Based on JWT claims:
  • If server_id present: Connect to specific server
  • If user_id only: Join matchmaking pool
  • Register connection in UserManager
4

Message Forwarding

Proxy forwards messages bidirectionally:
  • Client → Server: Prepends user identifier
  • Server → Client: Routes to correct connection

Building

Prerequisites

1

Install Rust

Install Rust via rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default nightly  # Optional: use nightly
2

Install Protoc

Install Protocol Buffers compiler:
# Ubuntu/Debian
sudo apt install protobuf-compiler

# macOS
brew install protobuf

# Windows
# Download from https://github.com/protocolbuffers/protobuf/releases

Build Commands

cd Proxy

# Build in debug mode
cargo build

# Run with logging
RUST_LOG=info cargo run

Configuration

Configure via environment variables:
.env
# Server Configuration
SERVER_IP=0.0.0.0
SERVER_PORT=8080

# JWT Validation
JWKS_URL=https://api.kyber.gg/.well-known/jwks.json

# Error Tracking
SENTRY_DSN=https://your-sentry-dsn

# Logging
RUST_LOG=info  # Options: error, warn, info, debug, trace

Performance Characteristics

Low Latency

Sub-millisecond message forwarding

High Throughput

10,000+ concurrent connections per instance

Memory Efficient

~10KB per active connection

Auto-Scaling

Stateless design enables horizontal scaling

Benchmarks

# Concurrent connections: 10,000
# Message rate: 100,000 msg/sec
# Average latency: 0.8ms
# Memory usage: 120MB
# CPU usage: 15% (8-core)

Connection Management

Reconnection Logic

const SERVER_RECONNECT_TIMEOUT: Duration = Duration::from_secs(10);

async fn handle_connection_loss(user_id: &str, manager: &UserManager) {
    let mut retry_count = 0;
    
    loop {
        tokio::time::sleep(SERVER_RECONNECT_TIMEOUT).await;
        
        match attempt_reconnect(user_id).await {
            Ok(_) => {
                info!("Reconnected user: {}", user_id);
                break;
            }
            Err(e) => {
                retry_count += 1;
                warn!("Reconnect attempt {} failed: {}", retry_count, e);
                
                if retry_count >= 3 {
                    manager.remove_user(user_id);
                    error!("Max reconnect attempts reached for {}", user_id);
                    break;
                }
            }
        }
    }
}

Heartbeat

// Send ping every 30 seconds
const PING_INTERVAL: Duration = Duration::from_secs(30);

tokio::spawn(async move {
    let mut interval = tokio::time::interval(PING_INTERVAL);
    
    loop {
        interval.tick().await;
        if let Err(_) = ws_sender.send(Message::Ping(vec![])).await {
            break;  // Connection lost
        }
    }
});

Monitoring

Logging

Structured logging with multiple levels:
use log::{info, warn, error, debug};

info!("Client connected: {}", user_id);
debug!("Message received: {:?}", msg);
warn!("Slow connection detected: {}ms", latency);
error!("Failed to forward message: {}", err);

Metrics

The Proxy tracks key metrics:
  • Active connections
  • Message throughput (in/out)
  • Average latency
  • Error rates
  • JWT validation failures

Development

Testing

# Run unit tests
cargo test

# Run with output
cargo test -- --nocapture

# Run specific test
cargo test test_jwt_validation

# Integration tests
cargo test --test integration

Load Testing

# Using websocket-bench
websocket-bench ws://localhost:8080 \
  --concurrent 1000 \
  --messages 100 \
  --payload-size 1024

Deployment

/etc/systemd/system/kyber-proxy.service
[Unit]
Description=KYBER Proxy Server
After=network.target

[Service]
Type=simple
User=kyber
WorkingDirectory=/opt/kyber-proxy
Environment=RUST_LOG=info
Environment=SERVER_IP=0.0.0.0
Environment=SERVER_PORT=8080
ExecStart=/opt/kyber-proxy/kyber_proxy
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl enable kyber-proxy
sudo systemctl start kyber-proxy

Troubleshooting

Check for connection leaks:
# Monitor active connections
ss -tn | grep :8080 | wc -l

# Check for unclosed connections in logs
journalctl -u kyber-proxy | grep "Connection lost"
Verify JWKS URL and key rotation:
# Test JWKS endpoint
curl https://api.kyber.gg/.well-known/jwks.json

# Check logs for key mismatch
RUST_LOG=debug cargo run
Increase timeout values and check network:
const SERVER_RECONNECT_TIMEOUT: Duration = Duration::from_secs(30);
const PING_INTERVAL: Duration = Duration::from_secs(60);
  • API - Provides JWT tokens and server routing info
  • Module - Game client that connects through Proxy
  • Launcher - Initiates connections to Proxy

Build docs developers (and LLMs) love