▶️ ЗАБЕРИ СВОИ 8 ПОДАРКОВ 🎁 ПРИ СОЗДАНИИ СВОЕГО МАЙНКРАФТ СЕРВЕРА
OPShield

OPShield

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

112
1

OPShield 1.8.0

release28 апреля 2026 г.

[1.8.0] - 2026-04-28 — Manager Refactor, Security Hardening & Quality Improvements

🔒 Security Fixes

CRITICAL — Permission Default Changed

  • opshield.admin default changed from opfalse (breaking if you relied on implicit OP grants)
    • Previously any player with OP status automatically received full OPShield admin rights
    • Now all permissions must be explicitly granted via a permission plugin (e.g. LuckPerms)
    • Migration: add opshield.admin to your OP group in your permission plugin
  • All child permissions (opshield.reload, opshield.unlock, opshield.op, opshield.deop) default changed from opfalse for the same reason
  • Added opshield.* wildcard permission for convenience

🏗️ Architecture Improvements

LockoutManager — Full Refactor

  • Introduced LockoutRecord inner class consolidating 5 separate ConcurrentHashMaps (failedAttempts, lockoutTimestamps, lockoutCount, lastLockoutAt) into a single per-key object
  • Decay logic moved entirely into LockoutManager.recordFailure() — no longer split between main class and manager
  • Added mirrorLockout() for IP-mirrored lockouts (called by OPShield when track_ip=true)
  • Added exportSnapshot() / importSnapshot() for clean persistence without raw map access
  • Backwards-compatible persistence: v1.8.0 reads legacy v1.7.0 data format and migrates automatically
  • LockoutManager is now the single source of truth for all lockout state

ShadowBanManager — Full Refactor

  • Shadow-ban levels now owned by ShadowBanManager (previously a raw ConcurrentHashMap in OPShield.java)
  • getFakeMessage() is no longer static; it accepts a MessageProvider functional interface so messages come from language files, not hard-coded strings
  • Added shouldEscalate(key, threshold) method — clearly separates the "should I punish?" decision from execution
  • Added exportLevels() / importLevels() for persistence
  • Extended command keyword → message-key mapping: now covers op, deop, kick, stop, reload, pardon

OPShield.java — Reduced God Class Burden

  • Replaced 5 raw state maps with delegation to LockoutManager
  • Replaced playerShadowBanLevel map with delegation to ShadowBanManager
  • Added /opshield status command for runtime diagnostics (shows active levels, flagged IPs, queue sizes)
  • Added debugLog() helper — controlled by debug: false config key; never exposes sensitive info in production

✨ New Features

  • debug mode (debug: false in config.yml) — enables verbose internal logging for troubleshooting without recompiling
  • /opshield status — new sub-command with opshield.status permission; reports shadow-ban level count, flagged IPs, sensitive-history windows, auto-punishment state
  • security.password.auto_upgrade_legacy_hash: true — automatically re-hashes a legacy SHA-256 password to PBKDF2 the next time the correct password is provided; hash is saved to config.yml with no manual action required
  • Audit queue capacity (audit.max_queue_size: 10000) — prevents unbounded memory growth if disk writes fail; oldest entries dropped with a console warning (rate-limited to once per flush cycle)
  • Audit JSON format (audit.format: json) — emits one machine-readable JSON object per line for log aggregator ingestion; plain format unchanged for backwards compatibility

🐛 Bug Fixes

  • ShadowBanManager.getFakeActionMessage() was never called — v1.7.0 added it but the main class still used hard-coded logic. Now the manager is the sole source of fake messages
  • LockoutManager.ipLimitMap was unusedrecordIpConnection() was called but the data was never read. Removed; IP limit tracking remains in OPShield.java pending IpLimitManager extraction
  • PasswordHasher.upgradeHashIfNeeded() (NEW) — isLegacyHash() existed in 1.7.0 but there was no code path to actually upgrade the stored hash. Now the main class calls upgradeHashIfNeeded() after each successful login when auto_upgrade_legacy_hash: true
  • HASH_FORMAT_VERSION constant (NEW) — the string "pbkdf2" was scattered as a magic literal across PasswordHasher; centralised to a named constant

