Skip to content

GameFilter XDP ​

Per-game, protocol-validating XDP filter — all Rust (aya-ebpf kernel program, aya userspace).

GameFilter XDP sits on the private NIC or VM bridge (vmbr0 / br0) between your edge firewall (such as OpenShield-XDP) and your game servers / guest VPSes. Every port a game listens on gets a filter; a packet only reaches the server if it provably speaks that game's protocol. Sources that pass validation once are admitted for a sliding TTL, so real players never notice the filter — and random flood garbage aimed at a game port dies in the NIC driver.

There are no pps knobs. Instead of guessing how many packets per second a "legit" client sends, GameFilter checks what the packet is: magic bytes at exact offsets, frame-length consistency, payload size bounds. A 10M pps UDP flood of random payloads to your Minecraft port is simply not RakNet — it is dropped on the first packet, and repeated failures temp-ban the source.

Topologies & Modes ​

GameFilter supports two operating modes:

  • mode: dedicated (Multi-Tenant / Proxmox / Dedicated Server): ONLY destination IPs enrolled under tenants: (or via the REST API) are inspected. All other destination IPs on the bridge bypass filtering instantly with XDP_PASS (100% transparent and safe for web, DB, and general guest VPSes).
  • mode: vps (Single Server / Standalone): Inspects all traffic arriving on the interface regardless of destination IP.
Internet ──► Physical NIC (eno1) ──► OpenShield-XDP (Volumetric Anti-DDoS)
                    │ (Clean Traffic)
                    ▼
             VM Bridge (vmbr0) ──► GameFilter-XDP (Per-Game Protocol Validation)
                    │
       ┌────────────┴────────────┬────────────────────────┐
       ▼                         ▼                        ▼
Guest VPS A (Minecraft)   Guest VPS B (FiveM)     Guest VPS C (Web/DB)
[Enrolled: mc_java]       [Enrolled: fivem]       [Un-enrolled: 100% Bypassed]

How It Works ​

Features ​

  • Multi-Tenant / Proxmox ready — mode: dedicated inspects only enrolled tenant destination IPs; general VPSes bypass instantly with zero risk of breaking web or database workloads.
  • Protocol proof, not rate guessing — validators check exact protocol structure (magic offsets, varint frame-length consistency), not just ports.
  • 7 built-in validators — mc_java, raknet (Bedrock/MCPE/Geyser), fivem, source_engine (CS2/CS:GO), ssh_banner, plus tcp_generic / udp_generic size-bounds fallbacks.
  • Sliding admission TTL — a source that validates once is admitted per (src_ip, dst_ip, rule); every further packet refreshes the window, so established players take the fast path.
  • Failure → temp-ban escalation — max_failures invalid packets inside a 60-second window bans the source for ban_sec, enforced in kernel.
  • Flexible port ownership — single ports ("25565"), lists, and ranges ("27015-27050"), up to 64 filters.
  • Whitelist / blacklist — permanent or timed entries, managed live from the CLI or HTTP API without a reload.
  • OpenShield-XDP list sync — mirrors OpenShield's whitelist/blacklist into the kernel maps (adds and removals), via its API, a JSON export file, or a direct read of its pinned ban maps.
  • HTTP management API — token-authenticated, per-IP rate-limited; stats, metrics sampler, live tenant enrollment, filters, admissions, lists, config read/patch, hot reload. No TUI by design.
  • Blip-free hot reload — delta-only port map updates, in-place rule writes, and admissions preserved for unchanged rules.

Quick Install ​

bash
# Extract the release package, then:
sudo ./install.sh

The installer auto-detects your environment (Bare Metal / Proxmox VE / KVM), suggests your bridge (e.g. vmbr0), prompts for deployment mode (dedicated vs vps), writes /etc/gamefilter/gamefilter.yaml, and starts the systemd services.

bash
sudo gamefilter status     # view status, mode & protected tenants
sudo gamefilter key        # show API URL + key

Built-in Validators ​

ValidatorProtocolsProof required on the first packet
mc_javaMinecraft Java (TCP)Full handshake frame: varint length (must match payload), packet id 0, protocol varint, address, port, next-state 1|2; legacy FE 01 ping accepted
raknetMC Bedrock / MCPE / Geyser (UDP)RakNet magic 00ffff00…12345678 at the exact offset for ping (0x01) / open-connection-request (0x05, 0x07)
fivemFiveM (UDP)0xFFFFFFFF + getinfo/getstatus/connect, or an ENet CONNECT command (low nibble 2, ≥52 bytes)
source_engineCS2 / CS:GO / Source (UDP)0xFFFFFFFF + A2S type byte; T additionally requires Source Engine Query\0
ssh_bannerSSH / SFTP (TCP)SSH- banner, ≤255 bytes (RFC 4253)
tcp_genericany TCPSize bounds + NULL/Xmas/FIN-scan flag rejection
udp_genericany UDPSize bounds only

TCP handshake packets are not admissions

SYN/ACK packets carry no payload and pass unvalidated — but they never admit a source. Admission only comes from a data packet that passes the protocol validator, so a spoofed handshake gets an attacker nothing.

vs. Generic Rate-Limit Firewalls ​

GameFilter is a complement to rate-limiting firewalls like OpenShield-XDP, not a replacement — run OpenShield on the public edge and GameFilter on the private NIC or bridge in front of the game servers.

GameFilter XDPGeneric rate-limit firewall
Decision basisProtocol validity (magic bytes, framing, size bounds)Packets/bytes per second per source
Multi-tenant safetyDedicated mode bypasses non-game VPS IPs instantlyInspects/drops all traffic on port across host
TuningPer-game payload bounds from documented protocol structureThresholds guessed from traffic baselines
Random-payload flood to a game portDropped on the first packet (not valid protocol)Dropped only after a rate threshold trips
Legit player experienceValidated once, then admitted (sliding TTL fast path)Counted against rate budgets forever
Attacker with valid-looking low-rate trafficBlocked unless packets are protocol-perfectInvisible below the threshold
Where it runsPrivate NIC or VM bridge (vmbr0)Public edge (eno1)
ManagementHTTP API + CLI, hot reload, OpenShield list syncVaries

Installation → · Configuration Reference → · HTTP API → · Architecture →