diff --git a/doc/configuration.txt b/doc/configuration.txt index 822a5c583..d81cdcde8 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -11569,6 +11569,11 @@ check-send-proxy "check-send-proxy" option needs to be used to force the use of the protocol. See also the "send-proxy" option for more information. +check-alpn + Defines which protocols to advertise with ALPN. The protocol list consists in + a comma-delimited list of protocol names, for instance: "http/1.1,http/1.0" + (without quotes). If it is not set, the server ALPN is used. + check-sni This option allows you to specify the SNI to be used when doing health checks over SSL. It is only possible to use a string to set . If you want to diff --git a/include/types/checks.h b/include/types/checks.h index 364eee88d..6346fe339 100644 --- a/include/types/checks.h +++ b/include/types/checks.h @@ -186,6 +186,8 @@ struct check { struct sockaddr_storage addr; /* the address to check */ struct wait_event wait_list; /* Waiting for I/O events */ char *sni; /* Server name */ + char *alpn_str; /* ALPN to use for checks */ + int alpn_len; /* ALPN string length */ }; struct check_status { diff --git a/src/checks.c b/src/checks.c index cb89f2f64..4baaf9fc9 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1621,6 +1621,9 @@ static int connect_conn_chk(struct task *t) #ifdef USE_OPENSSL if (s->check.sni) ssl_sock_set_servername(conn, s->check.sni); + if (s->check.alpn_str) + ssl_sock_set_alpn(conn, (unsigned char *)s->check.alpn_str, + s->check.alpn_len); #endif if (s->check.send_proxy && !(check->state & CHK_ST_AGENT)) { conn->send_proxy_ofs = 1; diff --git a/src/server.c b/src/server.c index 24732b301..4cd87849d 100644 --- a/src/server.c +++ b/src/server.c @@ -1613,6 +1613,8 @@ static void srv_settings_cpy(struct server *srv, struct server *src, int srv_tmp srv->check.use_ssl = src->check.use_ssl; srv->check.port = src->check.port; srv->check.sni = src->check.sni; + srv->check.alpn_str = src->check.alpn_str; + srv->check.alpn_len = srv->check.alpn_len; /* Note: 'flags' field has potentially been already initialized. */ srv->flags |= src->flags; srv->do_check = src->do_check; diff --git a/src/ssl_sock.c b/src/ssl_sock.c index d45e3e27b..282b85ddd 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -7966,34 +7966,42 @@ static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct ser #endif } -/* parse the "alpn" bind keyword */ +/* parse the "alpn" or the "check-alpn" server keyword */ static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err) { #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation char *p1, *p2; + char **alpn_str; + int *alpn_len; + if (*args[*cur_arg] == 'c') { + alpn_str = &newsrv->check.alpn_str; + alpn_len = &newsrv->check.alpn_len; + } else { + alpn_str = &newsrv->ssl_ctx.alpn_str; + alpn_len = &newsrv->ssl_ctx.alpn_len; + + } if (!*args[*cur_arg + 1]) { memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]); return ERR_ALERT | ERR_FATAL; } - free(newsrv->ssl_ctx.alpn_str); + free(*alpn_str); /* the ALPN string is built as a suite of ( )*, * so we reuse each comma to store the next and need * one more for the end of the string. */ - newsrv->ssl_ctx.alpn_len = strlen(args[*cur_arg + 1]) + 1; - newsrv->ssl_ctx.alpn_str = calloc(1, newsrv->ssl_ctx.alpn_len + 1); - memcpy(newsrv->ssl_ctx.alpn_str + 1, args[*cur_arg + 1], - newsrv->ssl_ctx.alpn_len); + *alpn_len = strlen(args[*cur_arg + 1]) + 1; + *alpn_str = calloc(1, *alpn_len + 1); + memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len); /* replace commas with the name length */ - p1 = newsrv->ssl_ctx.alpn_str; + p1 = *alpn_str; p2 = p1 + 1; while (1) { - p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.alpn_str + - newsrv->ssl_ctx.alpn_len - (p1 + 1)); + p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1)); if (!p2) p2 = p1 + 1 + strlen(p1 + 1); @@ -9132,6 +9140,7 @@ static struct srv_kw_list srv_kws = { "SSL", { }, { { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */ { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */ { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */ + { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */ { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */ { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */ { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */