rekey-method = ssl silently falls back to new-tunnel on TLS 1.3, causing a full tunnel rebuild on every rekey (undocumented)

Type: bug / documentation Component: worker (rekey advertisement), main (tunnel/lease handling), docs Affected versions: confirmed in 1.5.0 (master) and 1.4.2 — identical code. Present whenever TLS 1.3 is allowed on the CSTP channel (default, unless cisco-client-compat disables it). Not a security issue: no auth bypass, no information disclosure. Functional/stability + documentation gap.

Summary

rekey-method is documented as supporting an in-place, seamless ssl rehandshake. On the CSTP (control) channel this only works for TLS ≤ 1.2: TLS 1.3 has no renegotiation/rehandshake, so gnutls_safe_renegotiation_status() returns 0 and the worker silently overrides the configured ssl and advertises new-tunnel instead.

For clients that negotiate TLS 1.3, every rekey-time interval therefore triggers a full reconnect, not a rehandshake:

  1. the client tears down and re-establishes the TLS/DTLS channel;
  2. main spawns a new worker that resumes by cookie;
  3. the TUN interface is recreated under a new name (vpnsNvpsN+1);
  4. there is a brief data-path outage during the hand-over that breaks long-lived inner TCP flows (large downloads, RDP/SSH, etc.), even though the VPN itself stays "connected".

With a low rekey-time this repeats on every interval (e.g. rekey-time = 3600 → hourly tunnel rebuilds).

Evidence that TLS 1.3 hits the fallback

In issue #207 (closed) a reporter ran openssl s_client -tls1_3 against ocserv and the handshake reported:

New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
...
Secure Renegotiation IS NOT supported

"Secure Renegotiation IS NOT supported" is exactly the condition (gnutls_safe_renegotiation_status() == 0) that selects the new-tunnel branch below.

Code path (1.5.0 master)

  • Forced override — src/worker-vpn.c:2416-2420:

    if (ws->session != NULL &&
        gnutls_safe_renegotiation_status(ws->session) != 0)
            method = WSRCONFIG(ws)->rekey_method;   /* configured ssl */
    else
            method = REKEY_METHOD_NEW_TUNNEL;        /* TLS 1.3 lands here */
  • The in-place ssl rehandshake path that TLS 1.3 can never reach — src/worker-vpn.c:1699 (CSTP), src/worker-vpn.c:1544 (DTLS).

  • New TUN device (incrementing name) on each reconnect — src/tun.c:453, src/tun.c:499.

  • Old worker killed, leases moved to the new worker — src/main-auth.c:176 (steal_ip_leases).

Documentation gap

doc/sample.config:485-491 describes ssl as "an efficient rehandshake on the channel allowing a seamless connection during rekey" and says to use new-tunnel "only if the connecting clients have issues with the ssl option." There is no mention that:

  • on TLS 1.3 ssl is impossible and is silently replaced by new-tunnel;
  • with a small rekey-time, TLS 1.3 clients will see periodic tunnel rebuilds and inner-session breakage.

This is misleading for any modern deployment, where TLS 1.3 is the common case on the control channel.

What we ruled out

  • Not specific to one client: reproducible with any OpenConnect/AnyConnect client that negotiates TLS 1.3 on CSTP.
  • TLS 1.2 clients are not affected — they get the genuine in-place ssl rehandshake (same config, different negotiated version), which is why the issue is easy to miss.
  • Not caused by a small rekey-time alone — at the default rekey-time = 172800 the rekey almost never fires within a session, which is likely why this has gone unnoticed.

Requested action

Primary (documentation — what this report asks for):

  • State explicitly in doc/sample.config (and the manual) that rekey-method = ssl only applies to TLS ≤ 1.2, that on TLS 1.3 the server falls back to new-tunnel, and that the fallback causes a full reconnect (TLS/DTLS re-establishment, new TUN interface, brief inner-session interruption).
  • Recommend, for deployments that need seamless behavior, setting rekey-time greater than session-timeout (so rekey never fires mid-session) rather than disabling rekey with 0 (the existing note warns some clients fail when rekey is disabled).

Optional (maintainer discretion):

  • Log once per session when the configured rekey-method is overridden to new-tunnel, so operators can detect the condition.
  • Consider TLS 1.3 KeyUpdate (gnutls_session_key_update) as an in-place rekey for the control channel instead of forcing new-tunnel. Unverified — flagged as a design question, not a proposed patch.

Reproduction

  1. rekey-time = 60 (small, for fast reproduction), rekey-method = ssl, TLS 1.3 allowed (cisco-client-compat off, default priorities).
  2. Connect with an OpenConnect client that negotiates TLS 1.3 on CSTP.
  3. Start a large sustained download through the tunnel.
  4. Observe, every ~60 s: a new vpnsN interface on the server, X-CSTP-Rekey-Method: new-tunnel advertised despite rekey-method = ssl, and the download stalling/aborting while the VPN stays "connected".