Skip to content

Encryption

Tunnel Whisperer applies three nested encryption layers to every byte of application data. Each layer serves a distinct purpose and operates independently of the others.


Transport Encryption (TLS 1.3)

The outermost encryption layer is TLS 1.3 — the same standard used by online banking, healthcare portals, and every major website.

  • Caddy handles TLS termination on the relay VM
  • The relay's server certificate is automatically provisioned and renewed via Let's Encrypt using the ACME protocol
  • The handshake is mutual (mTLS): Caddy is configured with client_auth verify_if_given — a presented certificate must be signed by an enrolled server's CA or the handshake is rejected, but a bare handshake with no certificate is allowed (so certless invitees can reach /enroll); every tunnel route still requires a verified, matching certificate CN, so a connection without one never reaches a server's upstream
  • All traffic is served over standard HTTPS on port 443
  • To firewalls, proxies, and Deep Packet Inspection (DPI) systems, Tunnel Whisperer traffic is indistinguishable from normal web browsing

Why TLS 1.3?

TLS 1.3 removes legacy cipher suites, reduces handshake round-trips, and provides forward secrecy by default. It is the minimum acceptable standard for modern encrypted communications. The relay pins TLS 1.3 only (protocols tls1.3).

Mutual authentication

The client certificate is the relay's admission control — see Relay Authentication for the per-server CA, certificate distribution, and the Caddy client_auth gate.


Tunnel Protocol (VLESS + XHTTP)

Inside the TLS envelope, Xray runs the VLESS protocol with XHTTP transport.

  • VLESS is a lightweight proxy protocol that authenticates each user with a unique UUID token. There are no shared credentials — each user has an individually issued UUID registered on the relay under the server's own tenant inbound.
  • XHTTP carries the tunnel entirely within HTTP semantics (proxied by Caddy as HTTP/2 h2c streams on a per-server path like /tw/<server-id>), making the traffic pattern resilient in environments where long-lived raw connections are interrupted or throttled.
  • The relay cannot read application data. It receives opaque encrypted streams and forwards them to their destination. The VLESS layer handles routing; decryption happens only at the endpoints. The relay's Xray routing additionally permits only loopback connections to SSH and the tenant's own allocated port — all other destinations are blackholed.

UUID is not a secret key

The Xray UUID functions as a transport-layer identifier, not a cryptographic secret. It provides per-user routing and revocation at the relay level. Actual data confidentiality is provided by the SSH layer below.


SSH Encryption (Ed25519)

The innermost layer is a full SSH session providing end-to-end encryption between client and server.

  • All connections use Ed25519 public key authentication — a 256-bit elliptic curve algorithm
  • No passwords are used. There is no brute-force attack surface
  • Each user gets an individual Ed25519 key pair, generated on the client machine during tw server user invite enrollment — the private half never touches the server at all
  • The SSH session encrypts all forwarded port traffic, ensuring that neither the relay nor any intermediate network can read application data
# Example: an enrolled user "alice" (private key born on her own machine)
/etc/tw/config/users/alice/id_ed25519.pub   # public key only — added to the server's authorized_keys
/etc/tw/config/users/bob/id_ed25519.pub     # public key — added to the server's authorized_keys

Why Ed25519?

Ed25519 provides strong security with short keys (256-bit vs 3072-bit RSA for equivalent strength), fast signature verification, and resistance to timing side-channel attacks. It is the recommended key type for modern SSH deployments.


End-to-End Data Path

The following diagram shows the encryption layers applied to application data as it traverses from a client application to a server service:

Client app                                                          Server service
    │                                                                     ▲
    ▼                                                                     │
┌──────────────┐                                                  ┌──────────────┐
│ SSH encrypt  │                                                  │ SSH decrypt  │
│ (Ed25519)    │                                                  │ (Ed25519)    │
└──────┬───────┘                                                  └──────▲───────┘
       ▼                                                                 │
┌──────────────┐                                                  ┌──────────────┐
│ Xray VLESS   │                                                  │ Xray VLESS   │
│ encode       │                                                  │ decode       │
└──────┬───────┘                                                  └──────▲───────┘
       ▼                                                                 │
┌──────────────┐         ┌──────────────┐         ┌──────────────┐┌──────────────┐
│ TLS encrypt  │────────▶│    Caddy     │────────▶│    Xray      ││ TLS encrypt  │
│ (port 443)   │  HTTPS  │ mTLS gate +  │   h2c   │ per-tenant   ││ (port 443)   │
│              │         │ TLS terminate│         │ inbound      ││              │
└──────────────┘         └──────────────┘         └──────────────┘└──────────────┘
    Client                     Relay                    Relay            Server

Simplified linear path:

Client app → SSH encryption → Xray VLESS → TLS → Caddy → Xray → SSH → Server service

At every point in the relay, application data remains encrypted by the SSH layer. The relay handles only the outer TLS and VLESS layers — it never has access to the plaintext content of the SSH session.


Network Hardening

Beyond the encryption layers, the relay VM itself is hardened:

  • The relay firewall (UFW) allows only ports 80 and 443 by default. Port 22 is opened only when the relay is deliberately provisioned with --ssh-open
  • Caddy verifies any presented client certificate (client_auth verify_if_given) and requires a matching, verified certificate CN on every tunnel route, so untrusted callers never reach a tenant's upstream — a bare handshake only ever gets as far as the enrollment endpoint or a 404
  • Without --ssh-open, SSH on the relay listens on 127.0.0.1 only — accessible exclusively through the encrypted tunnel; tw's own management key is additionally pinned from="127.0.0.1" so it can never authenticate from the internet
  • Enrolled servers' relay SSH access is forwarding-only (restrict, no shell), scoped to their own allocated port — see Access Control
  • All management operations (user provisioning, relay configuration) happen through the encrypted tunnel, never over unprotected channels
  • Password authentication is disabled on the relay SSH daemon