Architecture
Hiatus Remote consists of six clearly separated processes. The supporter works in the client, the target runs service and agent, and the relay server sees nothing but encrypted packets in either direction. Video decoding runs in its own sandboxed process.
Components
| Process | Runs on | Task |
|---|---|---|
hiatus-client |
Supporter and target | User interface (Qt Quick): sessions, file browser, shell, Android debugging; the logic lives in Qt-free libraries |
hiatus-decoder |
Supporter | Decodes video, audio and clipboard images from the other side in its own process; AppContainer (Windows) or seccomp (Linux) |
hiatus-service |
Target | System service for unattended access; accepts connections even without a signed-in user and starts the agent in the user session |
hiatus-agent |
Target | Screen capture, input, files and audio in the respective user or login session |
hiatus-pty-host |
Target (Windows) | Holds terminal and shell for the remote shell as the signed-in user, not as SYSTEM |
hiatus-relay |
Server (Docker, Windows service) | Assigns IDs, brokers connections, rate-limits attempts and forwards packets when no direct path can be established |
Connection setup
From the ID request to the first frame: the password is never transmitted, the relay never gets to see it.
ID request. Both sides sign in to the relay over TLS 1.3, whose key is pinned via the SPKI pin in the access code, and receive their ID. The supporter requests the partner ID.
SPAKE2+ handshake. Over the signalling channel a shared key K_shared is derived from the one-time password without sending the password. Both device keys, the IDs and the protocol version go into the transcript.
Hole punching. Both sides exchange address candidates and attempt a direct UDP connection, with a targeted port search behind symmetric NAT. If that fails, the relay path remains; via TCP if UDP is blocked.
QUIC and channel binding. QUIC handshake (ngtcp2, TLS 1.3); the TLS exporter is bound to K_shared, direction keys are derived via HKDF. If a session starts via the relay, it switches to the direct path without interruption as soon as one is found.
Unattended access
With the Hiatus service a computer is reachable without anyone sitting in front of it, even at the login screen. The service checks the permanent password against a stored Argon2id verifier, matches the supporter's device key against the allowlist and starts the agent in the active session. Only an administrator can change the settings; on Linux through a polkit action.
Layer model
The logic lives in Qt-free libraries, the Qt Quick layer is thin. A CMake rule (hiatus_forbid_qt()) aborts configuration if a logic library links against Qt.
Qt Quick· windows, dialogs, bindings, view models: no logicsupport · adb· session logic, file transfer, shell, audit log, Android tools (file system, ADB shell, logcat)session · connect · remote· session protocol, connection setup, hole punching, relay fallback, host and viewer sideprotocol · net· message format (Protobuf), framing, QUIC (ngtcp2), TLS adapter with SPKI pinningcrypto · common· SPAKE2+, HKDF, AEAD, Argon2id, Ed25519; basic types, errors, logging
Network and relay
- Ports on the relay: the same port for TCP (TLS 1.3, signalling) and UDP (hole punching, forwarding), default 443, plus UDP 444 for address probes that detect symmetric NATs.
- Direct connections without a relay, for example inside a VPN: address instead of ID, default port 47443, certificate confirmed on first contact and pinned afterwards.
- Relay file or access code
hiatus://relay.example.org:443?pin=sha256:…for distribution to clients; the Docker image creates certificate and access code itself on first start. - Quality control: adaptive bitrate up to 16 Mbit/s and 60 frames/s, modes automatic, quality, speed, manual.
Test strategy
Unit
Every logic library without Qt and without network; CTest label unit.
Integration
Client, service and relay as real processes working together; NAT scenarios (cone, symmetric, UDP blocked, IPv6, VPN) in Docker.
Fuzzing · sanitizers
Protocol parsers with libFuzzer, ASan and UBSan; overnight runs over 26 targets, mutation tests against planted bugs.
BinSkim · clang-tidy
Hardening flags of the binaries (CFG, CET, ASLR, NX), static analysis with clang-tidy and MSVC /analyze, SBOM with CVE matching.
Technology stack
C++23 with CMake and vcpkg; Qt 6 for the client (LGPLv3, dynamically linked); OpenSSL for TLS and cryptographic primitives; ngtcp2 for QUIC; Protobuf for messages; OpenH264 and libyuv for video, Opus for audio, libvterm for the terminal; SQLite for the relay's device database; asio for network I/O. Packages: MSI (WiX) for Windows, systemd units and a polkit policy for Linux, a Docker image for the relay.
