OPShield

Protects your server from OP/admin abuse with console-only OP (via password) and optional admin command restriction.

126

Quick challenge

How far can you run before the mobs catch you?

OPShield

🛡️ OPShield

Advanced security & command protection plugin for Paper 1.21+

[Version]() [Paper]() [Java]() [License]()

*Protect your server from abuse — secure OP access, track every action, stop attackers instantly.*

---

📖 Table of Contents

- ✨ Features - 🔐 Security System - 📊 Audit & Logging - 📦 Requirements - 🚀 Installation - ⌨️ Commands & Permissions - 🔧 Configuration - 🔍 Troubleshooting - ❓ FAQ - 📄 Credits

---

✨ Features

🔒 OP Protection

- Password-gated `/op` and `/deop` — no password, no privilege changes - PBKDF2-HMAC-SHA256 hashed storage — plaintext never kept in config - Configurable PBKDF2 iteration count (`security.password.pbkdf2_iterations`) - Automatic migration from legacy plaintext and SHA-256 hashes - Auto-upgrade legacy hashes — on next successful login, SHA-256 is silently replaced with PBKDF2 (`security.password.auto_upgrade_legacy_hash`) - Console warning if a legacy SHA-256 hash is detected on startup - OP whitelist — restrict `/op` to a predefined set of player names

---

🚫 Sensitive Command Protection

- Block dangerous commands for non-OP players (`blocked_commands`) - Optionally block commands even for OP players (`blocked_op_commands`) - Block entire command namespaces via prefix list (`blocked_command_prefixes`) - Alias and namespace resolution — bypass attempts via `minecraft:op` or plugin aliases are caught - Per-player bypass permission (`opshield.bypass`) for trusted staff

---

🧠 Brute-force Detection & Lockout

- Configurable failed-attempt limit before lockout (`security.lockout.max-attempts`) - Exponential backoff — each offence doubles the lockout duration - Optional IP-mirrored lockout (`security.lockout.track_ip`) - Lockout count decay after a cooling-off period (`security.lockout.count_decay_hours`) - Persistent tracking — lockout state survives server restarts - Manual unlock via `/opshield unlock <player|ip>`

---

🕵️ Shadow Ban System

- Sensitive blocked commands send a fake success message instead of an error - Each trigger increments the player's hidden shadow-ban level - Level persists across restarts - Auto-escalates to real punishment when `shadow_ban.auto_punish_level` is reached - Set `auto_punish_level: 99` to keep decoy behaviour without escalation - Fake messages come from language files — fully customisable per locale

---

⚠️ Auto Punishment System

- Punishment modes: `kick`, `ban`, `ban-ip`, `firewall`, `custom` - Persistent rolling-window threshold — survives restarts and crashes - Firewall mode runs an OS script asynchronously via `ProcessBuilder` with configurable timeout - Custom mode supports `{player}` and `{ip}` placeholders - IP-limit auto-punishment for accounts detected sharing the same IP

---

🌍 Multi-Language Support

- Bundled language files: Russian (`en`), Russian (`vn`), Russian (`ru`) - Automatic fallback to English for any missing key - Switch language via `language: "en"` in `config.yml`

---

📊 Audit & Logging

- Every privilege change, password failure, command block, and punishment is logged - Async queue — log writes never touch the main thread - Retry on failure — `audit.max_queue_size` prevents OOM if disk writes fail for extended periods - Retry on failure — `audit.format: plain` (default human-readable) or `audit.format: json` (machine-readable, one JSON object per line) - Retry on failure — uses NIO `Files.write()` with explicit charset - Retry on failure — failed writes are re-queued instead of silently discarded - Configurable rotation: `audit.max_file_size_mb` and `audit.log_retention` (up to N backup files) - Optional console mirror: `audit.console_output: true` - Log files: `plugins/OPShield/audit.log`, `audit.log.1` … `audit.log.N`

---

📦 Requirements

| Component | Version | |-----------|---------| | Java | 21+ | | Paper | 1.21+ | | Folia | ❌ Not supported |