🔧 Build Improvements

  • maven-compiler-plugin 3.13.0 added with explicit <release>21</release> and <parameters> flag
  • maven-shade-plugin 3.6.0 added (no relocations yet, but scaffold is ready for future bundled deps)
  • maven-surefire-plugin 3.2.5 added with JUnit 5 + Mockito test dependencies for unit testing managers
  • Centralised version propertiesjava.version, paper.version, and plugin versions now all defined in <properties> for consistency

📝 Configuration

  • Added config-version: 2 — allows future automatic migration detection
  • Added debug: false — verbose diagnostic logging toggle
  • Added security.password.auto_upgrade_legacy_hash: true
  • Added audit.max_queue_size: 10000
  • Added audit.format: plain
  • Added shadow_ban.auto_punish_level default raised from 35
  • Added inline "Recommended values by server size" comments to config.yml

🌍 Language Files

  • Added 7 new shadow-fake message keys: shadow_fake_op, shadow_fake_deop, shadow_fake_kick, shadow_fake_pardon, shadow_fake_stop, shadow_fake_reload (all three languages)
  • Fixed inconsistent Vietnamese translations in vn.yml
  • All three language files now use natural-language fake messages that better blend in with real server output

📊 Code Quality Metrics

Metricv1.7.0v1.8.0
Raw state maps in OPShield.java73
Manager classes2 (stub)2 (fully active)
Permissions with insecure default op60
Hard-coded fake messages80
Unused manager methods20
config-version
Debug mode
Audit queue cap
JSON audit format

📝 Migration Notes

  1. Permission plugin setup required — add opshield.admin to your OP group (see CRITICAL note above)
  2. data.yml is auto-migrated from v1.7.0 format on first boot — no manual action needed
  3. All configuration keys are backwards-compatible; new keys use sensible defaults
  4. Old lockout_timestamps / failed_attempts / lockout_count / last_lockout_at sections in data.yml are read on upgrade and merged into lockout_records; old sections are replaced on next save

🔮 Planned for v1.9.0

  • Extract AutoPunishmentManager — move all ban/kick/firewall logic out of OPShield.java
  • Extract IpLimitManager — move IP tracking and flagging
  • Extract CommandRestrictionManager — move matchesConfiguredCommand logic
  • Add unit tests for LockoutManager and ShadowBanManager
  • Consider Argon2id as an optional stronger hashing algorithm

OPShield 1.7.0

release24 апреля 2026 г.

[1.7.0] - 2026-04-24 — Architecture Improvements & God Class Refactoring

🚀 Improvements

Architecture Refactoring

  • LockoutManager (NEW) — Extracted lockout logic from main class

    • Centralized player/IP lockout state management
    • Clean public API for lockout operations
    • Expired lockout cleanup methods
  • ShadowBanManager (NEW) — Extracted shadow ban logic

    • Shadow ban state tracking
    • Fake action message generation
    • Duration management with expiry cleanup
    • Improved message consistency

Password Security

  • PasswordHasher improvements — Enhanced password handling
    • PBKDF2 iteration count configurable at runtime
    • Legacy SHA-256 detection with isLegacyHash() method
    • Iteration count validation (10,000 - 1,000,000 range)
    • Better separation of hash versioning concerns

Code Organization

  • Created manager/ package for extracting business logic
  • Reduced OPShield.java God Class burden
  • Better separation of concerns
  • Improved testability of individual components

Language Files

  • Fixed grammar inconsistencies (e.g., "1 player" vs "1 players")
  • Improved fake action message clarity
  • Better error message wording

📊 Code Quality

Metrics

  • Before: 1,172 LOC in single class (God Class)
  • After: OPShield.java reduced + 2 new manager classes
  • Managers Created: 2 (LockoutManager, ShadowBanManager)
  • Lines Extracted: ~300+ from main class

