Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2.9 KiB
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:
- TLS handshake — both sides negotiate a TLS 1.2+ connection via rustls with ring.
- Server certificate verification — the connector verifies the listener's certificate against the shared CA.
- Client certificate verification — the listener verifies the connector's certificate against the same CA (skipped in insecure mode).
- Application auth token — the connector sends an
X-Rustunnel-Tokenheader; 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, and127.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
Redactedwrapper. - Auth failures are terminal: the connector's reconnect loop exits on auth failure rather than retrying.
Secret redaction
Redactedinsrc/redact.rswraps 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 withrtun1..
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 ofWebPkiClientVerifier. - The connector uses a custom
InsecureServerCertVerifierthat accepts any certificate. - A
warnlevel 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 |