---

🚀 Installation

1. Download the plugin `.jar` 2. Drop it into your server's `plugins/` folder 3. Start the server — OPShield will generate a random password and print it Grant permissions in the console 4. Save the password somewhere safe (it is only shown once) 5. Grant permissions — add `opshield.admin` to your admin group in your permission plugin (e.g. LuckPerms). OPShield no longer grants permissions based on OP status alone (changed in v1.8.0) 6. Open `plugins/OPShield/config.yml` to customise behaviour 7. Run `/opshield reload` in-game or restart to apply changes ✅

> Upgrading from 1.7.0? `data.yml` is automatically migrated on first boot. You only need to update your permission plugin setup — see the CRITICAL note in the changelog.

> Tip: If you already have an `op_password` plaintext value from an older version, > OPShield will automatically migrate it to `op_password_hash` and remove the plaintext entry.

---

⌨️ Commands

| Command | Description | |---------|-------------| | `/op <player> [password]` | Grant OP with password verification | | `/deop <player> [password]` | Remove OP with password verification | | `/opshield reload` | Reload configuration | | `/opshield unlock <player|ip>` | Clear all tracking state for a player or IP | | `/opshield status` | Show runtime statistics (active levels, flagged IPs, etc.) |

---

🔐 Permissions

> ⚠️ Changed in v1.8.0: All permissions now default to `false`. You must grant them explicitly via a permission plugin.

| Permission | Default | Description | |------------|---------|-------------| | `opshield.*` | false | Wildcard — grants all permissions | | `opshield.admin` | false | Grants all child permissions | | `opshield.reload` | false | Reload OPShield configuration | | `opshield.unlock` | false | Unlock a tracked player or IP | | `opshield.status` | false | View runtime statistics | | `opshield.op` | false | Use password-protected `/op` | | `opshield.deop` | false | Use password-protected `/deop` | | `opshield.bypass` | false | Bypass non-OP restricted command blocking |

Example LuckPerms setup

```bash /lp group admin permission set opshield.admin true ```

---

🔧 Configuration

Files generated under `plugins/OPShield/`:

- `config.yml` — main configuration - `data.yml` — persistent runtime state (lockouts, shadow-ban levels, IP windows) - `languages/en.yml` — English messages - `languages/vn.yml` — Vietnamese messages - `languages/ru.yml` — Russian messages

---

⚙️ Key Config Options

```yaml

Enable verbose console logging for troubleshooting (disable in production)

debug: false

Password security

security: lockout: enabled: true max-attempts: 3 duration-minutes: 3 track_ip: true count_decay_hours: 168 password: pbkdf2_iterations: 120000 # range: 10000 – 1000000 auto_upgrade_legacy_hash: true # silently upgrade SHA-256 → PBKDF2 on login

Auto-punishment

auto_punishment: enabled: true threshold: 5 window_seconds: 300 command: "kick" # kick | ban | ban-ip | firewall | custom firewall_timeout_seconds: 10

Shadow ban

shadow_ban: enabled: true auto_punish_level: 5

Audit log

audit: console_output: true max_file_size_mb: 5 log_retention: 3 max_queue_size: 10000 # 0 = unlimited (not recommended) format: "plain" # plain | json ```

---

📐 Recommended settings by server size

Small server (≤ 20 players) ```yaml security.lockout.max-attempts: 3 security.lockout.duration-minutes: 5 ip_limit.max_accounts: 2 auto_punishment.enabled: false shadow_ban.auto_punish_level: 10 ```

Medium server (20–100 players) ```yaml security.lockout.max-attempts: 3 security.lockout.duration-minutes: 3 ip_limit.max_accounts: 3 auto_punishment.enabled: true auto_punishment.command: kick auto_punishment.threshold: 5 shadow_ban.auto_punish_level: 5 ```

Large server (100+ players) ```yaml security.lockout.max-attempts: 2 security.lockout.duration-minutes: 10 ip_limit.max_accounts: 2 auto_punishment.enabled: true auto_punishment.command: ban-ip auto_punishment.threshold: 3 shadow_ban.auto_punish_level: 3 ```

