cannot be enabled using any configuration option. See also "force-tls*",
and "force-sslv3".
+npn <protocols>
+ This enables the NPN TLS extension and advertises the specified protocol list
+ as supported on top of NPN. The protocol list consists in a comma-delimited
+ list of protocol names, for instance: "http/1.1,http/1.0" (without quotes).
+ This requires that the SSL library is build with support for TLS extensions
+ enabled (check with haproxy -vv).
+
ssl
This setting is only available when support for OpenSSL was built in. It
enables SSL deciphering on connections instanciated from this listener. A
layer which deciphered it and found a Next Protocol Negociation TLS extension
sent by the client, matching the specified string. This requires that the SSL
library is build with support for TLS extensions enabled (check haproxy -vv).
+ Note that the TLS NPN extension is not advertised unless the "npn" keyword on
+ the "bind" line specifies a protocol list. Also, nothing forces the client to
+ pick a protocol from this list, any other one may be requested.
ssl_sni <string>
Returns true when the incoming connection was made over an SSL/TLS transport
return 0;
}
+#ifdef OPENSSL_NPN_NEGOTIATED
+/* This callback is used so that the server advertises the list of
+ * negociable protocols for NPN.
+ */
+static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
+ unsigned int *len, void *arg)
+{
+ struct bind_conf *conf = arg;
+
+ *data = (const unsigned char *)conf->npn_str;
+ *len = conf->npn_len;
+ return SSL_TLSEXT_ERR_OK;
+}
+#endif
+
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
* warning when no match is found, which implies the default (first) cert
}
SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
+#ifdef OPENSSL_NPN_NEGOTIATED
+ if (bind_conf->npn_str)
+ SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
+#endif
+
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
#endif
}
+#ifdef OPENSSL_NPN_NEGOTIATED
static int
smp_fetch_ssl_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp)
{
-#ifdef OPENSSL_NPN_NEGOTIATED
smp->flags = 0;
smp->type = SMP_T_CSTR;
return 0;
return 1;
-#else
- return 0;
-#endif
}
+#endif
static int
smp_fetch_ssl_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
return 0;
}
+/* parse the "npn" bind keyword */
+static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
+{
+#ifdef OPENSSL_NPN_NEGOTIATED
+ char *p1, *p2;
+
+ if (!*args[cur_arg + 1]) {
+ memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ free(conf->npn_str);
+
+ /* the NPN string is built as a suite of (<len> <name>)* */
+ conf->npn_len = strlen(args[cur_arg + 1]) + 1;
+ conf->npn_str = calloc(1, conf->npn_len);
+ memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
+
+ /* replace commas with the name length */
+ p1 = conf->npn_str;
+ p2 = p1 + 1;
+ while (1) {
+ p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
+ if (!p2)
+ p2 = p1 + 1 + strlen(p1 + 1);
+
+ if (p2 - (p1 + 1) > 255) {
+ *p2 = '\0';
+ memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ *p1 = p2 - (p1 + 1);
+ p1 = p2;
+
+ if (!*p2)
+ break;
+
+ *(p2++) = '\0';
+ }
+ return 0;
+#else
+ if (err)
+ memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+#endif
+}
+
/* parse the "ssl" bind keyword */
static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
{ "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
{ "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
{ "verify", bind_parse_verify, 1 }, /* set SSL verify method */
+ { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
{ NULL, NULL, 0 },
}};