Skip to content

dev -> main - add embedded web UI, monitoring endpoints and API hardening - #25

Draft
GIC-de wants to merge 16 commits into
mainfrom
dev
Draft

GIC-de wants to merge 16 commits into
mainfrom
dev

Conversation

@GIC-de

@GIC-de GIC-de commented Oct 3, 2026

Copy link
Copy Markdown
Member

Summary

This PR merges dev into main. It adds an embedded web UI, a set of new read-only REST endpoints that the UI uses, protections for the unauthenticated API, and reworked Debian packaging.

⚠️ Behavior changes

  • The web UI is on by default. It is served on /. Disable it with -ui=false.
  • File upload is on by default. The -upload flag now defaults to true. Disable it with -upload=false.
  • The interfaces endpoint is on by default. GET /api/v1/interfaces can be disabled with -interfaces-api=false.
  • The default bngblaster path changed from /usr/sbin/bngblaster to /usr/bin/bngblaster. Override it with -e.
  • Relative stream_config paths must stay inside the instance folder. Absolute paths, for example files in home directories, are still used as-is.
  • Cross-origin state-changing requests are rejected. The check uses Sec-Fetch-Site/Origin.
  • Log output is split by level. Warn and above goes to stderr. Info, debug and trace go to stdout.

Note: The web UI, file upload and the interfaces endpoint are on by default only for the beta. These defaults may change before the final release, so pass the flags explicitly (-ui, -upload, -interfaces-api) if your setup depends on them.

✨ Features

Embedded web UI

  • Plain HTML/CSS/JS single-page app, embedded with go:embed. It has no build step and no framework.
  • Lists instances and handles their lifecycle (create, edit config, start, stop, delete).
  • Edits instance config against the bngblaster JSON schema.
  • Shows an overview with interface stats, including loss count and loss % (0.001% precision, red when > 0).
  • Has views for streams, sessions, BGP, logs and files (download/upload).
  • Progress bars.

New API endpoints

Method Path Description
GET /api/v1/schema bngblaster config JSON schema (path set with -schema)
GET /api/v1/interfaces Host network interfaces (behind -interfaces-api)
GET /api/v1/instances/{name}/_overview Aggregated instance overview
GET /api/v1/instances/{name}/_streams Paginated stream summary
GET /api/v1/instances/{name}/_sessions Paginated session summary
GET /api/v1/instances/{name}/_logs Instance log output
GET /api/v1/instances/{name}/_files List instance files
GET /api/v1/instances/{name}/_files/{file_name} Download an instance file
GET /docs/ Embedded Swagger UI and OpenAPI definition
  • Stream, session and overview results are cached per instance for a short time. Concurrent identical requests share one fetch, and the cache is invalidated on lifecycle changes.
  • docs/swagger.yaml is extended to cover all new endpoints.

New flags

  • -ui (default true)
  • -interfaces-api (default true)
  • -schema (default /usr/share/bngblaster/bngblaster-config.json)
  • -allowed-hosts: comma-separated Host header allowlist against DNS rebinding. IP addresses and localhost are always allowed. An empty value allows any host.

🔒 Security hardening

  • Cross-origin check for state-changing requests.
  • -allowed-hosts Host header allowlist.
  • Security headers and a Content Security Policy on every response.
  • Bounded request bodies. Uploads larger than the free disk space are rejected.
  • Uploads of controller-managed run files (run.pid, run.sock, …) are rejected, as are pids <= 1. This prevents killing arbitrary processes as root.
  • Uploads and downloads are confined to the instance folder. File names are sanitized against path traversal.
  • Audit log of the client address for requests and lifecycle changes.
  • systemd unit sandboxing: ProtectSystem=full, ProtectHome=read-only, PrivateTmp, kernel/cgroup/clock/hostname protection, RestrictSUIDSGID, LockPersonality.

