mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-08-09 09:51:49 +08:00
worker: use TLS 1.3 transparent rekey on TLS 1.3 CSTP sessions
TLS 1.3 has no renegotiation and provides transparent rekeys but this was not used by the server. Instead rekey-method=ssl was silently downgraded to new-tunnel, causing a full tunnel/TUN-device rebuild (and a brief data-path interruption) on every rekey whenever a client negotiated TLS 1.3. This commit simplifies that handling by taking advantage of TLS 1.3's own rekey mechanism instead: the server now performs the "ssl" rekey on TLS 1.3 sessions via the standard TLS 1.3 KeyUpdate message. TLS <= 1.2 rekey behavior (client-driven rehandshake, gated on RFC 5746 safe renegotiation) is unchanged. Resolves: #745 Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
This commit is contained in:
@@ -613,6 +613,43 @@ response advertises `X-CSTP-Rekey-Method: ssl` and
|
||||
`X-CSTP-Rekey-Time: <N-derived value>`; a rekey is triggered at approximately
|
||||
`rekey_time` (with jitter — `FUZZ(WSRCONFIG(ws)->rekey_time, 30, rnd)` at
|
||||
`src/worker-vpn.c:2111`).
|
||||
|
||||
*TLS ≤ 1.2*: rekey is an in-place rehandshake, gated on RFC 5746 safe
|
||||
renegotiation (`gnutls_safe_renegotiation_status()`,
|
||||
`src/worker-vpn.c:2415-2419`), falling back to `new-tunnel` only for peers
|
||||
that lack it.
|
||||
|
||||
*TLS 1.3+*: TLS 1.3 has no renegotiation, so the server performs the whole
|
||||
rekey itself, with no client involvement: it advertises
|
||||
`X-CSTP-Rekey-Method: none` (not `ssl`) and, from `periodic_check()` at
|
||||
approximately `rekey_time`, unilaterally issues a TLS 1.3 `KeyUpdate`
|
||||
(`gnutls_session_key_update(session, GNUTLS_KU_PEER)`, GnuTLS ≥ 3.6.3, in
|
||||
`cstp_transparent_rekey_update()`, gated by
|
||||
`cstp_transparent_rekey_capable()`). There is no tunnel/TUN-device rebuild
|
||||
and no client-visible interruption — any TLS 1.3 peer accepts an
|
||||
unsolicited KeyUpdate transparently at the record layer (RFC 8446 §4.6.3),
|
||||
regardless of the CSTP header value.
|
||||
|
||||
`none` is required rather than `ssl` on TLS 1.3 because both of
|
||||
OpenConnect's TLS backends mishandle a client-driven rehandshake on an
|
||||
already-established TLS 1.3 session (GnuTLS backend: session torn down with
|
||||
an "illegal parameter" alert; OpenSSL backend: forced `new-tunnel`
|
||||
reconnect) — the exact disruption this requirement exists to avoid. Full
|
||||
analysis in the comment above `cstp_transparent_rekey_capable()` in
|
||||
`src/worker-vpn.c`.
|
||||
|
||||
The rekey is atomic: `gnutls_session_key_update()` is retried on
|
||||
`GNUTLS_E_AGAIN`/`GNUTLS_E_INTERRUPTED` for up to 30 seconds; if it has not
|
||||
succeeded by then, or fails for any other reason, the worker ends the
|
||||
session (`exit_worker_reason(ws, REASON_ERROR)`) rather than leave a rekey
|
||||
partially pending.
|
||||
|
||||
Tested by `tests/test-rekey-tls13` (TLS 1.3: one tun-device assignment for
|
||||
the session, i.e. no rebuild; `TLS 1.3 session keys refreshed` logged;
|
||||
tunnel pings succeed before and after the rekey window) and
|
||||
`tests/test-rekey-tls12` (TLS 1.2 negative case: legacy rehandshake
|
||||
completes, no TLS 1.3 KeyUpdate logged). Both connect with `--no-dtls` so
|
||||
the assertions exercise CSTP/TLS, not DTLS.
|
||||
**Divergence**: both `ssl` and `new-tunnel` are implemented (not just
|
||||
advertised), so this is MAJORITY rather than EXTENSION; classified MAJORITY
|
||||
(not UNIVERSAL) only because the *value* `rekey-time` and the *jitter* (`FUZZ`,
|
||||
|
||||
+4
-1
@@ -490,7 +490,10 @@ rekey-time = 172800
|
||||
# ReKey method
|
||||
# Valid options: ssl, new-tunnel
|
||||
# ssl: Will perform an efficient rehandshake on the channel allowing
|
||||
# a seamless connection during rekey.
|
||||
# a seamless connection during rekey. On TLS 1.2 and earlier this is
|
||||
# an in-place rehandshake; on TLS 1.3 (which has no renegotiation)
|
||||
# it is performed transparently via a standard TLS 1.3 KeyUpdate,
|
||||
# with no tunnel rebuild or client-visible interruption either way.
|
||||
# new-tunnel: Will instruct the client to discard and re-establish the channel.
|
||||
# Use this option only if the connecting clients have issues with the ssl
|
||||
# option.
|
||||
|
||||
Reference in New Issue
Block a user