Proxy Minecraft en Go : Architecture de gate-plugged
/ 9 min de lecture
Table des matières
Dans l’écosystème de l’hébergement de serveurs multijoueurs Minecraft, l’architecture par grappes (server networks) est la norme depuis plus d’une décennie. Pour relier des modes de jeu distincts (survie, mini-jeux, lobby) derrière une adresse IP unique sans déconnecter les joueurs, on intercale un proxy inverse de paquets.
Historiquement, cette couche est dominée par des solutions Java comme BungeeCord ou Velocity. Bien que performant, un proxy Java impose l’empreinte mémoire d’une machine virtuelle (JVM), consommant fréquemment 512 Mo à 1 Go de RAM rien que pour router des paquets TCP, tout en subissant les pauses de son garbage collector lors de pics d’affluence. De plus, orchestrer le cycle de vie des serveurs sous-jacents (démarrer un monde uniquement quand un joueur clique sur un portail, puis l’éteindre pour préserver les ressources) requiert traditionnellement des chaînes de scripts fragiles et disparates.
Pour bâtir une passerelle ultra-légère, autonome et étroitement liée à mon infrastructure d’hébergement, j’ai développé gate-plugged (FRFlo/gate-plugged). Ce projet s’appuie sur le framework en Go Minekube Gate, enrichi d’un ensemble de plugins modulaires : intégration de l’API Pelican Panel pour l’allumage/extinction à la demande, détection granulaire des clients et mods (Forge, NeoForge, Lunar Client via Protobuf, Bedrock/Geyser), et commandes d’administration centralisées sans aucun plugin sur les serveurs de jeu finaux.
Voici l’analyse d’architecture de cette passerelle réseau haute performance.
Vue d’ensemble de l’Architecture
gate-plugged agit comme le point d’entrée public unique du réseau Minecraft. Il termine les connexions TCP des joueurs, inspecte les paquets de handshake et de configuration, et dialogue avec le démon du panel Pelican pour piloter les conteneurs de jeu en arrière-plan :
flowchart TB
subgraph Players["Joueurs Minecraft"]
JavaClient["Client Java Standard"]
LunarClient["Lunar Client (Protobuf)"]
ModdedClient["Forge / NeoForge (Mods)"]
BedrockClient["Bedrock / Geyser"]
end
subgraph GateProxy["gate-plugged (Binaire Go Native)"]
TCPListener["TCP Listener (:25565)<br>Velocity Modern Forwarding"]
PluginRouter["Moteur de Plugins Minekube Gate"]
subgraph Plugins["Plugins Internes"]
Detection["plugins/detection<br>(Forge, Lunar PB, Bedrock)"]
PelicanPlugin["plugins/pelican<br>(Auto-Start & Auto-Stop)"]
Vanish["plugins/vanish<br>(Masquage Tablist & Paquets)"]
Commands["plugins/commands<br>(Marqueur F3 & Brand Spoofing)"]
end
end
subgraph Infrastructure["Infrastructure Backend (Pelican / Docker)"]
PelicanAPI["API Pelican Panel<br>(/api/client/servers/{id}/power)"]
LimboServer["Serveur Limbo (:25566)<br>(Monde d'attente ultra-léger)"]
GameServerA["Serveur Survie (Spigot/Paper)"]
GameServerB["Serveur Moddé (Forge/Fabric)"]
end
Players -->|Connexion TCP :25565| TCPListener
TCPListener --> PluginRouter
PluginRouter --> Detection
PluginRouter --> PelicanPlugin
PluginRouter --> Vanish
PluginRouter --> Commands
PelicanPlugin -->|"REST API Allumage et Extinction"| PelicanAPI
PluginRouter -->|Joueur en attente de boot| LimboServer
PluginRouter -->|Routage une fois prêt| GameServerA
PluginRouter -->|Routage direct| GameServerB
1. Pourquoi Gate (Go) plutôt qu’un Proxy JVM ?
L’un des plus grands défis de l’auto-hébergement de jeux vidéo sur VPS est la concurrence des ressources : faire cohabiter des bases de données, des pipelines RAG, des agents IA et des serveurs de jeu impose une discipline stricte sur chaque mégaoctet alloué.
Minekube Gate est une réimplémentation complète du protocole réseau Minecraft (paquets client/serveur, compression zlib, chiffrement AES/CFB8, et transfert d’identité moderne Velocity) écrite en Go :
- Empreinte Mémoire Réduite à Moins de 30 Mo : Là où Velocity réclame un minimum de 512 Mo pour être stable,
gate-pluggedtourne sereinement sous un budget de quelques dizaines de mégaoctets de RAM. - Goroutines Légères au Lieu de Threads OS : Chaque connexion de joueur est traitée par des goroutines Go concurrentes ultra-légères, sans le coût mémoire des piles d’appels de threads Java.
- Démarrage Éclair (< 50 ms) : Le binaire compilé démarre instantanément dans un conteneur Docker léger, éliminant le temps de préchauffage de la JVM.
Sécurisation via Velocity Modern Forwarding
Pour transmettre l’adresse IP réelle de l’utilisateur, son UUID Mojang et ses propriétés de skin aux serveurs finaux sans autoriser d’usurpation d’identité (spoofing), gate-plugged implémente le protocole de forwarding moderne de Velocity.
Chaque paquet de connexion vers un serveur backend est authentifié par une signature HMAC-SHA256 alimentée par une clé secrète partagée injectée via variable d’environnement (GATE_VELOCITY_SECRET) :
forwarding: mode: velocity velocity: secret: "${GATE_VELOCITY_SECRET}"2. Intégration Pelican : Allumage et Extinction à la Demande
Dans une grappe de serveurs classique, laisser tourner en permanence des mondes moddés ou des arènes secondaires inoccupées consomme inutilement plusieurs gigaoctets de RAM.
Le plugin plugins/pelican de gate-plugged s’interface directement avec l’API REST de Pelican Panel (le successeur moderne de Pterodactyl) pour implémenter un cycle de vie automatisé à deux volets :
sequenceDiagram
autonumber
actor Player as Joueur
participant Proxy as gate-plugged
participant Limbo as Serveur Limbo
participant Pelican as API Pelican Panel
participant Backend as Serveur Survie (Paper)
Player->>Proxy: Connexion (/server survie)
Proxy->>Pelican: GET /servers/{id} (Check Status)
alt Serveur Éteint (Offline)
Proxy->>Pelican: POST /servers/{id}/power (signal: start)
Proxy->>Player: Redirection temporaire vers Limbo
Player->>Limbo: Attente dans un monde vide (0 ressource)
loop Polling de Disponibilité
Proxy->>Backend: Ping TCP & Protocol Handshake
end
Backend-->>Proxy: Serveur Ouvert & Prêt
Proxy->>Player: Téléportation transparente vers le Serveur Survie
else Serveur Déjà Actif
Proxy->>Player: Connexion directe
end
Le Rôle Clé du Serveur Limbo
Lorsqu’un joueur demande à rejoindre un serveur actuellement hors ligne, gate-plugged ne refuse pas brutalement la connexion avec une erreur générique. Il transfère immédiatement le joueur sur un serveur Limbo (limbo:25566).
Limbo est un faux serveur Minecraft statique qui ne charge aucun chunk et aucune entité, consommant moins de 10 Mo de RAM. Le joueur y patiente dans un monde vide avec des messages de chargement personnalisés affichés dans la barre de boss ou dans le chat, pendant que le plugin pelican surveille l’initialisation du serveur backend avant de basculer la session TCP de façon fluide.
Auto-Stop Intelligent
Inversement, le module autostop.go surveille l’occupation des mondes backend. Dès qu’un serveur enregistre un compteur de 0 joueur pendant un délai paramétrable (ex. 10 minutes), gate-plugged émet une requête d’arrêt propre (signal: stop) auprès de l’API Pelican, réclamant instantanément les ressources système pour le reste du VPS.
3. Détection Avancée des Mods et Clients (plugins/detection)
Assurer l’intégrité d’un serveur de jeu nécessite de savoir avec quel client et quels fichiers un utilisateur se connecte. Traditionnellement, cette vérification est éclatée entre plusieurs plugins Spigot lourds ou nécessite des briques anti-cheat complexes.
gate-plugged centralise cette analyse directement sur la passerelle en exploitant les canaux de messages de plugins (Plugin Messaging Channels) échangés durant la phase de configuration du protocole Minecraft.
flowchart LR
Client["Client Minecraft"] -->|Plugin Channel Handshake| Proxy["gate-plugged Listener"]
Proxy --> ChannelRouter{"Canal Détecté ?"}
ChannelRouter -->|fml:handshake / fml:login| ForgeParser["Forge / NeoForge Mod Parser<br>(Extraction liste des mods & versions)"]
ChannelRouter -->|lunarclient:pm / lunar:message| LunarParser["Protobuf Lunar Decoder<br>(Extraction ID, version et settings)"]
ChannelRouter -->|minecraft:brand| BrandParser["Brand Filter<br>(Fabric, Vanilla, Cheat Clients)"]
ForgeParser --> PolicyEngine["Moteur d'Actions (actions.go)"]
LunarParser --> PolicyEngine
BrandParser --> PolicyEngine
PolicyEngine -->|Conforme| Allow["Autoriser Connexion & Logger Métadonnées"]
PolicyEngine -->|Non Conforme| Kick["Refus Immédiat & Message Personnalisé"]
Détection Forge & NeoForge (forge.go)
Les clients moddés sous Forge négocient leur liste de mods avec le serveur via un protocole d’échange spécifique (fml:handshake sur les versions antérieures, puis fml:login sur les versions modernes).
gate-plugged intercepte et décode ce handshake binaire sans nécessiter de serveur Forge en frontal :
- Extraction de la liste exhaustive des IDs de mods installés sur le client et de leurs versions exactes.
- Contrôle face à une liste blanche ou noire définie dans
plugged.yml. - Rejet immédiat de mods de triche connus avant même que le joueur ne pose le pied sur le serveur de survie.
Décodage Protobuf pour Lunar Client (lunar.go)
Pour les utilisateurs jouant sur le client compétitif Lunar Client, la communication passe par des messages encodés en Protocol Buffers (Protobuf) via le canal lunarclient:pm.
Le sous-module lunar_pb compile nativement les définitions Protobuf dans le binaire Go, permettant à gate-plugged de :
- Valider l’authenticité de la session Lunar Client.
- Configurer les modules visuels autorisés (désactiver les tags de joueurs à travers les murs, ajuster le réticule, etc.).
- Journaliser le hash du build du client pour l’équipe de modération.
4. Vanish Centralisé au Niveau Réseau (plugins/vanish)
Dans un réseau de serveurs, masquer un modérateur ou un administrateur (/vanish) pose régulièrement problème : les paquets de liste des joueurs (Tablist / PlayerInfo) et les messages de connexion/déconnexion doivent être répercutés manuellement entre tous les serveurs Paper et Spigot. Si un plugin backend présente un bug, l’apparition d’un modérateur peut être trahie par un paquet de mise à jour d’entité.
Le plugin plugins/vanish de gate-plugged résout ce défi en opérant au-dessus des serveurs finaux :
- Filtrage des Paquets
PlayerInfoUpdate: Lorsqu’un administrateur bascule en/vanish, le proxy réécrit dynamiquement les paquets de mise à jour du Tablist envoyés aux joueurs ordinaires pour effacer toute référence à l’UUID et au nom de l’administrateur. - Suppression des Annonces Globales : Les événements de commutation inter-serveurs (
ServerConnectedEvent) sont neutralisés afin qu’aucun message de switch ne filtre dans le chat. - Zéro Dépendance Backend : Le vanish fonctionne universellement, que le joueur navigue sur un serveur Paper en 1.21, un serveur moddé Forge en 1.20, ou une arène mini-jeu autonome.
Conclusion
En substituant les traditionnels proxys Java par une passerelle compilée en Go, gate-plugged divise la consommation mémoire par plus de dix tout en offrant une réactivité réseau optimale.
L’interconnexion native avec l’API Pelican permet de transformer une infrastructure de jeu statique en une plateforme serverless à la demande : les serveurs ne consomment des cycles CPU et de la mémoire vive que lorsqu’un joueur s’y amuse réellement.
Le projet est accessible en open source sur GitHub : github.com/FRFlo/gate-plugged.