Skip to content

NexaPipe v0.6.0

Choose a tag to compare

@open-nexa open-nexa released this 11 Oct 01:55
· 238 commits to main since this release
b1a6f48

Every device now holds a credential of its own, so revoking one no longer rotates
the rest. A config.toml written before this release loads unchanged: a client
carrying only secret keeps authenticating exactly as it did.

One thing breaks. /metrics renders request latency as a histogram:
nexapipe_request_duration_ms_bucket{le="…"} beside _sum and _count replaces
nexapipe_request_duration_ms_total. A scrape or dashboard looking for the old
counter will not find it; a mean that used to divide it by
nexapipe_requests_total reads _sum the same way.

Added

  • Per-device credentials. [auth.clients.<id>] gains a devices table — one
    TOTP secret per device, issued at enrollment and revoked on its own:

    [auth.clients.client-001.devices.laptop]
    secret = "LAPTOPSECRET"

    Nothing there is written by hand: enrollment files the device, and so does
    nexapipe client add client-001 --device laptop.

  • Revocation closes what the device already holds, not only what it dials
    next. The reload that notices a device left [auth] closes its connections,
    with a new close code REVOKED = 6 that the client reports as "this credential
    is gone" rather than as a code typed wrong.

  • Each install says which device it is. The desktop answers after its
    hostname, Android after the device model. The name is claimed at enrollment and
    nowhere else, so nothing re-enrolls on its own, and a credential that was never
    issued to a device keeps answering as it does today.

  • An access line says whose request it was. Every line ends
    client=… device=…, and /v1/connections answers who is connected rather than
    only how many.

  • nexapipe client list|add|revoke, each taking --device, writing
    config.toml through the same lock the server reads it with — a running
    instance picks the change up on its next reload. /v1/* stays read-only on
    purpose: its token has no scope and no rotation.

  • [auth.clients.<id>].unnamed_device_allowed (default true): set to
    false, a peer that names no device is refused rather than answered under the
    client's shared secret.

  • A systemd unit for the server in both READMEs. The relay has had one in
    docs/self-hosted-relay.md since earlier in this release.

  • Desktop: session totals, and a page listing the connections a running proxy
    holds. A running proxy says what quitting should do.

Changed

  • Request latency on /metrics is a histogram (see above).
  • The desktop TUN shares DNS and address space with other TUN apps, instead of
    taking both over.
  • The workspace declares the Rust version it needs: 1.89.

Fixed

  • A name outside the hijack is answered through the host's own resolver, instead
    of the TUN swallowing it.
  • Desktop: no empty window while the app starts; a launch with no frame still
    sends its start-up timings; the macOS bundle keeps the content security policy;
    the build gets the vendored smoltcp patch; a tunnel whose DNS was never
    hijacked no longer runs as though it had been.
  • Server: an enrollment can no longer take over a device that is already in the
    table; a peer is no longer connected before it is revocable; client add
    fails instead of reporting a secret it did not write.
  • Android: no native crash on the stop path, no stop on the main thread, no
    credential stored unencrypted without asking.
  • config.toml and the --qr-out file are created private, and neither follows
    a symlink to reach the file; [peers] refuses a key it does not recognise; a
    TOTP period that does not fit is refused at enrollment; each TUN flow and every
    preconnect runs under a budget.

Not in this release

Per-device key pairs (the credential stays TOTP), a write API (client add|revoke are subcommands, not POST /v1/clients), and package managers.


Full detail in
CHANGELOG.md;
what comes next in
docs/ROADMAP.md.