Repository navigation
01 architecture
Scope: this document describes the whole system. Section 2 covers the browser client, section 3 hosting a service, section 4 addressing/routing, section 5 security, and section 6 the roadmap. This file and
02-addressing-and-routing.mdare the foundation the rest builds on.
Nym is a packet-level mixnet, not a VPN and not Tor. It protects metadata (who talks to whom, when, how often) by moving every message through a sequence of nodes that each delay and reorder traffic. Two properties drive every design decision below:
- Uniform packets. Every regular Sphinx packet is exactly 2413 bytes (348-byte header + 17-byte payload overhead + 2048-byte plaintext). If size varied, an observer could fingerprint routes.
- The client knows the whole path; no node does. Only the sender chooses Entry Gateway → Mix L1 → L2 → L3 → destination. Each hop learns only its immediate predecessor and successor.
The component roles in the current (2025–2026) network:
| Role | Runs as | Job |
|---|---|---|
| Mix Node | nym-node --mode mixnode |
Decrypt one Sphinx layer, random delay, forward. Three layers in production. |
| Entry Gateway | nym-node --mode entry-gateway |
Public WSS endpoint. Clients connect here; stores messages for offline clients. First Sphinx hop. |
| Exit Gateway | nym-node --mode exit-gateway |
Last Sphinx hop for clearnet traffic. Runs the Network Requester (SOCKS4/4a/5) and IP Packet Router (raw IP). |
| Service Provider | your app + embedded client | A fourth participant, not infrastructure. Reachable only by Nym address; replies via SURBs. |
| Nyx blockchain / nym-api | separate | On-chain topology registry + signed epoch topology the client fetches. |
Critical production rule. Do not write your own Sphinx or curve code for real users. Use Nym's own software:
- Browser:
@nymproject/mix-tunnel,@nymproject/mix-fetch,@nymproject/mix-dns,@nymproject/mix-websocket.- Rust services/apps:
nym-sdk,nym-sphinx,sphinx-packet.- Local daemon / non-browser apps:
nym-client,nym-socks5-client.This repo's
crates/sphinx-coreis a reference implementation for education, audit and test vectors. It is not a substitute for audited code.
flowchart LR
subgraph Browser["Browser (Chrome / Firefox)"]
UI["React UI<br/>(status · path · latency)"]
SW["MV3 extension<br/>background service worker"]
WT["Web Worker<br/>mix-tunnel / smolmix-wasm"]
UI --> SW --> WT
end
WT -- "WSS (TLS)" --> EG["Entry Gateway"]
EG --> M1["Mix L1"]
M1 --> M2["Mix L2"]
M2 --> M3["Mix L3"]
M3 -->|"pure mixnet"| SPGW["Recipient Gateway"]
SPGW --> SP["Service Provider<br/>app + nym client"]
M3 -->|"clearnet"| XG["Exit Gateway"]
XG --> NR["Network Requester (SOCKS)"]
XG --> IPR["IP Packet Router"]
NR --> NET["Clearnet destination"]
IPR --> NET
┌─► mix L1 ─┐ mix L2 mix L3
client ──WSS──► Entry ───┤ ├──► ... ────┴─► destination
Gateway └─► mix L1 ─┘ │
├─ pure mixnet: recipient's Gateway → Service
└─ clearnet: Exit Gateway → NR / IPR → site
The Sphinx header supports MAX_PATH_LENGTH = 5, which is exactly:
[ Entry Gateway ] → [ Mix L1 ] → [ Mix L2 ] → [ Mix L3 ] → [ Destination Gateway ]
1 2 3 4 5
- Pure mixnet — hop 5 is the recipient's Gateway; the Sphinx destination address inside the final layer selects the client/service identity.
- Clearnet — hop 5 is an Exit Gateway running the Network Requester or IPR, which makes the clearnet connection. The destination sees the Exit Gateway's IP, never the client's.
The three mix layers are the anonymity core; the entry/exit gateways are the transport and policy boundaries.
| Pure mixnet (end-to-end) | Clearnet (proxy mode) | |
|---|---|---|
| Final hop | Recipient's Gateway | Exit Gateway |
| Destination | Nym address (id.enc@gw) |
host:port on the public internet |
| Content encryption | Sphinx-only; add app-layer crypto for confidentiality | TLS runs end-to-end to the site (mixnet only tunnels it) |
| Who sees the destination | Recipient | Exit Gateway sees destination, not sender |
| Exit policy | None | Exit Gateway's policy (ports/hosts allow-list) |
| Use for | Private services, messaging, RPC, wallets | Browsing, fetching public APIs |
sequenceDiagram
autonumber
participant C as Client (browser)
participant EG as Entry Gateway
participant M as Mix L1..L3
participant X as Exit Gateway (NR/IPR)
participant D as Clearnet site
C->>EG: WSS: 2413-byte Sphinx packet
EG->>M: decrypt layer 1, delay, forward
M->>X: decrypt layers 2-4, delayed/reordered
X->>X: decrypt final layer (SOCKS/IPR request)
X->>D: ordinary TLS/TCP from gateway IP
D-->>X: response
X-->>C: response wrapped in SURB reply packet(s)
For conversation-style clearnet traffic (HTTP over TCP), the browser stack builds SOCKS5-shaped requests and a userspace TCP/IP stack (
smoltcp) runs inside WASM; TLS (rustls) terminates at the destination. See §1.5.
nysiris/
├── Cargo.toml workspace
├── crates/
│ └── sphinx-core/ reference Sphinx (builds, tested, not for prod)
├── docs/
│ ├── 01-architecture.md ← this file
│ ├── 02-addressing-and-routing.md
│ └── 06-roadmap.md
├── web/ (planned) React UI
├── extension/ (planned) MV3 browser extension
├── services/ (planned) service-provider examples + Docker
└── workers/ (planned) mix-tunnel wrapper TypeScript
crates/sphinx-core mirrors sphinx-packet v0.6.x exactly where it matters:
| Concern | Implementation | Test |
|---|---|---|
alpha blinding chain |
X25519 via x25519-dalek
|
3-hop route test |
beta routing onion |
AES-128-CTR + Sphinx filler | 3-hop route test |
gamma |
HMAC-SHA256 truncated to 16 B | tamper test |
delta |
Lioness (BLAKE2b + ChaCha) | plaintext recovery test |
| SURB | header + per-hop payload keys | SURB reply test |
| Address |
<id>.<enc>@<gw> base58 |
round-trip test |
Run it: cargo test -p sphinx-core
A browser cannot open raw sockets or a SOCKS listener, so the production Nym design is:
Main thread (React app)
mix-fetch / mix-dns / mix-websocket (thin facades)
│ Comlink RPC over postMessage
▼
Web Worker (one per page)
smolmix-wasm
├─ IPR client → WSS to Entry Gateway
├─ smoltcp → userspace TCP/IP (no raw sockets in browsers)
└─ rustls → TLS terminated inside the WASM (Mozilla CA bundle baked in)
▼
Nym mixnet: entry → 3 mix layers → exit (IPR/NR) → internet
Consequences you must design around:
-
One tunnel per page.
setupMixTunnelis one-shot; afterdisconnectMixTunnelthe page must reload. Memoise a single promise. -
Worker + CSP. You need
worker-src 'self' blob:; the worker is started from an object URL.connect-srcmust includewss:and the bootstrap hosthttps://validator.nymtech.net(plain HTTPS, before any mixnet exists). - Bundle size. The WASM worker chunk is several MB; lazy-load it.
-
Not everything can be routed. Cross-origin iframes, vendor SDKs,
sendBeacon,EventSource,<img>/<script>prefetches and third-partyWebSockets bypass your code. Drop those integrations or proxy them. -
Leak guard. Wrap
fetchandXHR.opento detect direct requests to routed hosts, and fail closed in development.
Optional escape hatch for desktop/other apps: run a local nym-socks5-client
and point the browser/OS at 127.0.0.1:1080. Same mixnet, no WASM limits.
flowchart TB
subgraph Trusted["Client-controlled"]
C["Client keys<br/>chosen path<br/>SURB pool"]
end
subgraph Semi["Partially trusted"]
EG["Entry Gateway<br/>sees client IP + timing"]
XG["Exit Gateway<br/>sees destination + plaintext for non-TLS"]
end
subgraph Untrusted["Untrusted / adversarial"]
MIX["Mix nodes"]
NET["Network observer"]
end
C --> EG --> MIX --> XG --> NET
- Entry Gateway knows the client's IP but not the destination. That is the one node that can link you to the fact you are using Nym.
- Exit Gateway knows the destination but not the sender. Clearnet traffic is only as private as its own encryption past the exit.
- Mix nodes are assumed adversarial; layered encryption + independent delays are what break correlation.
- Client is the only party that knows the full route.
See 06-roadmap.md for acceptance criteria. Summary:
- Foundations — architecture + addressing/routing + reference Sphinx core ✅
-
Browser client —
mix-tunnelwrapper, React UI, MV3 extension, leak guard - Service hosting — pure-mixnet provider, hybrid nginx/Caddy, self-hosted gateway
- Hardening — security analysis, cover traffic tuning, observability
Next: 02-addressing-and-routing.md for
how "DNS" is replaced by cryptographic identities and a signed topology.
⚠️ Experimental / pre-audit. This repository is under active development and has not had an independent security audit. The Sphinx core incrates/is a reference implementation, never production crypto. Do not rely on it for high-stakes anonymity yet — see the threat model. Apache-2.0 © 2026 odelyzid (tribewarez). Report a security issue.
Nysiris docs
- Home
- 1. High-Level Architecture
- 2. Addressing & Routing Deep-Dive: how "DNS" works in Sphinx/Nym
- 3. Browser & Mobile Client (Web, Android, Desktop)
- 4. Hosting a Web Server / Service Reachable via the Nym Mixnet
- 5. Security Analysis & Recommendations
- 6. Implementation Roadmap
- 7. Desktop on Linux Mint / Debian
- 8. Hidden-Service Abstraction
- 9. nysiris-social: Metadata-Minimal Microblog + Encrypted DMs
- 10. Portal Layers: Data, Replication, Discovery, Reputation
- 11. UX Redesign — Calm, Private-by-Default Client
- 12. Windows build (MSYS2 / MSVC)
- 13. Hosting SDK &
nysirisCLI