Skip to content

feat(anticheat): detect cheat clients and disable unfair mods - #338

Open
TheMeinerLP wants to merge 4 commits into
mainfrom
feat/anticheat
Open

TheMeinerLP wants to merge 4 commits into
mainfrom
feat/anticheat

Conversation

@TheMeinerLP

Copy link
Copy Markdown
Contributor

Proposed changes

Adds an anticheat layer that detects cheat and unfair client mods on join and kicks or disables them.

Client guard

  • Detects the client brand and the minecraft:register channels a client announces.
  • Modes: OFF, LOG, KICK (default KICK).
  • Blocked brands and channels are configurable. An optional brand whitelist is only judged once a brand has arrived.

Client APIs

  • WorldDownloader is denied via the wdl:control channel.
  • LabyMod 4 gets an AddonDisablePacket (id 24) that disables its addons.
  • Lunar Client Apollo mod-setting overrides use apollo-protos 0.2.7 with protobuf-java 3.25.5. This is a lightweight path, because apollo-minestom bundles unrelocated Adventure.

Shader-mod probe

  • A sign translation-key probe runs on first spawn.
  • Iris/Oculus, OptiFine and Canvas are kicked with "Du hast inkompatible Mods! Entferne sie, um beizutreten."
  • Sodium, Embeddium and Nvidium are only logged. According to CygnusPack, only cosmetic terrain fog is lost with them.

Configuration

  • New sections client-guard., client-api. and lunar., see config.properties.example.

Limitations

  • Brand and channels are spoofable.
  • API requests can be ignored by modified clients.
  • Blocker mods (ExploitPreventer, OpSec) defeat the shader probe.
  • Iris is kicked even without an active shaderpack.
  • The sign-editor close and the Lunar mod keys (especially directionhud) are NOT tested against a live client.

Types of changes

What types of changes does your code introduce to this project?
Put an x in the boxes that apply

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update (if none of the other choices apply)

Test plan

  • Unit and Env tests green: :common:test 425, :game:test 1040, 0 failures
  • Manual test with a vanilla client
  • Manual test with Fabric + Sodium
  • Manual test with Iris
  • Manual test with a Lunar client
  • Manual test with a LabyMod client

Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of
them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before
merging your code.

  • I have read the CONTRIBUTING.md
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Read the client's minecraft:brand and minecraft:register messages in both the
configuration and play phases and kick clients that announce a known cheat
client (brand fragment, blocked channel prefix, or a brand outside an optional
whitelist). The mode decides between off, log only and kick.
Lunar Client users get the mods that could give a survivor an edge switched
off. Once the client registers lunar:apollo, the server sends one ModSetting
override (protobuf, wrapped in Any) that sets the enabled option of each
configured mod to false. The mods default to minimap, waypoints, freelook,
zoom, coordinates and directionhud, configured with lunar.disabled-mods.

This is a client courtesy API, not a cheat-proof measure.
The client guard now asks each player's client, on the first spawn, which
shader mods it has. Iris, OptiFine and Canvas kick the client with the
incompatible mods message, Sodium, Embeddium and Nvidium are only logged and
recorded on the profile.

The probe shows translatable texts on a sign that exists for that player
only, opens the sign editor on it and reads the answer from the sign update.
A key that resolved differs from its fallback. A client that does not answer
within shader-probe-timeout-ticks is not judged.
@github-actions

Copy link
Copy Markdown
Contributor

Test results

  666 files    666 suites   3m 58s ⏱️
1 528 tests 1 522 ✅  6 💤 0 ❌
4 587 runs  4 569 ✅ 18 💤 0 ❌

Results for commit cee6e6e.

SERVER_FULL = withMiniPrefix("<red>The server is full! Unable to join!");
GAME_ALREADY_STARTED = withMiniPrefix("<red>The game has already started! Unable to join!");
CLIENT_BLOCKED = withMiniPrefix("<red>Unsupported client detected! Remove your modifications to join.");
INCOMPATIBLE_MODS = withMiniPrefix("<red>Du hast inkompatible Mods! Entferne sie, um beizutreten.");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this specific message in German instead of English?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants