dwgx@blog:~$dwgx
> cd ../posts

strict: My MC Server Verifies Mods Right at the Login Handshake

// created

strict is a login access-control mod running on the Fabric server side, and it does one thing: at the moment a player logs in it verifies their mods and token, and kicks them if anything is off. Vanilla online verification only checks whether you own a legit account, not what you have installed, so client mods like X-ray ore vision, flight, or auto-fishing get into a vanilla server just fine. strict moves the gate to the login handshake. Runs on 1.21.3, Java 21, built with Fabric Loom, repo at github.com/dwgx/strict.

The core is wedging into the login handshake. It hooks into ServerLoginConnectionEvents.QUERY_START, and the server asks the client for data over a custom channel strict:check. The client’s ClientNetworking replies with a CheckPayload stuffed with two things: an AES-GCM encrypted token, plus the full list of currently loaded mods. The server first decrypts and verifies the SHA-256, then checks that the nonce hasn’t repeated within ten minutes and the timestamp is fresh within five minutes, and only then compares against the mod policy.

Why not just verify the mod list? The list is self-reported by the client, and anything you can report you can forge. The token layer proves this reply really was just sent by my mod, the nonce prevents replay, and the timestamp stops a captured packet from being used slowly later. Encryption/decryption and hashing all live in CryptoUtils, with the key derived from secretKey. There’s a trap buried here: the default value dwgx1337 is one I left in for lazy testing, and taking it to a live server without changing it is the same as no defense at all, so the docs call this out loudly.

Access control has two modes. Public mode lets you in once you pass, and OPs are waved through. Private mode is more fun: a stranger gets stuck in pendingPlayers, disconnected first to wait for approval, while an admin gets clickable [Accept] / [Reject] / [Blacklist] popping up in chat. One click and it’s done, no commands to memorize. Blacklisting supports both UUID and machine name, and reports carry the OS username, which is somewhat useful against griefers who swap to alt accounts.

Config lives in config/strict/config.yml. allowedMods / excludedMods handle the white/blacklist, and turning on allowFabricMods auto-passes official mods with the fabric- prefix. All commands are under /strict at OP level 4: switch modes, approve players, and /strict reload for a hot reload with no restart. Right now 1.0-SNAPSHOT is hard-bound to 1.21.3, an experiment I made on the side while running my own server.