106 lines
5.1 KiB
Markdown
106 lines
5.1 KiB
Markdown
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
|