---

🔥 Firewall mode setup

Firewall mode executes an OS script asynchronously. To enable it:

```yaml auto_punishment: command: "firewall" allow_unsafe_firewall_exec: true firewall_timeout_seconds: 10

Linux:

firewall_script: "iptables -A INPUT -s {ip} -j DROP"

Windows:

firewall_script: "netsh advfirewall firewall add rule name=OPShield dir=in action=block remoteip={ip}"

```

If `allow_unsafe_firewall_exec` is `false`, firewall mode falls back to a safe kick.

---

🔍 Troubleshooting

Cannot use /op — "Incorrect password"

The password is required. Run: ``` /op <yourname> <password> ``` If you forgot the password, clear `op_password_hash` in `config.yml` and restart — a new password will be generated and printed in the console.

Admin cannot use /opshield after upgrading from 1.7.0

In v1.8.0, permissions now default to `false` instead of `op`. You need to explicitly grant the permission: ```bash /lp group admin permission set opshield.admin true ```

Player is locked out and cannot try again

An admin can manually clear the lockout: ``` /opshield unlock <playername> /opshield unlock <ip-address> ```

Auto-punishment is not triggering

Check the following: - `auto_punishment.enabled: true` in `config.yml` - The command the player used is listed in `auto_punishment.sensitive_commands` - `shadow_ban.enabled` — if true, the player may be getting fake success messages first; level must reach `auto_punish_level` - Run `/opshield reload` after any config change - Run `/opshield status` to see current shadow-ban levels and punish state

Audit log is empty or not updating

- Check `audit.console_output: true` to confirm logging is active - Check write permissions on the `plugins/OPShield/` folder - If `audit.max_queue_size` is reached, a `SEVERE` warning appears in console — check disk space

Config changes are not taking effect

Run in-game or console: ``` /opshield reload ```

---

❓ FAQ

Does OPShield replace `/op`?

No — it intercepts and wraps it. The original `/op` behaviour is preserved but gated behind a password.

---

Is the password stored securely?

Yes — passwords are hashed using PBKDF2-HMAC-SHA256 with a random salt and 120,000 iterations (configurable). The plaintext is never written to disk.

---

Does it support Spigot or Folia?

Paper 1.21+ only. Spigot may work but is not tested. Folia is explicitly not supported (`folia-supported: false`).

---

Can I disable auto-punishment entirely?

Yes — set `auto_punishment.enabled: false`. Shadow-ban fake messages will still work independently.

---

What happens if the server restarts during a lockout?

Lockout state is persisted to `data.yml` and restored on startup. Players cannot bypass lockouts by crashing or restarting the server.

---

Can I have multiple language files?

Yes — all three bundled files (`en`, `vn`, `ru`) are always present. Switch via `language:` in `config.yml`. Missing keys automatically fall back to the bundled English defaults.

---

What changed in v1.8.0?

The most important change is permission defaults — see the permission defaults for the full list. The short version: grant `opshield.admin` to your admin group in LuckPerms.

---

📄 Credits

Website: Duong2012G Website: Apache 2.0 Website: https://modrinth.com/user/Duong2012G

*Built for secure, professional Minecraft servers.* - Password-gated `/op` and `/deop` — no password, no privilege changes - PBKDF2-HMAC-SHA256 hashed storage — plaintext never kept in config - Configurable PBKDF2 iteration count (`security.password.pbkdf2_iterations`) - Automatic migration from legacy plaintext and SHA-256 hashes - Console warning if a legacy SHA-256 hash is detected on startup - OP whitelist — restrict `/op` to a predefined set of player names

---

🚫 Sensitive Command Protection

- Block dangerous commands for non-OP players (`blocked_commands`) - Optionally block commands even for OP players (`blocked_op_commands`) - Block entire command namespaces via prefix list (`blocked_command_prefixes`) - Alias and namespace resolution — bypass attempts via `minecraft:op` or plugin aliases are caught - Per-player bypass permission (`opshield.bypass`) for trusted staff

