diff --git a/doc/configuration.txt b/doc/configuration.txt index 507c2da03..4c18eb7f6 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -18189,6 +18189,12 @@ no-send-proxy-v2-ssl-cn It may also be used as "default-server" setting to reset any previous "default-server" "send-proxy-v2-ssl-cn" setting. +no-sni-auto + May be used in the following contexts: tcp, http, log, peers, ring + + This option may be used as "server" setting to disable the automatic SNI + selection which is enabled by default. + no-ssl May be used in the following contexts: tcp, http, log, peers, ring @@ -18756,6 +18762,24 @@ sni By default, the SNI is assigned to the connection name for "http-reuse", unless overridden by the "pool-conn-name" server keyword. +sni-auto + May be used in the following contexts: tcp, http, log, peers, ring + + The "sni-auto" parameter enables the automatic SNI selection, if no value was + already set. It is enabled by default but this parameter may be used as + "server" setting to reset any "no-sni-auto" setting which would have been + inherited from "default-server" directive as default value. It may also be + used as "default-server" setting to reset any previous "default-server" + "no-sni-auto" setting. + + For HTTPS connections, the selected SNI is based on the request host header + value, if found. Otherwise it remains unset. For other protocols, the option + is ignored. + + If the automatic selection of the SNI is used, the value is assigned to the + connection name for "http-reuse", unless overridden by the "pool-conn-name" + server keyword. + source [:[-]] [usesrc { [:] | client | clientip } ] source [:] [usesrc { [:] | hdr_ip([,]) } ] source [:[-]] [interface ] ... diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index dd76ffac6..3cd1f7bdd 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -201,6 +201,7 @@ enum srv_init_state { /* server ssl options */ #define SRV_SSL_O_NONE 0x0000 +#define SRV_SSL_O_NO_AUTO_SNI 0x0001 /* disable automatic SNI */ #define SRV_SSL_O_NO_TLS_TICKETS 0x0100 /* disable session resumption tickets */ #define SRV_SSL_O_NO_REUSE 0x200 /* disable session reuse */ #define SRV_SSL_O_EARLY_DATA 0x400 /* Allow using early data */ diff --git a/include/haproxy/server.h b/include/haproxy/server.h index 7f38cd53b..79cf880b3 100644 --- a/include/haproxy/server.h +++ b/include/haproxy/server.h @@ -52,6 +52,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr int srv_update_addr(struct server *s, void *ip, int ip_sin_family, struct server_inetaddr_updater updater); struct sample_expr *_parse_srv_expr(char *expr, struct arg_list *args_px, const char *file, int linenum, char **err); +int server_parse_exprs(struct server *srv, struct proxy *px, char **err); int server_set_inetaddr(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater, struct buffer *msg); int server_set_inetaddr_warn(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater); void server_get_inetaddr(struct server *s, struct server_inetaddr *inetaddr); diff --git a/reg-tests/ssl/set_ssl_cafile.vtc b/reg-tests/ssl/set_ssl_cafile.vtc index 897fe5e40..66511ded8 100644 --- a/reg-tests/ssl/set_ssl_cafile.vtc +++ b/reg-tests/ssl/set_ssl_cafile.vtc @@ -51,11 +51,11 @@ haproxy h1 -conf { bind "fd@${clearlst}" # dummy bind used to test a change when the same crt is used as server and bind bind "fd@${foobarlst}" ssl crt ${testdir}/set_cafile_client.pem ca-file ${testdir}/set_cafile_interCA1.crt verify none - server s1 "${tmpdir}/ssl.sock" ssl crt ${testdir}/set_cafile_client.pem ca-file ${testdir}/set_cafile_interCA1.crt verify none + server s1 "${tmpdir}/ssl.sock" ssl crt ${testdir}/set_cafile_client.pem ca-file ${testdir}/set_cafile_interCA1.crt verify none no-sni-auto listen clear-verified-lst bind "fd@${clearverifiedlst}" - server s1 "${tmpdir}/ssl.sock" ssl crt ${testdir}/set_cafile_client.pem ca-file ${testdir}/set_cafile_interCA1.crt verify required + server s1 "${tmpdir}/ssl.sock" ssl crt ${testdir}/set_cafile_client.pem ca-file ${testdir}/set_cafile_interCA1.crt verify required no-sni-auto listen ssl-lst # crt: certificate of the server diff --git a/reg-tests/ssl/set_ssl_crlfile.vtc b/reg-tests/ssl/set_ssl_crlfile.vtc index 05ff67382..23537918c 100644 --- a/reg-tests/ssl/set_ssl_crlfile.vtc +++ b/reg-tests/ssl/set_ssl_crlfile.vtc @@ -52,7 +52,7 @@ haproxy h1 -conf { listen clear-lst bind "fd@${clearlst}" - server s1 "${tmpdir}/ssl.sock" ssl crt ${testdir}/set_cafile_client.pem ca-file ${testdir}/set_cafile_interCA2.crt crl-file ${testdir}/interCA2_crl_empty.pem verify required + server s1 "${tmpdir}/ssl.sock" ssl crt ${testdir}/set_cafile_client.pem ca-file ${testdir}/set_cafile_interCA2.crt crl-file ${testdir}/interCA2_crl_empty.pem verify required no-sni-auto listen ssl-lst # crt: certificate of the server diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c index 583461d6a..141da2357 100644 --- a/src/cfgparse-ssl.c +++ b/src/cfgparse-ssl.c @@ -2033,6 +2033,20 @@ static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct ser #endif } +/* parse the "sni-auto" server keyword */ +static int srv_parse_sni_auto(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err) +{ + newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_AUTO_SNI; + return 0; +} + +/* parse the "no-sni-auto" server keyword */ +static int srv_parse_no_sni_auto(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err) +{ + newsrv->ssl_ctx.options |= SRV_SSL_O_NO_AUTO_SNI; + return 0; +} + /* parse the "ssl" server keyword */ static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err) { @@ -2597,6 +2611,7 @@ static struct srv_kw_list srv_kws = { "SSL", { }, { { "no-renegotiate", srv_parse_renegotiate, 0, 1, 1 }, /* Disable renegotiation */ { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */ { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */ + { "no-sni-auto", srv_parse_no_sni_auto, 0, 1, 0 }, /* disable automatic SNI selection */ { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */ { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */ { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */ @@ -2611,6 +2626,7 @@ static struct srv_kw_list srv_kws = { "SSL", { }, { { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */ { "sigalgs", srv_parse_sigalgs, 1, 1, 1 }, /* signature algorithms */ { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */ + { "sni-auto", srv_parse_sni_auto, 0, 1, 0 }, /* enable automatic SNI selection */ { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */ { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */ { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */ diff --git a/src/cfgparse.c b/src/cfgparse.c index e1b4933dc..0bd29feb0 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -3761,6 +3761,25 @@ out_uri_auth_compat: cfgerr += xprt_get(XPRT_QUIC)->prepare_srv(newsrv); } + if (newsrv->use_ssl == 1 || ((newsrv->flags & SRV_F_DEFSRV_USE_SSL) && newsrv->use_ssl != 1)) { + /* In HTTP only, if the SNI not set and we can realy on the host + * header value, fill the sni expression accordingly + */ + if (newsrv->proxy->mode == PR_MODE_HTTP && !(newsrv->ssl_ctx.options & SRV_SSL_O_NO_AUTO_SNI)) { + newsrv->sni_expr = strdup("req.hdr(host),field(1,:)"); + + err = NULL; + if (server_parse_exprs(newsrv, curproxy, &err)) { + ha_alert("parsing [%s:%d]: failed to parse auto SNI expression: %s\n", + newsrv->conf.file, newsrv->conf.line, err); + free(err); + ++cfgerr; + goto next_srv; + } + } + } + + if ((newsrv->flags & SRV_F_FASTOPEN) && ((curproxy->retry_type & (PR_RE_DISCONNECTED | PR_RE_TIMEOUT)) != (PR_RE_DISCONNECTED | PR_RE_TIMEOUT))) diff --git a/src/server.c b/src/server.c index 441b7f831..83257e151 100644 --- a/src/server.c +++ b/src/server.c @@ -54,7 +54,6 @@ #include #include -static inline int _srv_parse_exprs(struct server *srv, struct proxy *px, char **errmsg); static void srv_update_status(struct server *s, int type, int cause); static int srv_apply_lastaddr(struct server *srv, int *err_code); static void srv_cleanup_connections(struct server *srv); @@ -2768,7 +2767,7 @@ int srv_set_ssl(struct server *s, int use_ssl) s->use_ssl = use_ssl; if (s->use_ssl) { - if (_srv_parse_exprs(s, s->proxy, NULL)) + if (server_parse_exprs(s, s->proxy, NULL)) return -1; s->xprt = xprt_get(XPRT_SSL); } @@ -3303,7 +3302,7 @@ static inline void _srv_parse_set_id_from_prefix(struct server *srv, /* Parse the sni and pool-conn-name expressions. Returns 0 on success and non-zero on * error. */ -static inline int _srv_parse_exprs(struct server *srv, struct proxy *px, char **errmsg) +int server_parse_exprs(struct server *srv, struct proxy *px, char **errmsg) { int ret = 0; @@ -3369,7 +3368,7 @@ static int _srv_parse_tmpl_init(struct server *srv, struct proxy *px) srv_settings_cpy(newsrv, srv, 1); srv_prepare_for_resolution(newsrv, srv->hostname); - if (_srv_parse_exprs(newsrv, px, NULL)) + if (server_parse_exprs(newsrv, px, NULL)) goto err; /* append to list of servers available to receive an hostname */ @@ -3876,7 +3875,7 @@ static int _srv_parse_finalize(char **args, int cur_arg, return ERR_ALERT | ERR_FATAL; } - if ((ret = _srv_parse_exprs(srv, px, &errmsg))) { + if ((ret = server_parse_exprs(srv, px, &errmsg))) { if (errmsg) { ha_alert("error detected while parsing sni or pool-conn-name expressions : %s.\n", errmsg); free(errmsg);