KeyUpdate is cpu-expensive, and there is little reason to receive a lot of
them. Using a value of "0" disables the rate limiting.
The default value is 100.
+tune.ssl.ktls-unsafe
+ Use kTLS even on OpenSSL versions affected by a bug that corrupts streams
+ when a pending record's buffer is reused (fixed in 3.4.6 and 3.5.7). On
+ those versions kTLS is refused, and a notice reports it when "ktls on" is
+ parsed, unless this option is set. It has no effect on fixed versions nor
+ on other SSL libraries. Disabled by default.
+
tune.ssl.lifetime <timeout>
Sets how long a cached SSL session may remain valid. This time is expressed
in seconds and defaults to 300 (5 min). It is important to understand that it
#define HA_USE_KTLS
#endif /* OPENSSL_IS_BORINGSSL || OPENSSL_IS_AWSLC */
+/* OpenSSL 3.4.6 and 3.5.7 fixed a kTLS bug where a blocked send kept
+ * referencing the caller's buffer; earlier versions corrupt streams.
+ */
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+#define HAVE_KTLS_TX_RETRY_FIX
+#elif defined(HAVE_VANILLA_OPENSSL) && \
+ (OPENSSL_VERSION_NUMBER >= 0x30500070L || \
+ (OPENSSL_VERSION_NUMBER >= 0x30400060L && OPENSSL_VERSION_NUMBER < 0x30500000L))
+#define HAVE_KTLS_TX_RETRY_FIX
+#endif
+
#endif /* USE_KTLS */
#endif /* USE_OPENSSL */
int skip_self_issued_ca;
int async; /* whether we use ssl async mode */
+ int ktls_unsafe; /* allow kTLS despite the library kTLS bug */
char *listen_default_ciphers;
char *connect_default_ciphers;
extern struct eb_root cafile_tree;
extern int sctl_ex_index;
extern struct global_ssl global_ssl;
+
+int ssl_sock_ktls_allowed(void);
extern struct ssl_crtlist_kw ssl_crtlist_kws[];
extern struct methodVersions methodVersions[];
__decl_thread(extern HA_SPINLOCK_T ckch_lock);
return 0;
}
+static int ssl_parse_global_ktls_unsafe(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ if (too_many_args(0, args, err, NULL))
+ return -1;
+
+ global_ssl.ktls_unsafe = 1;
+ return 0;
+}
+
/* Allow to explicitly disable certificate compression when set to "off" */
#ifdef SSL_OP_NO_RX_CERTIFICATE_COMPRESSION
static int ssl_parse_certificate_compression(char **args, int section_type, struct proxy *curpx,
return ERR_ALERT | ERR_FATAL;
}
if (strcasecmp(args[cur_arg + 1], "on") == 0) {
- conf->ktls = 1;
+ conf->ktls = ssl_sock_ktls_allowed();
} else if (strcasecmp(args[cur_arg + 1], "off") == 0) {
conf->ktls = 0;
} else {
}
if (strcasecmp(args[*cur_arg + 1], "on") == 0) {
- newsrv->ssl_ctx.options |= SRV_SSL_O_KTLS;
+ if (ssl_sock_ktls_allowed())
+ newsrv->ssl_ctx.options |= SRV_SSL_O_KTLS;
} else if (strcasecmp(args[*cur_arg + 1], "off") == 0) {
newsrv->ssl_ctx.options &= ~SRV_SSL_O_KTLS;
} else {
{ CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
{ CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
{ CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
+ { CFG_GLOBAL, "tune.ssl.ktls-unsafe", ssl_parse_global_ktls_unsafe },
{ CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
{ CFG_GLOBAL, "tune.ssl.keyupdate-rate-limit", ssl_parse_global_keyupdate_ratelimit },
{ CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
* handshake flag on the connection. It is safe to call it multiple times.
* It returns 0 on success and -1 in error case.
*/
+/* kTLS silently corrupts streams on libraries that keep referencing the caller's
+ * buffer after a blocked send (fixed in 3.4.6 and 3.5.7), so it is refused by
+ * default and the user has to opt in.
+ */
+int ssl_sock_ktls_allowed(void)
+{
+#ifdef HAVE_KTLS_TX_RETRY_FIX
+ return 1;
+#else
+ static char warned;
+
+ if (global_ssl.ktls_unsafe)
+ return 1;
+ if (!warned) {
+ warned = 1;
+ ha_notice("kTLS disabled: this OpenSSL version is affected by a known "
+ "kTLS bug; upgrade to at least 3.4.6 or 3.5.7, or set "
+ "'tune.ssl.ktls-unsafe' to use it anyway.\n");
+ }
+ return 0;
+#endif
+}
+
static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
{
struct ssl_sock_ctx *ctx;
ssl_sock_srv_try_reuse_sess(ctx, srv);
#ifdef HA_USE_KTLS
- if ((srv->ssl_ctx.options & SRV_SSL_O_KTLS) && !(global.tune.options & GTUNE_NO_KTLS)) {
+ if ((srv->ssl_ctx.options & SRV_SSL_O_KTLS) &&
+ !(global.tune.options & GTUNE_NO_KTLS) && ssl_sock_ktls_allowed()) {
#ifdef HAVE_VANILLA_OPENSSL
SSL_set_options(ctx->ssl, SSL_OP_ENABLE_KTLS);
#endif
#endif
#ifdef HA_USE_KTLS
- if (bc->ssl_conf.ktls && !(global.tune.options & GTUNE_NO_KTLS)) {
+ if (bc->ssl_conf.ktls &&
+ !(global.tune.options & GTUNE_NO_KTLS) && ssl_sock_ktls_allowed()) {
#ifdef HAVE_VANILLA_OPENSSL
SSL_set_options(ctx->ssl, SSL_OP_ENABLE_KTLS);
#endif