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 undertenants:(or via the REST API) are inspected. All other destination IPs on the bridge bypass filtering instantly withXDP_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: dedicatedinspects 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, plustcp_generic/udp_genericsize-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_failuresinvalid packets inside a 60-second window bans the source forban_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
# Extract the release package, then:
sudo ./install.shThe 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.
sudo gamefilter status # view status, mode & protected tenants
sudo gamefilter key # show API URL + keyBuilt-in Validators
| Validator | Protocols | Proof required on the first packet |
|---|---|---|
mc_java | Minecraft 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 |
raknet | MC Bedrock / MCPE / Geyser (UDP) | RakNet magic 00ffff00…12345678 at the exact offset for ping (0x01) / open-connection-request (0x05, 0x07) |
fivem | FiveM (UDP) | 0xFFFFFFFF + getinfo/getstatus/connect, or an ENet CONNECT command (low nibble 2, ≥52 bytes) |
source_engine | CS2 / CS:GO / Source (UDP) | 0xFFFFFFFF + A2S type byte; T additionally requires Source Engine Query\0 |
ssh_banner | SSH / SFTP (TCP) | SSH- banner, ≤255 bytes (RFC 4253) |
tcp_generic | any TCP | Size bounds + NULL/Xmas/FIN-scan flag rejection |
udp_generic | any UDP | Size 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 XDP | Generic rate-limit firewall | |
|---|---|---|
| Decision basis | Protocol validity (magic bytes, framing, size bounds) | Packets/bytes per second per source |
| Multi-tenant safety | Dedicated mode bypasses non-game VPS IPs instantly | Inspects/drops all traffic on port across host |
| Tuning | Per-game payload bounds from documented protocol structure | Thresholds guessed from traffic baselines |
| Random-payload flood to a game port | Dropped on the first packet (not valid protocol) | Dropped only after a rate threshold trips |
| Legit player experience | Validated once, then admitted (sliding TTL fast path) | Counted against rate budgets forever |
| Attacker with valid-looking low-rate traffic | Blocked unless packets are protocol-perfect | Invisible below the threshold |
| Where it runs | Private NIC or VM bridge (vmbr0) | Public edge (eno1) |
| Management | HTTP API + CLI, hot reload, OpenShield list sync | Varies |
Installation → · Configuration Reference → · HTTP API → · Architecture →
