Local load-testing dashboard for Eaglercraft Minecraft servers (WebSocket). For **authorized** testing only — you must own the target server or have written permission. ## What it does Spawns a configurable number of fake MC 1.12.2 (Protocol 340) clients over WebSocket, routes them through a SOCKS proxy pool, performs the EaglerV2 + MC login handshake, optionally sends `/register`/`/login` and chat messages, and keeps them alive on keep-alive packets. The dashboard shows live bot state, proxy health, and structured logs. ## What's new in v2 - **MC protocol fix:** proper length-prefixed packet framing, `Set Compression` handling, and correct `Position and Look` parsing (Little Endian, bitmask, VarInt teleport ID). - **Compression-aware:** bots negotiate compression when the server enables it (zlib raw). - **Auth state machine:** structured matching on `translate` keys (`commands.register.success`, etc.) instead of brittle substring search. - **Proxy registry v2:** JSON persistence, scoring (0–100), weighted picking strategies (`best-score`, `round-robin`, `least-used`, `random`), per-proxy inflight caps, EMA latency, automatic retest-after-cooldown. - **Per-bot inspector:** click "Inspect" on any bot to see packets, proxy, last error, and chat from a single bot. - **Rate limits:** login, proxy upload, test start, broadcast chat all rate-limited. - **Security:** `helmet` CSP, `httpOnly` + `sameSite=strict` cookies, HMAC-SHA256 session tokens, constant-time password compare, refuses to boot with default `SESSION_SECRET`. - **Observability:** `/healthz`, `/metrics` (Prometheus), `/api/diagnostics`, structured JSON daily logs, log throttling. - **Frontend:** score-colored proxy table, log filter, search, level toggles, per-bot inspector panel. ## Quick start ```bash cp .env.example .env # if you don't have one # Edit .env: set SITE_PASSWORD and SESSION_SECRET npm install npm start ``` Open `http://localhost:6070` and enter your `SITE_PASSWORD`. ## Tests ```bash npm run check # syntax check on all source files npm test # unit tests (packets, codec, compression, auth, registry) npm run smoke # boot the server, hit endpoints, verify shape ``` ## Project layout ``` src/ config.js config loading + env validation state.js shared mutable state + event bus auth.js HMAC tokens, cookie parser, constant-time compare io.js Socket.IO + throttled broadcaster validate.js input validation server.js bootstrap (express, helmet, routes, lifecycle) proxy/ registry.js ProxyRegistry class (scoring, persistence, picking) lease.js per-test proxy lease workerPool.js generic async worker pool bot/ packets.js VarInt, strings, MC framing helpers codec.js Eagler + MC 1.12.2 packet parsers/builders compression.js zlib threshold handling auth.js AuthStateMachine bot.js Bot class — state machine routes/ auth.js /api/auth/* test.js /api/test/* proxy.js /api/proxy/* bots.js /api/bots/* stats.js /api/stats, /api/logs health.js /healthz, /metrics, /diagnostics util/ log.js structured logger (daily rotation) throttle.js throttle + coalescer test/ node:test unit tests scripts/ smoke.js end-to-end smoke test migrate-proxies.js one-shot proxies.txt → proxies.json ``` ## Environment | Var | Required | Description | |---|---|---| | `SITE_PASSWORD` | yes | Dashboard login password | | `SESSION_SECRET` | yes | Random secret for HMAC-signed cookies. Refuse to boot if unset or default. | | `PORT` | no | Override `config.yaml` server.port | | `HOST` | no | Override `config.yaml` server.host | ## Configuration `config.yaml` is non-sensitive. Top-level keys: - `server.{port, host}` — defaults to 6070 / 0.0.0.0 - `bots.{max_bots, default_rate, default_spawn_delay, max_spawn_delay, max_packet_rate, password, join_delay_ms, chat_messages, auth_phrases, auth_timeout_ms}` — bot limits and defaults - `proxy.{test_timeout_ms, concurrency, max_list_size, probe_host, probe_port, score_decay_ms, score_penalty_per_fail, score_recovery_after_ms, alive_latency_max_ms, per_proxy_inflight_cap, default_strategy}` — proxy pipeline tuning - `logging.{max_log_entries, max_dom_logs, daily_log_dir}` — log buffering - `auth.session_hours` — cookie lifetime - `rate_limits.*` — per-route limits - `cors.origins` — CORS allowlist; empty = same-origin only - `quick_commands` — list of `/command` strings available in the dashboard's quick-actions panel ## Threat model This tool is intended for **local development and authorized load testing** of servers you own or have explicit written permission to test. Use against systems without authorization is illegal. The dashboard binds to `0.0.0.0` by default; if you're on a multi-tenant host, override `HOST` in `config.yaml` to `127.0.0.1`. The default rate limits and CORS are tuned for single-user local use; if you expose this beyond localhost, add a reverse proxy with auth and tighten further. ## License MIT