Claude Code Plugins

Community-maintained marketplace

Feedback

Game server security including encryption, anti-cheat, and secure communication

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name security-encryption
description Game server security including encryption, anti-cheat, and secure communication
sasmp_version 1.3.0
version 2.0.0
bonded_agent 01-game-server-architect
bond_type SECONDARY_BOND
parameters [object Object]
retry_config [object Object]
observability [object Object]

Security & Encryption for Game Servers

Implement secure game server architecture with encryption and anti-cheat measures.

Security Layers

[Client] ← TLS 1.3 → [Load Balancer] ← mTLS → [Game Server]
                                                    ↓
                                          [Encrypted State]

Transport Security

TLS/SSL Configuration

#include <openssl/ssl.h>

SSL_CTX* createSecureContext() {
    SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());

    // TLS 1.3 only
    SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
    SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);

    // Load certificates
    SSL_CTX_use_certificate_file(ctx, "server.crt", SSL_FILETYPE_PEM);
    SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM);

    // Secure cipher suites only
    SSL_CTX_set_ciphersuites(ctx,
        "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256");

    // Enable session tickets
    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);

    return ctx;
}

DTLS for UDP Game Traffic

SSL_CTX* createDTLSContext() {
    SSL_CTX* ctx = SSL_CTX_new(DTLS_server_method());
    SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);

    // Cookie verification to prevent DoS
    SSL_CTX_set_cookie_generate_cb(ctx, generateCookie);
    SSL_CTX_set_cookie_verify_cb(ctx, verifyCookie);

    return ctx;
}

Server Authority Model

// NEVER trust client data - validate everything server-side
class AuthoritativeServer {
public:
    bool onMoveCommand(uint32_t playerId, Vector3 targetPos) {
        auto& player = players[playerId];
        Vector3 currentPos = player.position;

        // Validate movement speed
        float distance = (targetPos - currentPos).length();
        float maxDistance = player.speed * deltaTime * 1.1f; // 10% tolerance

        if (distance > maxDistance) {
            logSuspicious(playerId, "SPEED_HACK", {
                {"distance", distance},
                {"max_allowed", maxDistance}
            });
            return false;
        }

        // Validate path (no teleporting through walls)
        if (!isPathClear(currentPos, targetPos)) {
            logSuspicious(playerId, "WALL_HACK", {});
            return false;
        }

        // Apply validated movement
        player.position = targetPos;
        return true;
    }

    bool onFireCommand(uint32_t playerId, Vector3 aimDir) {
        auto& player = players[playerId];

        // Validate fire rate
        auto now = Clock::now();
        auto timeSinceLastShot = now - player.lastFireTime;

        if (timeSinceLastShot < player.weapon.fireRate) {
            logSuspicious(playerId, "FIRE_RATE_HACK", {});
            return false;
        }

        // Server performs hit detection
        auto hit = raycast(player.position, aimDir);
        if (hit.entity) {
            applyDamage(hit.entity, player.weapon.damage);
        }

        player.lastFireTime = now;
        return true;
    }
};

Anti-Cheat Detection

class AntiCheatSystem {
    struct PlayerStats {
        float avgAccuracy;
        float avgReactionTime;
        int suspicionScore;
        std::vector<SuspiciousEvent> events;
    };

    std::unordered_map<uint32_t, PlayerStats> stats;

public:
    void onHit(uint32_t shooter, uint32_t target, const HitInfo& info) {
        auto& s = stats[shooter];

        // Statistical aimbot detection
        updateAccuracy(s, info);
        if (s.avgAccuracy > 0.95f && s.shots > 100) {
            s.suspicionScore += 10;
            flagForReview(shooter, "STATISTICAL_AIMBOT");
        }

        // Inhuman reaction time detection
        if (info.reactionTime < 0.1f) { // 100ms
            s.suspicionScore += 5;
            s.events.push_back({
                "INHUMAN_REACTION",
                info.reactionTime,
                Clock::now()
            });
        }

        // Trigger ban review if threshold exceeded
        if (s.suspicionScore > 100) {
            triggerBanReview(shooter, s);
        }
    }

    void validatePacket(uint32_t playerId, const Packet& pkt) {
        // Check sequence numbers for replay attacks
        if (pkt.sequence <= lastSequence[playerId]) {
            logSuspicious(playerId, "REPLAY_ATTACK", {});
            return;
        }

        // Verify packet checksum
        if (!verifyChecksum(pkt)) {
            logSuspicious(playerId, "PACKET_TAMPERING", {});
            disconnectPlayer(playerId);
        }
    }
};

