Resolve all architecture open questions, add 13 ADRs, update specs

Resolved all 11 open questions based on project guidance:

Transport:
- OQ-01/OQ-07: ACME/Let's Encrypt with domain + IP paths (ADR-008)
- OQ-02: Default to n0 relay, --iroh-relay override (ADR-009)
- OQ-05: Transport chaining supported natively (ADR-010)

Client:
- OQ-06: Programmatic-first API, no ~/.ssh/config (ADR-011)

Server:
- OQ-04: Ed25519 + OpenSSH cert-authority, no password auth (ADR-012)
- OQ-08: fail2ban-friendly logging + built-in rate limiting (ADR-013)

TUN:
- OQ-03/OQ-09: Deferred entirely, recommend tun2proxy (ADR-014)
- tun-shim.md marked deprecated

NAPI:
- OQ-10: Expose both connect() and serve() (ADR-016)
- OQ-11: Use napi-rs for FFI bridge (ADR-015)

Additional ADRs created during review:
- ADR-006: No logging of tunnel destinations (was phantom reference)
- ADR-017: Stealth mode protocol multiplexing
- ADR-018: Control channel for pubsub over SSH

Fixed: ADR-002 status → Superseded, ADR-007 title typo,
WRAUTH_SERVER typo, ADR-005 stale wraith-tun refs,
undefined ACL feature removed from server.md,
--proxy semantic difference documented.
This commit is contained in:
2026-06-01 17:31:28 +00:00
parent dad8224686
commit 13b0991fb8
23 changed files with 777 additions and 249 deletions

View File

@@ -1,111 +1,28 @@
---
status: draft
status: deprecated
last_updated: 2026-06-01
---
# TUN Shim
# TUN Shim (Deprecated)
## What
> **Note**: TUN functionality has been deferred from the wraith project. For VPN-like "route all traffic" behavior, use `tun2proxy` alongside wraith's SOCKS5 proxy. See ADR-014 for the rationale.
A separate process (`wraith-tun`) that creates a TUN interface, reads IP packets from it, and forwards them through the core wraith client's SOCKS5 port. Requires root or `CAP_NET_ADMIN`.
## What Changed
## Why
The core wraith binary must never require root. TUN interfaces need elevated privileges. By separating TUN into its own minimal process, we:
- Minimize the root-required code surface (auditable in an afternoon)
- Keep the core binary unprivileged for SOCKS5 and port forwarding
- Allow the TUN shim to crash without affecting the SSH session
- Match the proven tun2proxy architecture
(ADR-002)
## Architecture
```
┌─────────────────┐ ┌──────────────────────────────┐
│ wraith-tun │ │ wraith connect │
│ (root) │ │ (unprivileged) │
│ │ │ │
│ ┌────────────┐ │ │ ┌──────────────────────────┐ │
│ │ TUN Device │ │ │ │ SOCKS5 Server │ │
│ │ (tun-rs) │◄├─────┤├►│ :1080 │ │
│ │ 10.0.0.1/24│ │ │ └──────────────────────────┘ │
│ └────────────┘ │ │ │
│ │ │ ┌──────────────────────────┐ │
│ Route all │ │ │ SSH Client (russh) │ │
│ traffic via │ │ │ connect via Transport │ │
│ TUN device │ │ └──────────────────────────┘ │
└─────────────────┘ └──────────────────────────────┘
```
### Data Flow
1. OS routing table sends all traffic through TUN device `tun0`
2. `wraith-tun` reads IP packets from TUN device
3. `wraith-tun` extracts destination IP:port from each packet
4. `wraith-tun` connects to `127.0.0.1:1080` (wraith SOCKS5) with `SOCKS5h` (domain resolution by proxy)
5. `wraith-tun` proxies the TCP connection through SOCKS5
6. wraith's SOCKS5 server opens an SSH direct-tcpip channel to the destination
7. Bytes flow: application → TUN → SOCKS5 → SSH channel → server → target
### Virtual DNS
The TUN shim implements virtual DNS (same approach as tun2proxy):
- DNS queries to port 53 arriving at the TUN device are intercepted
- Query names are mapped to fake IPs from `198.18.0.0/15`
- Connections to fake IPs are resolved to the original domain name via SOCKS5h
- This prevents DNS leaks (all DNS resolution happens server-side)
### CLI Interface
The `wraith-tun` separate process and all TUN-related code is out of scope. The recommended approach for VPN-like behavior is:
```bash
# Basic TUN mode (uses wraith's SOCKS5 on 127.0.0.1:1080)
sudo wraith-tun --socks5 127.0.0.1:1080
# Terminal 1: wraith SOCKS5 proxy (no root required)
wraith connect --server example.com --identity ~/.ssh/id_ed25519
# With custom TUN address
sudo wraith-tun --socks5 127.0.0.1:1080 --tun-addr 10.0.0.1/24
# With DNS configuration
sudo wraith-tun --socks5 127.0.0.1:1080 --dns virtual
# Unprivileged mode (creates network namespace)
wraith-tun --socks5 127.0.0.1:1080 --unshare
# Terminal 2: tun2proxy routes all traffic through wraith's SOCKS5
sudo tun2proxy --proxy socks5://127.0.0.1:1080
```
### Unprivileged Mode
This keeps the core wraith binary free of TUN complexity and leverages an existing, well-tested tool for TUN-to-SOCKS5 bridging.
The `--unshare` flag creates a new network namespace, sets up the TUN device inside it, and maintains connectivity to the SOCKS5 proxy via the global namespace. This allows running without root, using only `CAP_NET_ADMIN` capability or namespace creation permissions.
## References
## Scope
This is Phase 3 of the implementation plan. The core (`wraith serve`, `wraith connect` with SOCKS5 and port forwarding) comes first. TUN is an add-on.
### What `wraith-tun` Does NOT Do
- It does not manage SSH sessions
- It does not know about transports
- It does not handle authentication
- It does not read SSH keys
It only: reads packets from TUN, forwards to SOCKS5. That's it.
## Constraints
- Requires root or `CAP_NET_ADMIN` (or `--unshare` namespace isolation)
- IPv4 only in initial release, IPv6 follow-up
- UDP over TCP (DNS queries are handled via SOCKS5h, other UDP is dropped in initial release)
- Approximately 200-500 lines of Rust for the initial implementation
## Open Questions
- **OQ-03**: Windows TUN support scope (wintun.dll dependency)
- **OQ-09**: Whether to use tun2proxy's `ip-stack` crate for TCP reconstruction or implement a simpler packet-level approach
## Design Decisions
| ADR | Decision | Summary |
|-----|----------|---------|
| [002](decisions/002-tun-separate-process.md) | TUN separate process | Core never needs root, TUN is thin wrapper |
| [005](decisions/005-socks5-before-tun.md) | SOCKS5 first | TUN forwards to SOCKS5, not to SSH directly |
- [ADR-014](decisions/014-defer-tun-recommend-socks5-proxy.md) — decision to defer TUN
- [ADR-005](decisions/005-socks5-before-tun.md) — SOCKS5 is still the primary interface
- [tun2proxy](https://github.com/tun2proxy/tun2proxy) — recommended external tool for TUN support