---

🧠 Brute-force Detection & Lockout

- Configurable failed-attempt limit before lockout (`security.lockout.max-attempts`) - Exponential backoff — each offence doubles the lockout duration - Optional IP-mirrored lockout (`security.lockout.track_ip`) - Lockout count decay after a cooling-off period (`security.lockout.count_decay_hours`) - Persistent tracking — lockout state survives server restarts - Manual unlock via `/opshield unlock <player|ip>`

---

🕵️ Shadow Ban System

- Sensitive blocked commands send a fake success message instead of an error - Each trigger increments the player's hidden shadow-ban level - Level persists across restarts - Auto-escalates to real punishment when `shadow_ban.auto_punish_level` is reached - Set `auto_punish_level: 99` to keep decoy behaviour without escalation

---

⚠️ Auto Punishment System

- Punishment modes: `kick`, `ban`, `ban-ip`, `firewall`, `custom` - Persistent rolling-window threshold — survives restarts and crashes - Firewall mode runs an OS script asynchronously via `ProcessBuilder` with configurable timeout - Custom mode supports `{player}` and `{ip}` placeholders - IP-limit auto-punishment for accounts detected sharing the same IP

---

🌍 Multi-Language Support

- Bundled language files: Russian (`en`), Russian (`vn`), Russian (`ru`) - Automatic fallback to English for any missing key - Switch language via `language: "en"` in `config.yml`

---

📊 Audit & Logging

- Every privilege change, password failure, command block, and punishment is logged - Async queue — log writes never touch the main thread - Retry on failure — uses NIO `Files.write()` with explicit charset (fixed in 1.6.0) - Retry on failure — failed writes are re-queued instead of silently discarded (fixed in 1.6.0) - Configurable rotation: `audit.max_file_size_mb` and `audit.log_retention` (up to N backup files) - Optional console mirror: `audit.console_output: true` - Log files: `plugins/OPShield/audit.log`, `audit.log.1` … `audit.log.N`

---

📦 Requirements

| Component | Version | |-----------|---------| | Java | 21+ | | Paper | 1.21+ | | Folia | ❌ Not supported |

---

🚀 Installation

1. Download the plugin `.jar` 2. Drop it into your server's `plugins/` folder 3. Start the server — OPShield will generate a random password and print it once in the console 4. Save the password somewhere safe (it is only shown once) 5. Open `plugins/OPShield/config.yml` to customise behaviour 6. Run `/opshield reload` in-game or restart to apply changes ✅

> Tip: If you already have an `op_password` plaintext value from an older version, > OPShield will automatically migrate it to `op_password_hash` and remove the plaintext entry.

---

⌨️ Commands

| Command | Description | |---------|-------------| | `/op <player> [password]` | Grant OP with password verification | | `/deop <player> [password]` | Remove OP with password verification | | `/opshield reload` | Reload configuration | | `/opshield unlock <player|ip>` | Clear all tracking state for a player or IP |

---

🔐 Permissions

| Permission | Default | Description | |------------|---------|-------------| | `opshield.admin` | op | Grants all child permissions | | `opshield.reload` | op | Reload OPShield configuration | | `opshield.unlock` | op | Unlock a tracked player or IP | | `opshield.op` | op | Use password-protected `/op` | | `opshield.deop` | op | Use password-protected `/deop` | | `opshield.bypass` | false | Bypass non-OP restricted command blocking |

---

🔧 Configuration

Files generated under `plugins/OPShield/`:

- `config.yml` — main configuration - `data.yml` — persistent runtime state (lockouts, shadow-ban levels, IP windows) - `languages/en.yml` — English messages - `languages/vn.yml` — Vietnamese messages - `languages/ru.yml` — Russian messages

---

⚙️ Example Config