🐛 Fixes

  • Graceful HTTP shutdown (30s timeout) lets in-flight requests and downloads finish. File transfers have no write deadline.
  • Instance files are served with Cache-Control: no-cache, and config.json is fetched with no-store. The config editor no longer reopens a stale version.

📦 Packaging (deb / systemd)

  • New /etc/default/rtbrick-bngblasterctrl with BNGBLASTERCTRL_OPTS to pass flags to the service.
  • New logrotate config.
  • Service state is kept on upgrade, and a postrm script is added. The package recommends bngblaster.
  • The service is re-enabled after upgrading from ≤ 0.1.3. The old prerm stopped and disabled it.

🛠 Build / CI / maintenance

  • Go upgraded from 1.25 to 1.27.1. testify bumped from 1.4.0 to 1.12.1.
  • golangci-lint v2 config and a CI lint job (fails only on new issues). The linter is built from source for Go 1.27 compatibility.
  • GitHub Actions bumped: checkout/setup-go v7, golangci-lint-action v9, goreleaser-action v7.
  • CI builds an installable dev package with a goreleaser snapshot and uploads it as the bngblasterctrl-dev artifact. The version scheme is <next patch>~dev.<time>.<commit>, so the next release upgrades over it.
  • Stream and session pagination share a generic summary handler (summary.go), and lint findings are fixed.
  • Copyright updated to 2020-2026. CLAUDE.md added. README updated for the new flags, defaults and hardening.

🤖 Generated with Claude Code

GIC-de and others added 16 commits September 11, 2026 18:41
- reject uploads of run files and pids <= 1 (kill as root)
- graceful HTTP shutdown; no write deadline for file transfers
- deb: keep service state on upgrade, add postrm, recommend bngblaster
- golangci-lint v2 + CI lint job, testify bump, swagger _overview

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- reject cross-origin state-changing requests (Sec-Fetch-Site/Origin)
- add -allowed-hosts Host header allowlist against DNS rebinding
- security headers and CSP on every response
- bound request bodies, reject uploads larger than free disk space
- restrict stream_config to files inside the instance folder
- audit log client address for requests and lifecycle changes
- systemd unit sandboxing; document in README, swagger and CLAUDE.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- interface stats: loss count plus ratio (0.001%), red when > 0
- progress bars: 3 decimals rounded down, so 9999/10000 no longer shows 100%
- serve instance files with Cache-Control: no-cache and fetch config.json
  with no-store, so the editor no longer reopens the previous version
- interface stats: loss count plus ratio (0.001%), red when > 0
- progress bars: 3 decimals rounded down, so 9999/10000 no longer shows 100%

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- stream_config: absolute paths are used as-is again, so stream files
  kept in home directories work; relative paths must still stay inside
  the instance folder
- systemd: keep home directories readable (ProtectHome=read-only) for
  stream, BGP and MRT files
- uploads and downloads remain confined to the instance folder
- update README, swagger and web UI hint

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deduplicate the stream and session pagination handlers into a generic
summary endpoint (summary.go), split Start's startup wait and the overview
fetch into their own functions, and fix the remaining style findings:
FlowID/SessionID naming, min/max and any, test file permissions, request
contexts and unused parameters. Allow generic returns in ireturn, as the
summary cache necessarily returns its type parameter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Build golangci-lint v2.14.0 from source in CI, as its prebuilt binaries
are built with go 1.26 and refuse to load a module targeting go 1.27.
Bump checkout and setup-go to v7, golangci-lint-action to v9 and
goreleaser-action to v7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run a goreleaser snapshot after build and test and upload the .deb,
tarball and checksums as the bngblasterctrl-dev workflow artifact.
Snapshot versions are now <next patch>~dev.<commit time>.<commit>, which
dpkg sorts below the upcoming release so it upgrades over a dev build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dpkg runs the old package's prerm on upgrade, and the one shipped up to
0.1.3 unconditionally stopped and disabled the service, so try-restart
left it stopped and disabled. Those versions always enabled the service
on install, so restore that when upgrading from them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant