mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 13:21:29 +02:00
MEDIUM: server/ssl: Base the SNI value to the HTTP host header by default
For HTTPS outgoing connections, the SNI is now automatically set using the Host header value if no other value is already set (via the "sni" server keyword). It is now the default behavior. It could be disabled with the "no-sni-auto" server keyword. And eventually "sni-auto" server keyword may be used to reset any previous "no-sni-auto" setting. This option can be inherited from "default-server" settings. Finally, if no connection name is set via "pool-conn-name" setting, the selected value is used. The automatic selection of the SNI is enabled by default for all outgoing connections. But it is concretely used for HTTPS connections only. The expression used is "req.hdr(host),host_only". This patch should paritally fix the issue #3081. It only covers the server part. Another patch will add the feature for HTTP health-checks.
This commit is contained in:
parent
58555b8653
commit
668916c1a2
@ -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 <expression>
|
||||
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 <addr>[:<pl>[-<ph>]] [usesrc { <addr2>[:<port2>] | client | clientip } ]
|
||||
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | hdr_ip(<hdr>[,<occ>]) } ]
|
||||
source <addr>[:<pl>[-<ph>]] [interface <name>] ...
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)))
|
||||
|
@ -54,7 +54,6 @@
|
||||
#include <haproxy/xxhash.h>
|
||||
#include <haproxy/event_hdl.h>
|
||||
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user