Whitepaper v0.2
VPN9 is a consumer‑focused, zero‑logs VPN with a fully open‑source stack. It is engineered for verifiable privacy, reproducible builds, and predictable performance under real‑world constraints. The system is composed of three public repositories:
vpn9-portal— Ruby on Rails application for account lifecycle, privacy‑preserving payments, and public API.vpn9-service— Rust control plane and node/relay agents providing provisioning, key issuance, policy enforcement, and health orchestration.vpn9-app— Tauri‑based client for desktop and mobile implementing transport, kill‑switch, split tunneling, and local trust controls.
This document specifies the threat model, the cryptographic and network architecture, operational controls behind the zero‑logs claim, supply‑chain guarantees, interfaces between components, and the roadmap for post‑quantum agility and censorship resilience.
v0.2 additions: Two account types—Anonymous (no email, 7‑word token phrase, one‑time recovery code, account‑layer anonymity) and Email (recovery via email; email encrypted at rest; “we never share or sell your data”). Bitcoin (BTC) and Monero (XMR) payments are supported at launch.
- Minimal data, maximally provable. Collect nothing by default. Where telemetry is necessary, hold it in aggregate, in memory, and only long enough to manage capacity.
- Open by construction. All code, build pipelines, IaC manifests, and security policies are public. No hidden components.
- Reproducibility over trust. Users must be able to reproduce clients and verify binaries against source with deterministic outputs.
- Separation of concerns. The portal never sees traffic metadata. The control plane never stores user PII. Exit nodes never learn account identity.
- Fail‑closed safety. Any policy breach (interface down, daemon crash, handshake failure) forces a kill‑switch state.
- Threat‑model clarity. VPN9 is a privacy tool for network confidentiality and location obfuscation. It is not an anonymity network against a truly global passive adversary.
- Account choice. Anonymous account or Email account; both map to the same blind‑token service model; identity never reaches the data plane.
- Local and access‑network attackers. Malicious Wi‑Fi, ISP observers, captive portals, and LAN peers performing sniffing, spoofing, or MITM.
- On‑path regional observers. IXPs, transit providers, and regional surveillance systems performing traffic correlation within limited scope.
- Content‑side trackers. DNS collectors, CDN edge correlation, and third‑party beacons measuring IP reputation and geolocation.
- Malicious or compromised exit node. Attempting packet inspection, DNS hijack, or metadata extraction.
- Platform‑level interference. OS APIs leaking traffic outside the tunnel; update supply‑chain tampering.
- Targeted disruption. UDP blocking, DPI against VPN handshakes, throttling, or connection resets.
- Global passive adversary capable of full‑internet timing correlation.
- Compromised endpoints. Devices with resident malware or kernel‑level rootkits.
- Application‑layer identity. Logged‑in service accounts and browser fingerprints.
+-----------------+ +----------------------+ +--------------------+
| vpn9-app | TLS1.3 | vpn9-portal | gRPC | vpn9-service |
| (Desktop/Mobile)|<-------->| (Rails, public API) |<--------->| (Rust control plane)|
+--------+--------+ +----------+-----------+ +-----+--------------+
| | |
| WireGuard w/ obfuscation | |
v v v
+-----+-------------------+ +------+----------------+ +------+----------------+
| Entry Relay (Agent) |<--->| Regional Coordinator |<--->| Exit Node (Agent) |
| (vpn9-service/agent) | | (vpn9-service) | | (vpn9-service/agent) |
+-------------------------+ +-----------------------+ +----------------------+
Planes
-
Control Plane (
vpn9-service) Rust microservices and agents:- Coordinator: device provisioning, policy distribution, path selection.
- CA/KMS: short‑lived device certificates, node identity keys, HSM‑backed roots.
- Directory: public list of regions, capabilities, and transparency attestations.
- Agent: runs on relays/exits; receives signed policies; enforces datapath with nftables/eBPF; exposes minimal health endpoints.
-
Data Plane (Agents on Nodes) WireGuard‑based tunnels with optional obfuscation layers. Entry and exit can be the same node (single‑hop) or different nodes (multi‑hop).
-
User Plane (
vpn9-app) Tauri shell with a Rust core. Integrates OS‑native VPN stacks (Wintun on Windows; NetworkExtension on macOS/iOS; VpnService/wireguard‑go on Android; kernel WireGuard on Linux when available). Implements kill‑switch, per‑app routing, and DNS policy. -
Business Plane (
vpn9-portal) Runs account lifecycle, subscription credits, privacy‑preserving payment tokens, device limits, and support workflows. Publicly documented REST/GraphQL API.
-
Primary: WireGuard (NoiseIK) with Curve25519, ChaCha20‑Poly1305, BLAKE2s, and HKDF‑based key derivation.
-
Portability: UDP default; UDP keepalives; NAT‑friendly timers.
-
Fallback/Obfuscation:
- WG‑over‑QUIC encapsulation to TCP/443 look‑alike where UDP is blocked.
- Pluggable fronting providers via a simple trait in
vpn9-serviceto add uTLS/TLS1.3 camouflage without changing client UX.
- TLS 1.3 everywhere. Ciphersuites: X25519 or P‑256 key exchange; AES‑GCM or ChaCha20‑Poly1305.
- mTLS for nodes. Node agents present short‑lived X.509 issued by VPN9 CA; clients pin CA via
vpn9-apptrust store.
- Device keys: Curve25519 static public key per device; stored only client‑side; registered to control plane via one‑time enrollment.
- Session keys: Ephemeral; rekeyed per WireGuard standard.
- Node identity: Long‑term Ed25519/25519 key pairs anchored in HSM; published in transparency ledger.
- Payment tokens: Chaumian blind signatures for unlinkable credit redemption (see §9).
Definition. “Zero logs” means: no retention of source IPs, connection timestamps, DNS queries, bandwidth usage per user, or application identifiers across any persistent medium. The system is engineered so these data are neither produced nor storable under default operation.
Controls
- Disk discipline: Exit/relay nodes boot read‑only; journald set to
volatile; swap disabled;/var/logon tmpfs with periodic shred at process exit. - Flow tables: NAT and conntrack counters exposed only as integers aggregated per node; never tagged with user or device identifiers.
- In‑memory health telemetry: Node health (CPU, mem, packet drops, per‑region capacity) streamed via QUIC to control plane with lossy sampling; window ≤ 60 seconds; no IPs; no ports.
- DNS privacy: On‑node Unbound/Bind in forwarding mode to VPN9 resolvers over DoT/DoH with ECS disabled. Optional blocklists run on exit; queries are never logged.
- Access controls: Operators cannot enable per‑user logging without forking public code and leaving evidence in attestations.
- Legal posture: No dynamic capability for “turning on logs”; no partially retained debug traces. Support diagnostics are generated client‑side with user opt‑in and scrubbed of IPs by design.
-
Core: Rust crate owning networking, platform FFI, policy parser, and attestation verifier.
-
Shell: Tauri webview for UI; all privileged operations occur in Rust, not JS.
-
OS integrations:
- Windows: Wintun; kill‑switch via Windows Filtering Platform; firewall rules locked to WG interface.
- macOS/iOS: NetworkExtension Packet Tunnel; kill‑switch via
NEOnDemandRuleDisconnect+ scoped routes. - Linux: Kernel WireGuard if present, otherwise wireguard‑go; kill‑switch via nftables sets bound to interface and peer pubkey.
- Android: VpnService + wireguard‑go; disallow “always‑on” bypass.
- Kill‑switch: Default on; traffic blocked when tunnel is down, DNS scoped to tunnel interface.
- Split tunneling: App‑based on Windows/macOS/Linux; domain‑based split via DoH policy; per‑route rules.
- Multi‑hop: Optional entry+exit selection with deterministic pathing; second hop never sees device account.
- IPv6 first: Full dual‑stack; NAT64/DNS64 support; ULA leak prevention.
- Leak protection: DNS leak tests, WebRTC local IP suppression toggle, local proxy exceptions disabled by default.
- Autoupdate: Code‑signed delta updates; user‑verifiable detached signatures.
- Off by default. Opt‑in sends crash minidumps with symbolicated stack traces without network state.
- Enrollment: Validates one‑time device code from portal; pins device pubkey; returns bootstrap: region directory + CA pinset.
- Policy Engine: Calculates best entry/exit for user constraints (region, latency, streaming rules) and network health.
- Certificate Authority: Issues short‑lived (e.g., 24h) device certificates for API use. Keys anchored in HSM; rotation automated.
- Directory/Transparency: Publishes signed snapshot of node fleet, software versions, build hashes, and attestation reports.
- Datapath enforcement: nftables/eBPF programs to bind WireGuard peer pubkeys to allowed routes; DNS forced to internal resolver; egress NAT consistent.
- Process isolation: Agent is the only process with WG private key; unprivileged sidecars for health checks; seccomp and ambient caps minimized.
- Attestation: On startup, agent submits: kernel hash, container image digest, commit ID, and build attestation (cosign/Sigstore). Control plane refuses drift.
- What we see: packet/handshake failure rates, queue drops, per‑node capacity slice, region‑level latency histograms.
- What we never see: source/destination IPs, per‑device throughput, or connection times.
Two account types.
-
Anonymous Account
- Identity: No email. No personal information.
- Credential: A 7‑word token phrase generated client‑side from a CSPRNG and public wordlist. The phrase is the only sign‑in secret.
- Storage: Server stores only a slow‑KDF (e.g., Argon2id) hash of the phrase and an opaque account ID. The raw words are never stored.
- Recovery: A one‑time recovery code is issued at creation, shown once, and stored server‑side as a hash. Using it rotates the token phrase and emits a new one‑time code; the old code is destroyed.
- Properties: Account‑layer anonymity. No email. No linkage to payment events (see §9). If both phrase and recovery code are lost, the account is unrecoverable by design.
-
Email Account
- Identity: Email address only; no usernames.
- Recovery: Via signed email link. Optional 2FA (TOTP/WebAuthn) for additional protection.
- Storage: Email is encrypted at rest using per‑record envelope encryption with KMS/HSM‑protected keys. Backups are encrypted. Access is audited and least‑privileged.
- Policy: We never share or sell your data.
Devices: Soft‑limit per plan; device enrollment via short code; local device name exists only client‑side; server stores an opaque device ID.
- Credit model: Portal mints time credits as blind‑signed tokens. User redeems tokens in control plane to enable service periods.
- Unlinkability: The token verifier (control plane) cannot link tokens to purchase events. The issuer (portal) cannot see which device redeems them.
- Traditional payments: If the user pays by card/processor, the transaction resides with the processor; portal stores only the processor’s opaque subscription ID.
- Cryptocurrency (launch support): Bitcoin (BTC) and Monero (XMR) supported at launch. Fresh addresses/subaddresses per payment; no address reuse. Purchase events mint blind tokens; no wallet metadata is linked to accounts.
- Network separation: Payment processing is isolated from control plane. Only blind tokens cross the boundary.
-
Auth: Device‑scoped tokens bound to device certs. For Email accounts, session established via email login challenge. For Anonymous accounts, session established by proving knowledge of the token phrase (PAKE‑style flow or KDF‑bound proof).
-
Endpoints (illustrative):
-
POST /v1/device/enroll– exchange enrollment code for bootstrap. -
GET /v1/regions– signed directory snapshot with version/attestation hashes. -
POST /v1/token/redeem– present blind token; receive service window receipt (no account identifiers). -
Anonymous flows:
POST /v1/anon/register– create anonymous account; returns account ID, token phrase, and one‑time recovery code.POST /v1/anon/session– begin session by presenting proof of token phrase knowledge.POST /v1/anon/recover– rotate token phrase using the one‑time recovery code.
-
Email flows:
POST /v1/email/challenge– send signed login link.POST /v1/email/complete– finalize session from challenge.
-
Goal: Decouple payer identity from device service access.
Protocol Outline
- Client obtains a mint challenge from portal and blinds a random token
T. - Portal validates payment and signs blinded
T'with mint private key; returnsS(T'). - Client unblinds to obtain
S(T). - Client presents
T, S(T)to control plane. - Control plane verifies
S(T)against mint’s public key (published in transparency ledger), checks double‑spend set, grants service window, and stores onlyH(T)in a rolling Bloom filter.
Properties
- Issuer cannot link purchases to redemptions.
- Redeemer cannot trace tokens to accounts.
- Double‑spend prevention does not reveal redemption histories.
- BTC/XMR payments feed the same blind‑mint, preserving unlinkability.
-
Deterministic builds:
- Clients:
vpn9-appuses locked toolchains (rust-toolchain.toml), pinned NPM/Yarn/PNPM lockfiles, and deterministic Tauri bundles. - Services/Agents:
vpn9-servicecontainers built with pinned bases;Cargo.lockchecked in;--remap-path-prefixensures stable DWARF.
- Clients:
-
SBOMs: CycloneDX generated for every artifact; shipped alongside releases.
-
Signing: cosign/Sigstore with keyless (OIDC) and offline KMS‑backed keys; both published.
-
Attestations: SLSA provenance for each build; node agents verify image digests before join; coordinator rejects nodes without matching attestations.
-
User verification: CLI recipe to rebuild
vpn9-appand verify checksums locally. Binaries refuse to run if detached signature missing or CA pinset mismatched.
- Resolvers: In‑tunnel resolvers run with DNSSEC validation; ECS disabled.
- Filtering (opt‑in): Category blocklists applied on exit resolvers only; never at the portal or coordinator layers.
- Streaming and geo: Exit regions labelled with content compatibility hints; client pathing respects user‑selected region, never fakes geolocation beyond exit IP geography.
- Adaptive handshake: Try UDP WireGuard; fall back to QUIC‑wrapped tunnel on TCP/443; optional pluggable transports behind a single “Stealth” toggle.
- Traffic shaping: Padding and MTU tuning to blend with HTTP/3 profiles when in stealth.
- Decoy routing (future): MASQUE‑style gateway support planned as an opt‑in path where lawful.
- Latency overhead: Single‑hop within region expected to add single‑digit milliseconds; multi‑hop adds one additional regional RTT.
- Throughput: WireGuard saturates typical consumer links; QUIC‑wrapped mode trades ~5‑15% throughput for reachability.
- Resource: Client CPU remains bounded by crypto; mobile uses platform accelerators when available.
(Numbers are directional targets; exact results depend on access network, device class, and distance to exit.)
- Open development. All issues and PRs public by default; security reports via private channel with 90‑day coordinated disclosure.
- Third‑party audits. Annual audits of client, control plane, and agents; reports published.
- Bug bounty. Tiered rewards for RCE, privacy bypass, and key/identity issues.
- Continuous verification. Canary releases, staged rollouts, crash monitoring sans network data.
- Transparency reports. Semiannual report of legal requests, all denials due to absence of records, and any compliance actions.
- Warrant canary. Signed and updated on a fixed cadence.
- Jurisdiction strategy. Control plane and portal isolated from exit jurisdictions; exits placed with providers meeting minimum transparency and contract terms prohibiting logging requirements.
- Data stewardship: Email (if provided) is encrypted at rest; we do not share or sell data—by policy and by design.
- Post‑quantum agility. Hybrid KEM for control plane TLS (X25519 + Kyber class), client‑verifiable negotiation, and gradual WG‑handshake PQC research.
- MASQUE gateway. HTTP/3‑native tunnels for high‑censorship regions.
- Local DNS‑over‑Oblivious (ODoH/Oblivious DoH). Resolver privacy beyond in‑tunnel DoH.
- Shipped: Anonymous Account (token‑phrase + one‑time recovery). Future: hardware‑bound recovery as an opt‑in.
POST /v1/device/enroll
{ "enrollment_code": "ABCD-EFGH", "device_pubkey": "<base64>" }
200 OK
{
"bootstrap": {
"regions": [...],
"coordinator": "https://api.vpn9.net",
"ca_pinset": ["sha256/....", "sha256/..."],
"attestations": [{"node_id": "...", "image": "sha256:..."}]
},
"device_token": "<JWT short-lived>"
}
POST /v1/token/redeem
{ "token": "<T>", "signature": "<S(T)>" }
200 OK
{ "service_until": "2025-12-01T00:00:00Z", "receipt": "sig..." }
GET /v1/regions
200 OK
{
"version": 42,
"signed_at": "2025-08-01T00:00:00Z",
"signature": "sig...",
"regions": [
{
"id": "us-sea",
"capabilities": ["wg", "quic-wrap", "multihop-exit"],
"attestation": {"image": "sha256:...", "kernel": "sha256:..."}
}
]
}
POST /v1/anon/register
200 OK
{
"account_id": "acc_...",
"token_phrase": "word1-word2-word3-word4-word5-word6-word7",
"one_time_recovery_code": "RC-...."
}
POST /v1/anon/session
{ "proof": "<KDF/PAKE proof derived from token_phrase>" }
200 OK
{ "session": "<JWT device-scoped>" }
POST /v1/anon/recover
{ "recovery_code": "RC-...." }
200 OK
{
"rotated_token_phrase": "word1-...-word7",
"new_one_time_recovery_code": "RC-...."
}
POST /v1/email/challenge
{ "email": "user@example.com" }
200 OK
{ "challenge_id": "ch_..." }
POST /v1/email/complete
{ "challenge_id": "ch_...", "token": "<link token>" }
200 OK
{ "session": "<JWT device-scoped>" }
- Incident: exit compromise suspected. Immediately revoke node cert; remove from directory; publish revocation in transparency log; rotate fleet keys; publish post‑mortem.
- CVE in dependency. Automated advisories create PRs with pinned patches; rebuild; roll forward with canary wave; publish SBOM delta.
- Jurisdictional pressure to log. Exit is shut down; statement issued in transparency report; no logging capability exists in shipped agents.
- VPNs shift trust; they do not create anonymity against global observers.
- Application logins, browser fingerprinting, and side channels can still identify users.
- Some streaming or banking services may block known exit IPs; region rotation mitigates but cannot guarantee access.
- In stealth modes, throughput may be reduced to preserve reachability.
- Anonymous accounts provide account‑layer anonymity, not network‑layer anonymity. The threat‑model boundary remains as defined in §2.
- Domains: accounts (Anonymous + Email), mint (blind‑signing service), billing adapters, email auth, device enrollment codes, public API.
- Security: CSRF‑hardened sessions, strict CSP, readonly DB roles for API, background jobs with idempotent mints, rate‑limits on enroll/redeem.
- Data: minimal PII (email only, if provided), email encrypted at rest, processor IDs, mint public keys, transparency artifacts. No IP addresses retained.
- Crates:
coordinator,ca,directory,agent,health,quicwrap(optional),attest. - Runtime: async Rust (Tokio), gRPC/HTTP, QUIC for inter‑node signals.
- Agents: systemd units with read‑only root; nftables/eBPF integration; sealed secrets for node certs.
- Crates:
client-core,platform-ffi,wireguard-if,policy,updater,verifier. - UX: minimal surface, region selection, multihop toggle, split tunneling per app/domain, stealth toggle.
- Builds: reproducible; detached signatures; platform‑native signing (Notarization on macOS, Authenticode on Windows, APK/AAB signing on Android, TestFlight/AltStore pipelines for iOS).
- GDPR/CCPA: Data minimization by construction. Anonymous accounts: no PII to erase. Email accounts: right to erasure deletes encrypted email and billing linkage; redeemed service continues on blind tokens.
- PCI scope: Offloaded to payment processors; portal stores only opaque references.
- SLSA: Target level 3 for provenance; agents refuse non‑attested images.
- Build
vpn9-appfrom source; verify checksums of release binaries. - Inspect
vpn9-servicedirectory snapshot, attestation, and node image digests. - Confirm exit node logging paths are mounted
tmpfs; verifyjournaldvolatile mode. - Confirm DNS resolvers disable ECS; verify with integrated DNS test.
- Validate blind‑mint public key in portal versus service verifier key in directory.
- Run integration tests that enforce kill‑switch behavior by forcibly terminating the tunnel interface and observing blocked egress.
- For Anonymous accounts: verify that only KDF‑hardened hashes of token phrases and recovery codes exist in the database and that recovery rotates secrets.
- For Email accounts: verify per‑record encryption and key‑management policies; confirm no data sharing pathways exist.
VPN9 eliminates guesswork by making privacy verifiable. The architecture isolates concerns, minimizes data, and exposes the full system—including builds and policies—to public scrutiny. The product is consumer‑grade in usability and uncompromising in security posture. The roadmap keeps the stack agile against censorship and cryptographic shifts.
Linux (nftables)
table inet vpn9 {
set wg_peers { type ipv4_addr; flags interval; }
chain output {
type filter hook output priority 0;
ip daddr @wg_peers accept
ip daddr {10.64.0.0/10} accept
meta oifname "wg0" accept
ct state established,related accept
counter drop
}
}
Windows (WFP)
Block all outbound except to WireGuard peer and local loopback when wg0 down; rules bound to interface GUID.
- Anonymous account: opaque account ID; KDF‑hardened hash of token phrase; KDF‑hardened hash of one‑time recovery code; subscription state. Retention: while account active.
- Email account: email (encrypted at rest), subscription state, payment processor opaque ID. Retention: while subscription active + tax/legal minimum.
- Blind‑token spent set
H(T). Retention: rolling window ≤ service period + grace (e.g., 7 days). - Aggregate node health metrics (no IPs). Retention: sliding window ≤ 24h.
- Crash reports (opt‑in). Retention: 30 days; scrubbed.
We do not collect or retain: source IP, connection timestamps, DNS queries, ports, per‑device throughput.
git cloneall three repos at tagged release.- Install pinned toolchains via
rustupandasdf(Ruby/Node). make sbom && make build && make attest.- Verify cosign signatures and SLSA provenance.
- On Linux, confirm
sha256sumofvpn9-appmatches published detached signature.
- Attestation: Cryptographic evidence of how/where software was built.
- Blind signature: Signature on a hidden message enabling unlinkable redemption.
- ECS: EDNS Client Subnet.
- MASQUE: HTTP/3 mechanism for proxying UDP/QUIC.
- SLSA: Supply‑chain Levels for Software Artifacts.
- Token phrase: A 7‑word passphrase generated from a public wordlist via a CSPRNG; stored only as a slow‑KDF hash.
Status: Draft for public review. Contributions are expected. Audits are mandatory before “stable” designation of any major feature.