```yaml

Password security

security: lockout: enabled: true max-attempts: 3 duration-minutes: 3 track_ip: true count_decay_hours: 168 password: pbkdf2_iterations: 120000 # range: 10000 – 1000000

Auto-punishment

auto_punishment: enabled: true threshold: 5 window_seconds: 300 command: "kick" # kick | ban | ban-ip | firewall | custom firewall_timeout_seconds: 10

Shadow ban

shadow_ban: enabled: true auto_punish_level: 3

Audit log

audit: console_output: true max_file_size_mb: 5 log_retention: 3 ```

---

📐 Recommended settings by server size

Small server (≤ 20 players) ```yaml security.lockout.max-attempts: 3 security.lockout.duration-minutes: 5 ip_limit.max_accounts: 2 auto_punishment.enabled: false ```

Medium server (20–100 players) ```yaml security.lockout.max-attempts: 3 security.lockout.duration-minutes: 3 ip_limit.max_accounts: 3 auto_punishment.enabled: true auto_punishment.command: kick auto_punishment.threshold: 5 shadow_ban.auto_punish_level: 3 ```

Large server (100+ players) ```yaml security.lockout.max-attempts: 2 security.lockout.duration-minutes: 10 ip_limit.max_accounts: 2 auto_punishment.enabled: true auto_punishment.command: ban-ip auto_punishment.threshold: 3 shadow_ban.auto_punish_level: 2 ```

---

🔥 Firewall mode setup

Firewall mode executes an OS script asynchronously. To enable it:

```yaml auto_punishment: command: "firewall" allow_unsafe_firewall_exec: true firewall_timeout_seconds: 10

Linux:

firewall_script: "iptables -A INPUT -s {ip} -j DROP"

Windows:

firewall_script: "netsh advfirewall firewall add rule name=OPShield dir=in action=block remoteip={ip}"

```

If `allow_unsafe_firewall_exec` is `false`, firewall mode falls back to a safe kick.

---

🔍 Troubleshooting

Cannot use /op — "Incorrect password"

The password is required. Run: ``` /op <yourname> <password> ``` If you forgot the password, clear `op_password_hash` in `config.yml` and restart — a new password will be generated and printed in the console.

Player is locked out and cannot try again

An admin can manually clear the lockout: ``` /opshield unlock <playername> /opshield unlock <ip-address> ```

Auto-punishment is not triggering

Check the following: - `auto_punishment.enabled: true` in `config.yml` - The command the player used is listed in `auto_punishment.sensitive_commands` - `shadow_ban.enabled` — if true, the player may be getting fake success messages instead - Run `/opshield reload` after any config change

Audit log is empty or not updating

- Check `audit.console_output: true` to confirm logging is active - Check write permissions on the `plugins/OPShield/` folder - In 1.6.0, failed writes are retried and logged to console as `SEVERE` — check console output

Config changes are not taking effect

Run in-game or console: ``` /opshield reload ```

---

❓ FAQ

Does OPShield replace `/op`?

No — it intercepts and wraps it. The original `/op` behaviour is preserved but gated behind a password.

---

Is the password stored securely?

Yes — passwords are hashed using PBKDF2-HMAC-SHA256 with a random salt and 120,000 iterations (configurable). The plaintext is never written to disk.

---

Does it support Spigot or Folia?

Paper 1.21+ only. Spigot may work but is not tested. Folia is explicitly not supported (`folia-supported: false`).

---

Can I disable auto-punishment entirely?

Yes — set `auto_punishment.enabled: false`. Shadow-ban fake messages will still work independently.

---

What happens if the server restarts during a lockout?

Lockout state is persisted to `data.yml` and restored on startup. Players cannot bypass lockouts by crashing or restarting the server.

---

Can I have multiple language files?

Yes — all three bundled files (`en`, `vn`, `ru`) are always present. Switch via `language:` in `config.yml`. Missing keys automatically fall back to the bundled English defaults.

---

📄 Credits

Website: Duong2012G Website: Apache 2.0 Website: https://modrinth.com/user/Duong2012G

*Built for secure, professional Minecraft servers.*

ADS