Quality Improvements

  • ✅ Reduced cyclomatic complexity in main class
  • ✅ Improved code organization
  • ✅ Better separation of concerns
  • ✅ More testable components
  • ✅ Easier to extend for future features

📝 Migration Notes

For existing servers:

  1. No database migration needed
  2. All configuration stays the same
  3. No command changes
  4. Direct drop-in JAR replacement

🔮 Future Work (v1.8.0+)

Recommended further refactoring:

  • Extract AutoPunishmentManager for ban/kick logic
  • Extract IpLimitManager for IP tracking
  • Extract CommandRestrictionManager for command validation
  • Create interface-based services for better testability
  • Add unit tests for new manager classes

OPShield 1.6.0

release21 апреля 2026 г.

[1.6.0] — 2026-04-21

Bug fixes

High severity

  • AuditLogger switched from FileWriter to NIO Files.write()FileWriter used the JVM platform default charset, which could produce garbled or truncated log entries on servers whose OS locale is not UTF-8. All writes now use java.nio.file.Files.write() with an explicit StandardCharsets.UTF_8 argument and StandardOpenOption.APPEND.

  • ensureFile() is no longer called on every flush tick — the previous implementation re-checked (and conditionally re-created) the log file and its parent directory on every async flush, even when neither had changed. An AtomicBoolean fileReady flag now gates the check so it runs at most once per file lifetime. The flag is cleared after rotation so the next write correctly re-creates the log file.

  • Failed audit writes now re-queue entries instead of silently discarding them — if a flush attempt throws IOException, the affected lines are returned to the front of the queue and retried up to MAX_WRITE_RETRIES (2) times. On final failure a SEVERE console error is printed and the lines are re-queued so they are not permanently lost.

Medium severity

  • Legacy SHA-256 password hash triggers a console warning on startup — if op_password_hash in config.yml contains an old SHA-256 value (generated by OPShield < 1.4.0), the server console now displays a clear warning advising the admin to reset the password so it is upgraded to PBKDF2 storage. The plugin continues to accept the legacy hash for authentication; no data is lost.

Low severity

  • Magic string "unknown" for unresolvable player IPs replaced with named constant UNKNOWN_IP — eliminates the class of silent typo bugs where inconsistent string literals caused an IP to be handled as a real address in some code paths but skipped correctly in others.

  • Grammar correction in English shadow-ban fake messagesshadow_fake_clear incorrectly read "Cleared the inventory of 1 players". Corrected to "Cleared the inventory of 1 player". Related entity messages (shadow_fake_kill, shadow_fake_tp) also updated to use the singular form "entity" for consistency.

  • folia-supported: false added to plugin.yml — OPShield uses the Bukkit task scheduler and is not compatible with Folia. The flag prevents Folia auto-detection from incorrectly classifying the plugin as Folia-safe and loading it on an incompatible runtime.

  • auto_punish_firewall_fail message key added to all language files — previously the firewall punishment path had no dedicated message for the case where the script is skipped (unsafe exec disabled, blank script, or unknown IP). All three language files (en.yml, vn.yml, ru.yml) now include the key.

Improvements

  • PBKDF2 iteration count is now configurable via security.password.pbkdf2_iterations (default 120000, range 100001000000). Increasing the value raises brute-force resistance at the cost of slightly slower verification on each /op or /deop attempt. Existing stored hashes are unaffected — they carry their own iteration count.

  • firewall_script config entry now includes OS-specific examples — the config comment now shows both a Linux iptables example and a Windows netsh example so admins know the expected format without having to consult external documentation.

New config keys

KeyDefaultDescription
security.password.pbkdf2_iterations120000PBKDF2 iteration count for new password hashes (10 000–1 000 000)

New language keys (all files)

KeyDescription
auto_punish_firewall_failShown when firewall punishment is skipped and player is kicked instead

OPShield 1.5.0

release20 апреля 2026 г.

[1.5.0] — 2026-04-19

Bug fixes

