mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-10 17:17:06 +02:00
MEDIUM: ssl: add bind-option "strict-sni"
This new option ensures that there is no possible fallback to a default certificate if the client does not provide an SNI which is explicitly handled by a certificate.
This commit is contained in:
parent
cb2699a152
commit
656233715e
@ -7241,6 +7241,12 @@ ssl
|
|||||||
appear in clear text, so that ACLs and HTTP processing will only have access
|
appear in clear text, so that ACLs and HTTP processing will only have access
|
||||||
to deciphered contents.
|
to deciphered contents.
|
||||||
|
|
||||||
|
strict-sni
|
||||||
|
This setting is only available when support for OpenSSL was built in. The
|
||||||
|
SSL/TLS negotiation is allow only if the client provided an SNI which match
|
||||||
|
a certificate. The default certificate is not used.
|
||||||
|
See the "crt" option for more information.
|
||||||
|
|
||||||
tfo
|
tfo
|
||||||
Is an optional keyword which is supported only on Linux kernels >= 3.6. It
|
Is an optional keyword which is supported only on Linux kernels >= 3.6. It
|
||||||
enables TCP Fast Open on the listening socket, which means that clients which
|
enables TCP Fast Open on the listening socket, which means that clients which
|
||||||
|
@ -127,6 +127,7 @@ struct bind_conf {
|
|||||||
SSL_CTX *default_ctx; /* SSL context of first/default certificate */
|
SSL_CTX *default_ctx; /* SSL context of first/default certificate */
|
||||||
char *npn_str; /* NPN protocol string */
|
char *npn_str; /* NPN protocol string */
|
||||||
int npn_len; /* NPN protocol string length */
|
int npn_len; /* NPN protocol string length */
|
||||||
|
int strict_sni; /* refuse negotiation if sni doesn't match a certificate */
|
||||||
struct eb_root sni_ctx; /* sni_ctx tree of all known certs full-names sorted by name */
|
struct eb_root sni_ctx; /* sni_ctx tree of all known certs full-names sorted by name */
|
||||||
struct eb_root sni_w_ctx; /* sni_ctx tree of all known certs wildcards sorted by name */
|
struct eb_root sni_w_ctx; /* sni_ctx tree of all known certs wildcards sorted by name */
|
||||||
#endif
|
#endif
|
||||||
|
@ -178,8 +178,12 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
|
|||||||
(void)al; /* shut gcc stupid warning */
|
(void)al; /* shut gcc stupid warning */
|
||||||
|
|
||||||
servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||||
if (!servername)
|
if (!servername) {
|
||||||
|
if (s->strict_sni)
|
||||||
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
|
else
|
||||||
return SSL_TLSEXT_ERR_NOACK;
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < trash.size; i++) {
|
for (i = 0; i < trash.size; i++) {
|
||||||
if (!servername[i])
|
if (!servername[i])
|
||||||
@ -193,14 +197,21 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
|
|||||||
/* lookup in full qualified names */
|
/* lookup in full qualified names */
|
||||||
node = ebst_lookup(&s->sni_ctx, trash.str);
|
node = ebst_lookup(&s->sni_ctx, trash.str);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
if (!wildp)
|
if (!wildp) {
|
||||||
|
if (s->strict_sni)
|
||||||
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
|
else
|
||||||
return SSL_TLSEXT_ERR_ALERT_WARNING;
|
return SSL_TLSEXT_ERR_ALERT_WARNING;
|
||||||
|
}
|
||||||
/* lookup in full wildcards names */
|
/* lookup in full wildcards names */
|
||||||
node = ebst_lookup(&s->sni_w_ctx, wildp);
|
node = ebst_lookup(&s->sni_w_ctx, wildp);
|
||||||
if (!node)
|
if (!node) {
|
||||||
|
if (s->strict_sni)
|
||||||
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
|
else
|
||||||
return SSL_TLSEXT_ERR_ALERT_WARNING;
|
return SSL_TLSEXT_ERR_ALERT_WARNING;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* switch ctx */
|
/* switch ctx */
|
||||||
SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
|
SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
|
||||||
@ -2569,6 +2580,13 @@ static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bin
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* parse the "strict-sni" bind keyword */
|
||||||
|
static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
|
||||||
|
{
|
||||||
|
conf->strict_sni = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* parse the "verify" bind keyword */
|
/* parse the "verify" bind keyword */
|
||||||
static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
|
static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
|
||||||
{
|
{
|
||||||
@ -2888,6 +2906,7 @@ static struct bind_kw_list bind_kws = { "SSL", { }, {
|
|||||||
{ "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
|
{ "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
|
||||||
{ "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
|
{ "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
|
||||||
{ "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
|
{ "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
|
||||||
|
{ "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
|
||||||
{ "verify", bind_parse_verify, 1 }, /* set SSL verify method */
|
{ "verify", bind_parse_verify, 1 }, /* set SSL verify method */
|
||||||
{ "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
|
{ "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
|
||||||
{ NULL, NULL, 0 },
|
{ NULL, NULL, 0 },
|
||||||
|
Loading…
Reference in New Issue
Block a user