Resolve open questions: - OQ-01: Restrict cipher suites to match nginx scope (4 ECDHE-AES-GCM suites for TLS 1.2 + all TLS 1.3 suites) — ADR-012 - OQ-03: Health check on separate local port (default 9900, localhost only) — ADR-013 - OQ-04: Add Unix domain socket admin API for config reload alongside SIGHUP, with structured success/failure responses — ADR-014 - OQ-06: Per-site upstream timeouts with defaults (5s connect, 60s request), overridable in SiteConfig — ADR-015 Document previously undocumented decisions flagged by architecture review: - ADR-016: Explicit bind address requirement (reject 0.0.0.0) - ADR-017: Upstream connection defaults (HTTP/1.1, no redirects, pooling) - ADR-018: 100 MB body size limit (matches nginx, Gitea compatibility) OQ-07 (per-site TLS overrides) remains open for future consideration. Spec updates: - config.md: add health_check_port, admin_socket_path, per-site timeout fields, update TOML example and validation rules - proxy.md: reference ADR-015/017/018 for timeouts, connection defaults, and body limit decisions - tls.md: replace OQ-01 cipher suite section with ADR-012 decision - operations.md: add local health check port section, admin socket reload - overview.md: update Phase 1 scope with new features, add ADR references - open-questions.md: resolve OQ-01/03/04/06, keep OQ-07 open
2.9 KiB
ADR-012: Restrict Cipher Suites to Match nginx Scope
Status
Accepted
Context
Our current nginx configuration explicitly restricts cipher suites to four ECDHE-AES-GCM suites:
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384
rustls 0.23 with the aws_lc_rs crypto provider defaults to a conservative
set that excludes all weak ciphers (no SHA-1, no 3DES, no RC4, no CBC-mode
suites, no RSA key exchange). The rustls defaults include these four suites
plus TLS 1.3 suites (which nginx also allows via TLSv1.3).
The question was whether to accept the wider rustls defaults or restrict to the same scope as our current nginx configuration (see OQ-01).
Decision
Explicitly restrict cipher suites to match the same scope as our current nginx configuration: the four ECDHE-AES-GCM suites for TLS 1.2, plus all TLS 1.3 suites. This is slightly more restrictive than rustls defaults but preserves compatibility with all modern clients.
The restricted set in rustls terms:
TLS 1.2 (explicitly selected):
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS 1.3 (all default suites):
TLS_AES_128_GCM_SHA256TLS_AES_256_GCM_SHA384TLS_CHACHA20_POLY1305_SHA256
This is configured by building a CryptoProvider with a custom
cipher_suite list and passing it to ServerConfig::builder_with_provider().
Rationale
- Maintains behavioral parity with our current nginx configuration during migration — no client that worked with nginx should see different TLS behavior
- The four TLS 1.2 suites are the same ones nginx allows, providing a known security baseline
- TLS 1.3 suites are all modern and secure — restricting them provides no meaningful security benefit and reduces compatibility
- rustls defaults include ChaCha20-Poly1305 suites for TLS 1.2 which nginx does not; these are cryptographically sound but represent a wider scope than our current nginx config allows
- Explicit configuration means the cipher list is documented and auditable
- If compatibility issues arise, expanding the list is straightforward; the reverse (restricting after deployment) risks breaking existing clients
Consequences
Positive:
- Behavioral parity with current nginx TLS configuration
- Explicitly auditable cipher list
- No client that currently works will see different TLS behavior
- Matches security review expectations
Negative:
- Slightly more restrictive than rustls defaults — excludes ChaCha20-Poly1305 for TLS 1.2 and AES-CCM suites (rarely used)
- Must update the cipher list when deprecating TLS 1.2 in the future
- Custom
CryptoProviderconstruction is slightly more code than using defaults
References
- tls.md
- OQ-01 (now resolved)