Medium severity

  • sensitiveCommandHistory now persisted to data.yml — the auto-punishment rolling window survived previously only in memory, allowing players to bypass the threshold by timing restarts or crashes. Timestamps are now written on every dirty flush and restored on startup; stale entries outside the configured window are discarded automatically on load.
  • Shadow-ban level escalation is now enforcedplayerShadowBanLevel was incremented and stored but never acted upon. A new config key shadow_ban.auto_punish_level (default 3) defines the threshold at which the level triggers real auto_punishment and then resets. Requires auto_punishment.enabled: true.
  • Firewall script no longer blocks the main threadexecuteFirewallBlock previously called Runtime.getRuntime().exec() synchronously, which could freeze the server if the script was slow. It now runs asynchronously via ProcessBuilder with a configurable hard timeout (auto_punishment.firewall_timeout_seconds, default 10). The player is kicked immediately on the main thread; the OS script executes in the background.

Low severity

  • unlockIdentifier() now clears sensitiveCommandHistory — previously, /opshield unlock cleared all other tracking maps but left sensitiveCommandHistory intact, causing inconsistent state after a manual unlock.
  • getMsgPlain() replaced fragile color-strip logic — manual replace('&X', "") calls missed several color codes and decorators. Now uses Adventure's PlainTextComponentSerializer for correct, future-proof plain-text extraction.
  • Multi-file audit log rotationAuditLogger previously kept only one backup file (audit.log.1), permanently overwriting it on every rotation. Rotation now shifts files: audit.log.1audit.log.2 → … → audit.log.N. Controlled by audit.log_retention (default 3).
  • Config validation for auto_punishment.command — an unrecognized mode with no custom_command set now prints a clear console warning on load and reload instead of silently falling back to a potentially unexpected behaviour.

New config keys

KeyDefaultDescription
shadow_ban.auto_punish_level3Shadow-ban level threshold that triggers auto-punishment
audit.log_retention3Number of rotated audit log backup files to keep
auto_punishment.firewall_timeout_seconds10Max seconds before a hung firewall script is force-killed

OPShield 1.4.0

release14 апреля 2026 г.

[1.4.0] — 2026-04-14

Security hardening

  • migrated password storage to op_password_hash so plaintext is no longer kept in config after migration
  • added PBKDF2 password hashing for new stored credentials
  • preserved backward compatibility for older SHA-256 hashes during migration
  • made firewall execution explicitly unsafe and opt-in only via allow_unsafe_firewall_exec
  • disabled auto-punishment by default to reduce accidental false positives on fresh installs

Logic fixes

  • fixed IP-limit detection so it counts unique accounts inside a real rolling time window
  • changed OP whitelist enforcement to apply to /op only
  • added lockout count decay after a configurable cooling-off period
  • cleaned expired lockouts and expired IP flags automatically on a schedule
  • localized shadow-ban fake success messages instead of hardcoding English strings in Java

Performance and maintainability

  • replaced repeated async save spawns with a debounced persistent save loop
  • replaced synchronous audit file writes with queued async flushes
  • added basic audit log rotation
  • cached CommandMap reflection result instead of resolving it on every blocked command
  • split hashing and audit logging into dedicated helper classes

Permissions and command handling

  • added opshield.op
  • added opshield.deop
  • added opshield.admin
  • added opshield.bypass
  • kept /opshield reload and /opshield unlock <player|ip> as admin management commands

Config changes

  • added op_password_hash
  • retained op_password only as a legacy migration input
  • added broadcast_on_privilege_change
  • added audit.*
  • added security.lockout.track_ip
  • added security.lockout.count_decay_hours
  • added auto_punishment.window_seconds
  • added auto_punishment.custom_command
  • added auto_punishment.allow_unsafe_firewall_exec
  • added ip_limit.auto_punish
  • added ip_limit.flag_duration_minutes

Совместимость

Minecraft: Java Edition

1.21.x

Платформы

Поддерживаемые окружения

Сервер

Создатели

Детали

Лицензия:Apache-2.0
Опубликован:2 месяца назад
Обновлён:2 недели назад
Главная