20. Mai 2026
5 min read
ZeroTrust Team

Sichern Sie Ihre Events: FiveM Lua Event-Sicherheitsleitfaden

Cheats ermöglichen es bösartigen Clients, Events in jedem Kontext auszulösen. Erfahren Sie, wie Sie die Client-Server-Kommunikation sichern, serverseitige Validierung implementieren und FXServer-Sicherheitsconvars konfigurieren.

Das Anti-Cheat-Team versucht immer, das Anti-Cheat zu verbessern, aber manchmal schlüpfen Dinge durch.

In dieser Anleitung versuchen wir, einige gängige Praktiken zu vermitteln, mit denen Sie Ihren Server sicherer machen können, indem Sie Ihre Events richtig absichern.

Netzwerk-Events in FiveM verstehen

Cheats können es dem Client ermöglichen, Events in jedem Kontext auszulösen.

Mit Kontext meinen wir, dass sie Client->Server (über TriggerServerEvent) oder Client-Ressource->Client-Ressource (über TriggerEvent) ausführen können.

Richtige Verwendung von Event-Handlern in Lua

Bei der Arbeit mit Events in Lua ist es entscheidend, diese korrekt zu registrieren, je nachdem, ob sie vom Client oder vom Server aufgerufen werden.

Ein häufiger Fehler ist das Registrieren von Server-Events, die nicht vom Client aufgerufen werden sollten, oder umgekehrt, was zu schwerwiegenden Sicherheitslücken führen kann.

AddEventHandler

Verwenden Sie AddEventHandler, wenn das Event im selben Kontext ausgelöst werden soll, entweder Client-Client oder Server-Server. Dies stellt sicher, dass die Events nicht vernetzt sind und nicht von der Gegenseite aufgerufen werden können.

AddEventHandler("eventName", function(eventParam1, eventParam2)
    -- Der Code hier wird ausgeführt, sobald das Event im selben Kontext ausgelöst wird.
end)

RegisterNetEvent

Verwenden Sie RegisterNetEvent, wenn das Event über verschiedene Kontexte hinweg ausgelöst werden muss, z. B. vom Client zum Server oder vom Server zum Client.

Unter der Haube

HINWEIS: Dies blockiert nicht die Ausführung aus demselben Kontext. Unter der Haube ist RegisterNetEvent ein Wrapper, der lediglich Folgendes darstellt: RegisterNetEvent("eventName") AddEventHandler("eventName", function() ... end)
RegisterNetEvent("eventName", function(eventParam1, eventParam2)
    -- Der Code hier wird ausgeführt, sobald das Event über verschiedene Kontexte hinweg ausgelöst wird.
end)

Dieses Beispiel ist für den Client, und wie alles auf dem Client ist es nicht absolut sicher und kann von cheatenden Clients manipuliert werden.

Wenn Sie die Ausführung aus demselben Kontext blockieren möchten (z. B. um zu verhindern, dass ein Server-zu-Server-Netzwerk-Event vom Client ausgelöst wird), sollten Sie Ihr Event registrieren und die Absenderquelle überprüfen:

RegisterNetEvent("eventName", function(eventParam1, eventParam2)
    -- Der Server sendet die Netz-ID `65535` für Events vom Server
    if source ~= 65535 then return end
end)

Prüfungen und Validierung hinzufügen

Selbst wenn Sie ein starkes Anti-Cheat-System aufbauen, macht das Hinzufügen von Prüfungen bei Server-Events diese erheblich sicherer. Dies ist eine dringend empfohlene Praxis, obwohl sie nicht alles verhindert. Unten teilen wir einige gute Tipps.

  • Spielergeld: Validieren Sie Kontostand und Transaktionen serverseitig.
  • Spieler-State-Bags: Überprüfen Sie State-Daten in aktiven Sitzungen.
  • Spieler-Inventargegenstände: Überprüfen Sie Gegenstandsnamen und -mengen.
  • Spielerposition: Überprüfen Sie Reichweiten und Distanzen.
  • Spielererfahrung und Level: Stellen Sie sicher, dass Statistiken serverseitig berechnet werden.
  • Spielerberechtigungen und -rollen: Validieren Sie die serverseitige ACL.

Faustregel

Stellen Sie sicher, dass alle Werte über serverseitige Methoden abgerufen werden und Spieler die Werte nicht selbst bereitstellen oder ändern können. Bitte beachten Sie, dass clientseitige Prüfungen auch eine gute Praxis für die UX sein können, aber leicht umgangen werden können.

Dies gewährleistet die Integrität und Sicherheit Ihrer Spielumgebung.

Beispiele für gängige Sicherheitsmuster

Alle folgenden Beispiele setzen eine Art Framework voraus (wie ESX, QB-Core usw.).

Schlechte Sicherheit (Niemals so machen)

Dies soll Ihnen schlechte Wege zur Handhabung von Events zeigen. Sie sollten dies niemals tun. Das direkte Hinzufügen von Gegenständen für den Benutzer aus seiner eigenen Eingabe ist immer eine schlechte Praxis: Sie sollten Benutzereingaben immer validieren.

RegisterNetEvent("job:givePlayerItem", function(item, count)
    local ply = FX.GetPlayerFromSource(source)
    -- Direktes Hinzufügen von Gegenständen für den Benutzer aus seiner eigenen Eingabe ist unsicher!
    ply.addItem(item, count)
end)

Gute Sicherheit (Empfohlen)

Hier ist ein robustes Sicherheitsmuster. Der Server verfolgt den Spielerstatus und die Koordinaten und überprüft Aktionen mithilfe von serverseitigen Ticks, anstatt sich ausschließlich auf Client-Trigger zu verlassen.

