]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: checks: Add check-alpn.
authorOlivier Houchard <ohouchard@haproxy.com>
Fri, 21 Dec 2018 18:47:01 +0000 (19:47 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 21 Dec 2018 18:54:16 +0000 (19:54 +0100)
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.

doc/configuration.txt
include/types/checks.h
src/checks.c
src/server.c
src/ssl_sock.c

index 822a5c5836dfb05644d733b1c07fb59cbd120dca..d81cdcde882b1641ab33143bdacd4032f1026557 100644 (file)
@@ -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 <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
index 364eee88d164de562e3a15ed37b41ffb02c8c4f5..6346fe33921cba889b3df63c47cc9659a3ed36e0 100644 (file)
@@ -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 {
index cb89f2f64fdc7ce88870a630968073864a39d318..4baaf9fc99ac28a2ad553416b415afe1c9cca148 100644 (file)
@@ -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;
index 24732b3019e556fbd7616c7ae4fc701610d9a387..4cd87849d8bca882e58f62dade23e0f30fecbfe5 100644 (file)
@@ -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;
index d45e3e27be6543f3150753b04dee30aa4774dde2..282b85ddd8273e81068b6a73208173dc94c57c1a 100644 (file)
@@ -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 (<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 @@ 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 */