protocol for health-check connections established to this server.
If not defined, the server one will be used, if set.
+check-sni-auto
+ May be used in the following contexts: tcp, http, log
+
+ This option enables the automatic SNI selection when doing health checks over
+ SSL, if no value was already set. It is enabled by default but this parameter
+ may be used as "server" setting to reset any "no-check-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-check-sni-auto" setting.
+
+ For HTTPS connections, the SNI is automatically selected but only if there is
+ no "http-check connect" rule. In that case, the selected SNI is based on the
+ host header value, specified via the "option httpchk" directive or a
+ "http-check send" rule. There is no automatic selection for "http-check
+ connect" rules. For other protocols, the option is ignored.
+
+ If the automatic selection of the SNI is used for health-checks, the value is
+ assigned to the connection name if "check-reuse-pool" setting is set, unless
+ overridden by the "check-pool-conn-name" server keyword.
+
+ See "sni-auto" option to enable automatic SNI selection for proxied traffic.
+
check-sni <sni>
May be used in the following contexts: tcp, http, log
This option reverts any previous "check-reuse-pool" possibly inherited from a
"default-server". Any checks will be conducted on its dedicated connection.
+no-check-sni-auto
+ May be used in the following contexts: tcp, http, log
+
+ This option may be used as "server" setting to disable the automatic SNI
+ selection for SSL health checks which is enabled by default.
+
+ See "no-sni-auto" option to disable automatic SNI selection for proxied
+ traffic.
+
no-check-ssl
May be used in the following contexts: tcp, http, log
This option may be used as "server" setting to disable the automatic SNI
selection which is enabled by default.
+ See "no-check-sni-auto" option to disable automatic SNI selection for SSL
+ health checks.
+
no-ssl
May be used in the following contexts: tcp, http, log, peers, ring
connection name for "http-reuse", unless overridden by the "pool-conn-name"
server keyword.
+ See "check-sni-auto" option to enable automatic SNI selection for SSL health
+ checks.
+
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>] ...
#define SRV_F_DEFSRV_USE_SSL 0x4000 /* default-server uses SSL */
#define SRV_F_DELETED 0x8000 /* srv is deleted but not yet purged */
#define SRV_F_STRICT_MAXCONN 0x10000 /* maxconn is to be strictly enforced, as a limit of outbound connections */
-/* unused: 0x20000 */
+#define SRV_F_CHK_NO_AUTO_SNI 0x20000 /* disable automatic SNI selection for healthcheck */
/* configured server options for send-proxy (server->pp_opts) */
#define SRV_PP_V1 0x0001 /* proxy protocol version 1 */
struct check;
struct tcpcheck_connect {
char *sni; /* server name to use for SSL connections */
+ struct lf_expr *sni_fmt; /* log-format string used for SNI. if defined, point on the following HTTP host header value */
char *alpn; /* ALPN to use for the SSL connection */
int alpn_len; /* ALPN string length */
const struct mux_proto_list *mux_proto; /* the mux to use for all outgoing connections (specified by the "proto" keyword) */
return 0;
}
+/* parse the "check-sni-auto" server keyword */
+static int srv_parse_check_sni_auto(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+ newsrv->flags &= ~SRV_F_CHK_NO_AUTO_SNI;
+ return 0;
+}
+
+/* parse the "no-check-sni-auto" server keyword */
+static int srv_parse_no_check_sni_auto(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+ newsrv->flags |= SRV_F_CHK_NO_AUTO_SNI;
+ return 0;
+}
+
/* parse the "no-check-ssl" server keyword */
static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
{
{ "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
{ "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
{ "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
+ { "check-sni-auto", srv_parse_check_sni_auto, 0, 1, 0 }, /* enable automatic SNI selection for health checks */
{ "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
{ "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
{ "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
{ "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
{ "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
{ "ktls", srv_parse_ktls, 1, 1, 1 }, /* enable or disable kTLS */
+ { "no-check-sni-auto", srv_parse_no_check_sni_auto, 0, 1, 0 }, /* disable automatic SNI selection for health checks */
{ "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
{ "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 */
return 0;
}
+static inline void tcpcheck_connect_auto_sni(const struct check *check,
+ const struct tcpcheck_connect *connect,
+ struct buffer *chk)
+{
+ chunk_reset(chk);
+ chk->data = sess_build_logline(check->sess, NULL, b_orig(chk), b_size(chk), connect->sni_fmt);
+ if (b_data(chk)) {
+ char *beg = b_orig(chk);
+ char *end = b_tail(chk) - 1;
+ char *p;
+
+ for (p = end; p >= beg; p--) {
+ if (*p == ':' || *p == ']')
+ break;
+ }
+ if (p >= beg && *p == ':')
+ b_set_data(chk, p - beg);
+ *b_tail(chk) = 0;
+ }
+}
+
/* Evaluates a TCPCHK_ACT_CONNECT rule. Returns TCPCHK_EVAL_WAIT to wait the
* connection establishment, TCPCHK_EVAL_CONTINUE to evaluate the next rule or
* TCPCHK_EVAL_STOP if an error occurred.
struct protocol *proto;
struct xprt_ops *xprt;
struct tcpcheck_rule *next;
+ struct buffer *auto_sni = NULL;
int status, port;
TRACE_ENTER(CHK_EV_TCPCHK_CONN, check);
check_release_buf(check, &check->bi);
check_release_buf(check, &check->bo);
+ /* Deal with automatic SNI selection now because it can be used as connection name */
+ if (tcpcheck_connect_use_ssl(check, connect) && s && !(s->flags & SRV_F_CHK_NO_AUTO_SNI) && connect->sni_fmt) {
+ auto_sni = alloc_trash_chunk();
+ if (auto_sni) {
+ tcpcheck_connect_auto_sni(check, connect, auto_sni);
+ if (!b_data(auto_sni)) {
+ free_trash_chunk(auto_sni);
+ auto_sni = NULL;
+ }
+ }
+ }
+
+
if (!(check->state & CHK_ST_AGENT) && check->reuse_pool &&
!tcpcheck_use_nondefault_connect(check, connect) &&
!srv_is_transparent(s)) {
pool_conn_name = ist(connect->sni);
else if ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT) && check->sni)
pool_conn_name = ist(check->sni);
+ else if (auto_sni)
+ pool_conn_name = ist2(b_orig(auto_sni), b_data(auto_sni));
}
if (!(s->flags & SRV_F_RHTTP)) {
ssl_sock_set_servername(conn, connect->sni);
else if ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT) && s && s->check.sni)
ssl_sock_set_servername(conn, s->check.sni);
+ else if (auto_sni)
+ ssl_sock_set_servername(conn, b_orig(auto_sni));
if (connect->alpn)
ssl_sock_set_alpn(conn, (unsigned char *)connect->alpn, connect->alpn_len);
if (ret == TCPCHK_EVAL_CONTINUE && check->proxy->timeout.check)
check->task->expire = tick_add_ifset(now_ms, check->proxy->timeout.check);
+ if (auto_sni)
+ free_trash_chunk(auto_sni);
+
TRACE_LEAVE(CHK_EV_TCPCHK_CONN, check, 0, 0, (size_t[]){ret});
return ret;
}
LIST_INSERT(px->tcpcheck_rules.list, &chk->list);
}
+ /* Now, back again on HTTP ruleset. Try to resolve the sni log-format
+ * string if necessary, but onlu for implicit connect rules, by getting
+ * it from the following send rule.
+ */
+ if ((px->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
+ struct tcpcheck_connect *connect = NULL;
+
+ list_for_each_entry(chk, px->tcpcheck_rules.list, list) {
+ if (chk->action == TCPCHK_ACT_CONNECT && !chk->connect.sni &&
+ (chk->connect.options & TCPCHK_OPT_IMPLICIT)) {
+ /* Only eval connect rule with no explici SNI */
+ connect = &chk->connect;
+ }
+ else if (connect && chk->action == TCPCHK_ACT_SEND) {
+ struct tcpcheck_http_hdr *hdr;
+
+ list_for_each_entry(hdr, &chk->send.http.hdrs, list) {
+ if (isteqi(hdr->name, ist("host")))
+ connect->sni_fmt = &hdr->value;
+ }
+ connect = NULL;
+ }
+ }
+ }
+
+
/* Remove all comment rules. To do so, when a such rule is found, the
* comment is assigned to the following rule(s).
*/