-- zufällige Koordinate
local VALID_JOB_COORD = vector3(125.0, 111.1, 35.83)
local MAX_ITEM_COUNT = 10

-- zufällige Koordinate
local VALID_TURNIN_COORD = vector3(1888.0, 1254.1, 48.0)

local ITEM_NAME = 'log'

-- Liste der Spieler mit aktiven Jobs
local activeJobs = {}

AddEventHandler("playerDropped", function ()
    if not activeJobs[source] then return end
    activeJobs[source] = nil
end)

function isPedWithinRange(ped, tgtCoords)
    return #(GetEntityCoords(ped) - tgtCoords) < 15.0
end

-- Serverseitige Erhöhung der Gegenstandsmenge verarbeiten
CreateThread(function()
    while true do
        for src, data in pairs(activeJobs) do
            local ped = GetPlayerPed(src)
            -- wenn sie nicht in Reichweite sind, wollen wir ihnen den Gegenstand nicht geben
            if isPedWithinRange(ped, VALID_JOB_COORD) then
                -- gib ihnen den Gegenstand, aber begrenze ihn auf MAX_ITEM_COUNT
                data.itemCount = math.min(data.itemCount + 1, MAX_ITEM_COUNT)
            end
        end
        -- Job-Tick einmal pro Sekunde verarbeiten
        Wait(1000)
    end
end)

RegisterNetEvent("job:startJob", function()
    local ped = GetPlayerPed(source)
    -- wenn sie innerhalb von 15 Einheiten sind, machen sie den Job
    if isPedWithinRange(ped, VALID_JOB_COORD) then
        activeJobs[source] = {
            itemCount = 0,
        }
    end
end)

RegisterNetEvent("job:givePlayerItem", function()
    local ply = FX.GetPlayerFromSource(source)
    -- wenn sie keinen aktiven Job haben, sollten sie dies nicht aufrufen!
    local jobData = activeJobs[source]
    if not jobData then return end

    local ped = GetPlayerPed(source)
    -- sie sind nicht in Reichweite der Abgabekoordinaten, lehne ihre Änderungen ab
    if not isPedWithinRange(ped, VALID_TURNIN_COORD) then return end

    -- setze die Gegenstandsdaten zurück, damit sie das Event nicht mehrfach auslösen können
    activeJobs[source] = nil

    -- Füge dem Benutzer Gegenstände hinzu, die serverseitig validiert wurden
    ply.addItem(ITEM_NAME, jobData.itemCount)
end)

Serverbesitzer-Optionen (Convars)

Bitte beachten Sie, dass die folgenden Einstellungen nicht geändert werden sollten, es sei denn, Sie wissen genau, was Sie tun. Das Cfx.re / Adhesive-Team arbeitet immer sehr hart daran, Cheater zu verhindern. Die meisten dieser Funktionen sind ab FXServer-Buildversion 8450 und höher standardmäßig aktiviert.

  • sv_kick_players_cnl_timeout_sec: Dies ist das Zeitlimit, nach dem der Server den Spieler kickt (z. B. wenn dies 600 ist, nach 10 Minuten ohne CnL-Verbindung).
  • sv_kick_players_cnl_update_rate_sec: Dies ist die Häufigkeit, mit der CnL mit der Spielerliste abgefragt wird.
  • sv_pure_verify_client_settings: Ersetzt die regelmäßige Anfrage an info.json auf dem Client. Richtet eine sichere Verbindung zwischen adhesive und svadhesive ein und überprüft einige der sv_settings wie pureLevel, scripthook und andere Konfigurationen.
  • sv_kick_players_cnl_consecutive_failures: Wie viele aufeinanderfolgende Fehler nach dem timeout_sec erforderlich sind, um einen Spieler zu kicken. Der Standardwert ist auf 2 festgelegt. Das bedeutet, wenn ein Spieler sich 10 Minuten lang nicht meldet und dann das nächste Check-In-Update verpasst, wird er gekickt. Dies dient als Sicherheitsmechanismus.
  • sv_authMaxVariance: Die Varianz gibt an, wie wahrscheinlich es ist, dass sich die ID des Benutzers für einen bestimmten Anbieter (z. B. 'steam', 'ip' oder 'license') ändert.
  • sv_authMinTrust: Vertrauen gibt an, wie unwahrscheinlich es ist, dass die Identität des Benutzers von einem böswilligen Client gefälscht wird.
  • sv_filterRequestControl: Eine Konsolenvariable, die verwendet wird, um das Routing von REQUEST_CONTROL_EVENT basierend auf einer konfigurierbaren Richtlinie zu blockieren.
  • sv_disableClientReplays: Das Aktivieren dieser Option zielt darauf ab, die Möglichkeiten für Cheats zu verringern. Bitte beachten Sie, dass dadurch der Rockstar-Editor deaktiviert wird.

Ergebnisse auf dem Spieler

Wenn diese Convars aktiv sind, wird der Spieler wahrscheinlich mit folgendem Grund gekickt: Connection to CNL timed out.

Ein Kick bedeutet nicht, dass der Spieler automatisch global gebannt (Global Banned) ist. Es liefert jedoch einen starken Hinweis auf die Zuverlässigkeit des Spielers, was für die Beurteilung der Vertrauenswürdigkeit äußerst nützlich ist.

Wichtig zu wissen

Die bereitgestellten Codes sind nicht dafür gedacht, einfach kopiert und eingefügt zu werden. Dies sind nur einige Tipps, um bestimmte Aktionen zu verhindern, die auf dem Server auftreten könnten. Dies erfordert Programmierkenntnisse. Es steht Ihnen jederzeit frei, unserem Discord beizutreten, um zusätzliche Hilfe zu erhalten.