Authentication

#include <jwt-cpp/jwt.h>

class AuthService {
    std::string secret;

public:
    std::string generateToken(const Player& player) {
        return jwt::create()
            .set_issuer("game-auth-server")
            .set_type("JWS")
            .set_payload_claim("player_id", jwt::claim(player.id))
            .set_payload_claim("username", jwt::claim(player.username))
            .set_issued_at(std::chrono::system_clock::now())
            .set_expires_at(std::chrono::system_clock::now() +
                           std::chrono::hours(24))
            .sign(jwt::algorithm::hs256{secret});
    }

    std::optional<PlayerClaims> validateToken(const std::string& token) {
        try {
            auto verifier = jwt::verify()
                .allow_algorithm(jwt::algorithm::hs256{secret})
                .with_issuer("game-auth-server");

            auto decoded = jwt::decode(token);
            verifier.verify(decoded);

            return PlayerClaims{
                decoded.get_payload_claim("player_id").as_string(),
                decoded.get_payload_claim("username").as_string()
            };
        } catch (const std::exception& e) {
            return std::nullopt;
        }
    }
};

Rate Limiting

class RateLimiter {
    struct Bucket {
        int tokens;
        std::chrono::steady_clock::time_point lastRefill;
    };

    std::unordered_map<std::string, Bucket> buckets;
    std::shared_mutex mutex;

public:
    bool allow(const std::string& key, int cost = 1) {
        std::unique_lock lock(mutex);

        auto& bucket = buckets[key];
        refill(bucket);

        if (bucket.tokens >= cost) {
            bucket.tokens -= cost;
            return true;
        }
        return false;
    }

private:
    void refill(Bucket& bucket) {
        auto now = std::chrono::steady_clock::now();
        auto elapsed = now - bucket.lastRefill;
        auto refillAmount = elapsed.count() * refillRate;
        bucket.tokens = std::min(maxTokens, bucket.tokens + refillAmount);
        bucket.lastRefill = now;
    }
};

// Usage
RateLimiter limiter;

void onClientMessage(Connection* conn, Message& msg) {
    if (!limiter.allow(conn->ip, 1)) {
        // Rate limited
        conn->send(RateLimitedResponse{});
        return;
    }
    processMessage(conn, msg);
}

Rate Limit Thresholds

Action Limit Window
Login attempts 5 1 min
Commands/sec 60 1 sec
Chat messages 10 10 sec
API requests 100 1 min

Troubleshooting

Common Failure Modes

Error Root Cause Solution
TLS handshake fail Cert expired Auto-renew certs
Token rejected Clock drift NTP sync
False positives Strict thresholds Tune detection
DoS vulnerability No rate limit Add rate limiting

Debug Checklist

# Verify TLS configuration
openssl s_client -connect game.example.com:443 -tls1_3

# Check certificate validity
openssl x509 -in server.crt -noout -dates

# Monitor security events
journalctl -u game-server | grep -E "(SUSPICIOUS|BLOCKED|VIOLATION)"

# Test rate limiter
for i in {1..100}; do curl -s game.example.com/api; done

Unit Test Template

#include <gtest/gtest.h>

TEST(Security, RejectsInvalidToken) {
    AuthService auth;
    auto result = auth.validateToken("invalid.token.here");
    EXPECT_FALSE(result.has_value());
}

TEST(Security, DetectsSpeedHack) {
    AuthoritativeServer server;
    Player player{.position = {0, 0, 0}, .speed = 10.0f};

    // Normal movement
    EXPECT_TRUE(server.onMoveCommand(1, {5, 0, 0}));

    // Teleport attempt
    EXPECT_FALSE(server.onMoveCommand(1, {1000, 0, 0}));
}

TEST(Security, RateLimiterWorks) {
    RateLimiter limiter;

    // First 10 requests pass
    for (int i = 0; i < 10; ++i) {
        EXPECT_TRUE(limiter.allow("test_ip"));
    }

    // 11th request blocked
    EXPECT_FALSE(limiter.allow("test_ip"));
}

TEST(Security, AESEncryptDecrypt) {
    std::string plaintext = "game state data";
    auto [ciphertext, iv] = encrypt_aes_gcm(plaintext, key);
    auto decrypted = decrypt_aes_gcm(ciphertext, key, iv);
    EXPECT_EQ(plaintext, decrypted);
}

Resources

  • assets/ - Security checklists
  • references/ - Encryption guides