Understand trust, authentication, transport admission and the limits of local and network isolation. Wire contracts follow the Core specification, Prelude Extension and Egress Extension.
- Certificate trust
- Connection authentication
- SOCKS5 ingress
- Morph transport protection
- Observable boundaries
- Admission and Flow resources
- Flow lifetime and exit ownership
- Local IPC
- Metadata and diagnostics
Vector and Egress require system CA trust with hostname validation, or an exact
certificate SHA-256 pin. TLS 1.3 and ALPN nw3 are mandatory. 0-RTT is disabled,
including on resumed connections.
| Trust mode | Verification |
|---|---|
| System CA | The certificate chain is trusted and the server name matches |
| Exact pin | The presented leaf certificate matches the configured SHA-256 fingerprint |
| Fingerprint inspection | Reads the presented certificate for separate trust verification |
A pin is 64 lowercase hexadecimal characters. A missing, empty or none pin
uses normal certificate verification. Explicit fingerprint inspection does
not establish trust; compare its result through a trusted channel before use.
See Operations for inspection commands.
Pinning checks the SHA-256 digest of the leaf certificate and the TLS handshake signature; it does not perform CA-chain, hostname or certificate-validity checks. A pin therefore needs its own trusted provisioning and rotation process.
With the default tls=1, Portal generates a new self-signed certificate on each
start. Pinned clients need the newly verified fingerprint after a restart. With
tls=2, Portal loads the supplied certificate and key at startup. Once
NOW_RELOAD_INTERVAL has elapsed, a subsequent handshake attempts a reload; a
failed reload is logged and leaves the last valid certificate in use. Coordinate
certificate rotation with pinned clients, which each accept one configured pin.
AuthFrame is a 16-byte HMAC tag over the transport byte and normal TLS exporter. Tags are compared in constant time and bind authentication to the connection, transport and role, including on resumed TLS connections. The Core specification defines Vector authentication; the Egress Extension defines the additional role key.
Portal, Vector, Egress, Probe and fingerprint inspection require exactly 32
lowercase hexadecimal text characters. Shared Key is percent-decoded once and
used as text bytes.
nowhere generate-key encodes 16 cryptographically random bytes as text,
providing 128 bits of entropy. The accepted format alone does not guarantee
entropy; key derivation does not increase it.
One credential derives both Vector and Egress role keys. Sharing it shares its authority; role derivation does not provide independent credential permissions.
Vector's SOCKS5 listener is a separate trust boundary from the encrypted Vector-to-Portal connection:
+-------------+ SOCKS5 +----------+ TLS / QUIC +----------+
| Application |---------------->| Vector |=================>| Portal |
+-------------+ +----------+ +----------+
No Nowhere encryption Morph optional
Without configured SOCKS credentials, any client that can reach the listener can use it. SOCKS username/password authentication does not encrypt that hop. Restrict access to the TCP listener and the ephemeral UDP sockets used by UDP ASSOCIATE. See SOCKS5 ingress.
Morph masks the transport wire image. TLS/QUIC supplies authenticated encryption and integrity. TCP bootstrap authentication and UDP version filtering apply at different ingress stages; neither replaces AuthFrame authentication.
Each TCP cipher direction is limited to 2^38 - 64 bytes to prevent cipher
block-counter wrap within a connection. The 96-bit TCP Nonce is randomly
generated, so uniqueness across connections sharing a key is probabilistic.
A repeated Nonce reuses the outer Morph keystream; Prelude counters do not
prevent that collision.
Portal requires a valid 14-byte Prelude Tag and Counter before ClientHello parsing. All configured Prelude policies use the same authentication and replay checks.
Replay precheck precedes silent ClientHello parsing. After rustls Acceptor accepts ClientHello, Portal checks the deadline and atomically rechecks and commits replay state before any TLS response. Incomplete or malformed ClientHello does not reserve a Counter. Later TLS or AuthFrame failures do not undo a commit.
Each Identity has a 1024-bit replay window while it remains in the 16,384-entry FIFO registry. Eviction or Portal restart removes its history. Shared Key holders can churn the registry or advance replay windows; random 64-bit Identity collisions can cause unwanted window sharing.
Portal reads ClientHello through rustls Acceptor without sending parser alerts.
Before acceptance, incomplete or rejected input, including a peer's write-side
FIN, is held silently until the authentication deadline. The absolute deadline
starts when TCP accept completes and covers Prelude, Nonce, ClientHello, TLS
and AuthFrame together. NOW_HANDSHAKE_TIMEOUT controls it; its unset default is
derived once from the Shared Key in the range 3–30s. See
timeout semantics.
Shutdown may end the connection earlier. Resets and unrecoverable I/O failures
detected while reading may also end it before input is rejected.
When authentication processing is full, Morph TCP connections wait silently without reading input, creating TLS state or holding a processing or business connection permit. Released processing permits wake waiting connections to retry admission within their original deadline. Waiting does not guarantee ordering or eventual admission under sustained contention.
Silent rejection during authentication immediately stops reading and retains the socket and processing permit until the original deadline. Further input, FIN or RST does not shorten or extend that wait. Portal sends no filler data and introduces no random delays.
The silent stage ends after ClientHello acceptance, successful replay commit
and the deadline check. Configuration-dependent ClientHello checks, TLS
completion and AuthFrame validation follow; TLS processing can send alerts
at this point. Standard TLS (morph=0) and QUIC do not use this stage.
For Morph TCP, Portal enables SO_LINGER=0 when TCP accept completes and
retains it through TLS, ALPN and AuthFrame verification.
| Authentication state | Socket close policy |
|---|---|
| Prelude, replay or ClientHello checks incomplete or rejected | Zero linger; abortive close |
| TLS, ALPN or AuthFrame incomplete or rejected | Zero linger; abortive close |
| Complete authorized Vector or Egress AuthFrame within the deadline | Restore normal linger; normal close and half-close |
Portal checks the original deadline before and after restoring normal linger. Expiry retains zero linger; failure, timeout or cancellation before successful authentication does not restore normal linger. Socket-option failures terminate the connection without forwarding.
On Linux, zero linger requests RST even with unread data. Packet-level FIN/RST behavior on other operating systems depends on the kernel. Resource rejection before connection authentication begins and socket-option failures are outside this close policy's guarantees.
After unmasking, Portal checks the first QUIC packet in each UDP datagram before handing it to Quinn. A long header with an incomplete or unsupported Version, including Version 0, is silently discarded. Supported versions follow Quinn's default endpoint version list. Short headers pass to Quinn without version filtering.
Each UDP GRO segment is checked independently. This filter applies only to Portal's Morph UDP ingress; native QUIC retains its normal Version Negotiation behavior. The filter adds no replay state or authentication exchange.
Portal requires Retry for QUIC connections whose remote address has not been validated. Version filtering does not change address validation, TLS, AuthFrame or business Flow admission.
The UDP Prelude contains 12 policy-generated random bytes. It provides neither identity authentication nor replay protection and is separate from every encrypted datagram's Morph Nonce. Portal silently discards it without a response or authentication state. QUIC uses TLS 1.3 and AuthFrame for connection protection and authentication.
Transport admission limits early responses. Its protection depends on the input and the stage it reaches:
| Input or stage | Observable behavior |
|---|---|
| Rejected Morph TCP bootstrap or ClientHello | No parser response before the original deadline; socket closure remains observable |
| Accepted Morph TCP ClientHello with committed replay state | TLS responses and later alerts are possible before AuthFrame succeeds |
| Unsupported-version Morph UDP long header | Silently discarded before Quinn; no Version Negotiation response |
| Captured valid Morph QUIC Initial | Replay can trigger Retry or other QUIC responses, depending on packet and address-validation state |
| Standard TLS or native QUIC | Uses the transport's normal response behavior |
RST, deadlines, business connection limits and operating-system resource exhaustion remain observable. These protections do not eliminate all active-probing or traffic-analysis fingerprints. Morph UDP version filtering does not authenticate datagrams or provide replay protection. TLS and AuthFrame must succeed before target access.
The Prelude Tag authenticates bootstrap metadata, not the encrypted TLS stream. An observer who knows a captured ClientHello field's position and value can modify its Morph ciphertext without the Shared Key. Modified input may pass Acceptor and trigger later alerts; a captured bootstrap can race its first use with a modified ClientHello and consume its Counter.
A captured bootstrap also permits offline verification of candidate Shared Keys through its Tag. Prelude masking has no forward secrecy: disclosure of the Shared Key permits decoding captured Identity and Counter metadata.
Authentication precedes target work and Egress registration. Portal applies these limits before accepting a role:
| Resource | Pre-authentication limit |
|---|---|
| Authentication processing | 256 total; 32 per IPv4 source or IPv6 /64, shared by TCP and QUIC |
| QUIC Stream credit | One client bidirectional Stream; no unidirectional Streams |
| QUIC connection receive window | 64 KiB |
| Handshake and authentication | NOW_HANDSHAKE_TIMEOUT, Shared Key-derived default 3s–30s |
Morph TCP connections waiting for authentication processing are bounded by the operating system's file descriptor limit, not a separate application quota. They retain a socket and task until admission, the original deadline or shutdown. Accepted connections also require a shared connection permit (1024 total), held through their business lifetime; parked connections do not hold this permit. Temporary TCP accept resource failures use a 10 ms exponential backoff capped at 250 ms, reset after a successful accept. Existing tasks continue to run and expire during backoff. Extreme load can exhaust file descriptors, memory or CPU, degrade service and require operational intervention. QUIC requires Retry for unvalidated addresses and ignores arrivals when admission is full.
After authentication, receive windows are raised to the selected QUIC profile. Business resources remain bounded by target Flow permits, Stream credit, UDP queues, reassembly reservations and transport receive buffers. See Configuration for runtime settings.
UDP DATAGRAM bypasses Stream flow control. Unknown, pre-READY and unauthenticated
IDs are discarded. Reassembly permits 64 partial packets per connection with a
ten-second TTL. Queued datagrams and fragments share the per-connection
NOW_QUIC_UDP_QUEUE_BYTES budget (default 4 MiB), separate from QUIC's DATAGRAM
receive and send buffers (4 MiB each). Reservations remain held until delivery
or cleanup. Full Flow queues use nonblocking dispatch so one slow Flow cannot
stall the connection.
Stream direction and the 30-bit derived UDP ID range are checked before use, without truncation. ID exhaustion stops admission and triggers a bounded drain and close or reconnect. FIN, RESET, STOP_SENDING, idle timeout and connection loss reclaim UDP routes independently of CLOSE DATAGRAM delivery.
Egress registers only when Portal has out=egress. Queue claims and cleanup
are tied to the actual connection. Egress waits for ACCEPTED before target work.
Offline Flows wait within the setup deadline, without local fallback. Vector
connection acquisition, request writing and READY reading share one Flow setup
deadline; timeout drops pending streams and UDP routes. A temporary first-Flow
QUIC connection is closed, while a reused connection retains its other Flows.
QUIC Egress registration bounds Stream acquisition, AuthFrame sending and the
complete ACCEPTED reply with one handshake deadline. See
Egress ownership.
DNS and target sockets belong to the selected exit. Explicit source binding errors fail the dial and do not retry with an automatic source.
Local observation is restricted to the service's operating-system user.
| Boundary | Protection |
|---|---|
| Unix registry and sockets | Permissions and symlink/object checks |
| Windows registry and named pipes | ACLs and peer checks |
| Collector discovery | Registry/Hello consistency, process liveness and platform peer identity |
| Linux and Windows discovery | Additional process-incarnation checks |
Discovery and cleanup stay inside the documented IPC namespace. Administrators and compromised processes running as the same user are outside this isolation boundary.
A 64 KiB server frame ceiling, 16-client limit and bounded writes constrain resource use. A five-second write deadline disconnects blocked consumers. See Telemetry for limits and identity requirements.
Startup output omits Shared Key and SOCKS credentials. Private key contents are never logged. IPC metadata exposes validated service endpoints to authorized collectors; it includes no configuration summary, client address or transport peer identity.
IPC carries instance identity and six statistics. It contains no Flow events, error messages or logs.
Service errors preserve their original cause chains and can contain addresses or paths. Error construction excludes passwords, Shared Keys and complete credential URLs. See Telemetry privacy.