Solution Strategy¶
Protocol Stack¶
The system layers multiple protocols to achieve secure, firewall-transparent tunneling:
graph TB
subgraph "Protocol Stack (outside → inside)"
TLS["TLS 1.3 + mutual auth<br/><small>Caddy terminates on relay :443; client_auth verify_if_given</small>"]
HTTP["XHTTP Transport<br/><small>Traffic split into standard HTTP requests</small>"]
VLESS["VLESS Protocol<br/><small>UUID-authenticated proxy layer</small>"]
SSH["SSH Session<br/><small>End-to-end encrypted, key-based auth</small>"]
FWD["Port Forwarding<br/><small>direct-tcpip channels with permitopen</small>"]
APP["Application Data<br/><small>PostgreSQL, HTTP, etc.</small>"]
end
TLS --> HTTP --> VLESS --> SSH --> FWD --> APP
style TLS fill:#1565C0,color:#fff
style HTTP fill:#1976D2,color:#fff
style VLESS fill:#1E88E5,color:#fff
style SSH fill:#00897B,color:#fff
style FWD fill:#00ACC1,color:#fff
style APP fill:#26A69A,color:#fff Technology Integration¶
graph LR
subgraph "Infrastructure"
TF[Terraform]
CI[cloud-init]
CLOUD[Cloud Provider<br/>Hetzner / DO / AWS]
end
subgraph "Relay VM"
CADDY[Caddy<br/>mTLS + per-tenant handles]
XRAY_R[Xray<br/>per-tenant VLESS inbounds]
OSSH[OpenSSH<br/>127.0.0.1 only]
end
subgraph "Go Binary (tw)"
XRAY[Xray Core<br/>in-process]
SSHD[SSH Server<br/>x/crypto/ssh]
GRPC[gRPC API]
DASH[Dashboard<br/>SSE + WebSocket]
COBRA[Cobra CLI]
end
TF --> CLOUD
CI --> CLOUD
CLOUD --> CADDY
CADDY --> XRAY_R
XRAY_R --> OSSH
XRAY --> CADDY
SSHD --> XRAY
GRPC --> SSHD
DASH --> GRPC
COBRA --> GRPC
style TF fill:#7E57C2,color:#fff
style CI fill:#7E57C2,color:#fff
style CLOUD fill:#5C6BC0,color:#fff
style CADDY fill:#1565C0,color:#fff
style XRAY_R fill:#1565C0,color:#fff
style OSSH fill:#1565C0,color:#fff
style XRAY fill:#00897B,color:#fff
style SSHD fill:#00897B,color:#fff
style GRPC fill:#00897B,color:#fff
style DASH fill:#00897B,color:#fff
style COBRA fill:#00897B,color:#fff Challenge-Solution Map¶
| Challenge | Solution | Technology |
|---|---|---|
| Firewalls block non-HTTPS traffic | Encapsulate all traffic in TLS on port 443 | Xray (VLESS + XHTTP) |
| Server and client are behind NAT | All connections are outbound-only; relay is the rendezvous point | SSH reverse port forwarding |
| Relay must never see plaintext | End-to-end encryption between client and server | SSH session layer |
| Relay must admit only trusted servers | Mutual-TLS gate verifying an X.509 client cert against a per-tenant CA trust pool (verified if presented; every tunnel route requires a verified, matching CN) | Caddy client_auth verify_if_given + internal/pki |
| Enrollees have no client cert yet | A bare TLS handshake is allowed and routed to a per-tenant /enroll/<tok> endpoint; the SPAKE2 code + SAS read-back is the real gate there, not TLS | internal/enroll + Caddy verify_if_given |
| TLS certificates for the relay | Automatic issuance and renewal | Caddy (ACME / Let's Encrypt) |
| Per-server relay admission | One CA-issued client cert per server (CN = server-id), presented by Xray (usage: "client-cert"); Caddy routes only when path and cert CN match | xray-core mTLS + internal/pki |
| Multiple servers on one relay | Per-tenant VLESS inbound on 127.0.0.1:<remote-port>+10000, per-tenant Caddy handle, per-tenant allow/deny routing rules | internal/relay/{caddy,xray} |
| Relay must not become an open proxy | Freedom outbound carries finalRules allowing loopback only; each tenant's allow rule permits exactly ports 22 + its own remote port, then a blackhole deny | Xray routing + freedom finalRules |
| Adding a server must not disrupt others | Enrollment live-adds the tenant's inbound + rules over the Xray gRPC API (:10085, loopback, reached over the admin's SSH tunnel) — no Xray restart | AddInbound / AddRule via internal/ops/enroll.go |
| Hand-edited role field | Config mode is ed25519-signed against the profile's own identity (tamper-evidence, not a security wall) | internal/ops/modeauth |
| Multiple relays / identities per machine | kubectl-style contexts: sealed profile bundles switched with tw config use-context | internal/ops/context.go + internal/cryptobox |
| Per-user access control | Identity and authorization live entirely on the on-prem server — no external control plane; each user key grants specific host:port targets only, never network/overlay reachability | SSH authorized_keys + permitopen (+ optional single-session) |
| Infrastructure provisioning | Interactive wizard generates Terraform + cloud-init, or an install script for a bring-your-own VM | Terraform (Hetzner, DigitalOcean, AWS) / manual install script |
| Cross-platform operation | Single binary for all three roles | Go (Linux + Windows + macOS) |
| Dynamic user management | Re-read authorized_keys on every auth attempt | No server restart needed |
| Config change detection | SHA-256 hash comparison of config file | crypto/sha256 |
| Real-time dashboard | SSE for progress + log streaming, WebSocket for SSH terminal | Go net/http, gorilla/websocket, xterm.js |
| Runtime log level | Dynamic slog.LevelVar propagates through handler chain | log/slog |