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
83 lines
2.9 KiB
Markdown
83 lines
2.9 KiB
Markdown
# 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_SHA256`
|
|
- `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`
|
|
- `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`
|
|
- `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`
|
|
|
|
**TLS 1.3 (all default suites):**
|
|
- `TLS_AES_128_GCM_SHA256`
|
|
- `TLS_AES_256_GCM_SHA384`
|
|
- `TLS_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 `CryptoProvider` construction is slightly more code than using defaults
|
|
|
|
## References
|
|
|
|
- [tls.md](../tls.md)
|
|
- OQ-01 (now resolved) |