MEDIUM: checks: Add check-alpn.
Add a way to configure the ALPN used by check, with a new "check-alpn"
keyword. By default, the checks will use the server ALPN, but it may not
be convenient, for instance because the server may use HTTP/2, while checks
are unable to do HTTP/2 yet.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 822a5c5..d81cdcd 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -11569,6 +11569,11 @@
"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 <protocols>
+ 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 <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 <sni>. If you want to
diff --git a/include/types/checks.h b/include/types/checks.h
index 364eee8..6346fe3 100644
--- a/include/types/checks.h
+++ b/include/types/checks.h
@@ -186,6 +186,8 @@
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 cb89f2f..4baaf9f 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -1621,6 +1621,9 @@
#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 24732b3..4cd8784 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1613,6 +1613,8 @@
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 d45e3e2..282b85d 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -7966,34 +7966,42 @@
#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 (<len> <name>)*,
* so we reuse each comma to store the next <len> 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 @@
{ "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 */