# Security rustunnel's security posture is built on multiple layers: TLS transport, mutual authentication, application-level auth tokens, secret redaction, and fail-closed error handling. ## Security gates Before any traffic flows, four gates must pass: 1. **TLS handshake** — both sides negotiate a TLS 1.2+ connection via rustls with ring. 2. **Server certificate verification** — the connector verifies the listener's certificate against the shared CA. 3. **Client certificate verification** — the listener verifies the connector's certificate against the same CA (skipped in insecure mode). 4. **Application auth token** — the connector sends an `X-Rustunnel-Token` header; the listener validates it with constant-time comparison. The E2E test `auth_required_in_addition_to_mtls` verifies that valid mTLS alone is not sufficient; the correct auth token is also required. ## mTLS - The listener requires client certificates signed by the shared CA. It uses `WebPkiClientVerifier`. - The connector presents its client certificate and validates the server certificate against the CA. - Certificate identities are validated against SANs (Subject Alternative Names) and CN. The server certificate includes SANs for `localhost`, `rustunnel`, and `127.0.0.1`, plus the bind IP if applicable. ## Auth token - Generated as 32 random bytes encoded as 64 hex characters. - Compared with a constant-time XOR loop to prevent timing attacks. - Never logged in raw form. All log output uses the `Redacted` wrapper. - Auth failures are terminal: the connector's reconnect loop exits on auth failure rather than retrying. ## Secret redaction - `Redacted` in `src/redact.rs` wraps strings and displays `[REDACTED(len=N)]`. - `redact_pem()` shows only the PEM block type and line count. - `redact_config_json()` scrubs sensitive keys from JSON. - `is_sensitive()` detects PEM private key blocks. - `is_auth_token()` detects long alphanumeric strings. - `is_connection_key()` detects strings starting with `rtun1.`. The E2E test `ops_auth_failure_is_actionable_and_redacted` verifies that error messages do not contain raw token values. ## Insecure mode `--insecure-skip-tls-verify` disables certificate verification on either side. This is intended for DPI/intercepted environments only. When enabled: - The listener uses `with_no_client_auth()` instead of `WebPkiClientVerifier`. - The connector uses a custom `InsecureServerCertVerifier` that accepts any certificate. - A `warn` level log is emitted. ## Fail-closed design All error paths reject the connection rather than falling back to an insecure mode. There are no bypasses around TLS, certificate verification, or auth. ## Key source files | File | Purpose | | ---- | ------- | | `src/tls.rs` | TLS config, certificate loading, identity validation | | `src/tunnel.rs` | Auth handshake, constant-time comparison, security gate tests | | `src/redact.rs` | Secret redaction wrappers and helpers | | `src/errors.rs` | Error enums for TLS, auth, tunnel |