[9.20] chg: dev: Add TLS SNI extension to all outgoing TLS connections

Backport of !9923.

Merge branch 'artem-outgoing-tls-sni-support-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!9933
This commit is contained in:
Artem Boldariev 2024-12-26 17:13:03 +00:00
commit b14148ac89
13 changed files with 92 additions and 55 deletions

View file

@ -2785,6 +2785,12 @@ _cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line) {
check_if_done();
}
static inline const char *
get_tls_sni_hostname(dig_query_t *query) {
return query->lookup->tls_hostname_set ? query->lookup->tls_hostname
: query->userarg;
}
static isc_tlsctx_t *
get_create_tls_context(dig_query_t *query, const bool is_https,
isc_tlsctx_client_session_cache_t **psess_cache) {
@ -2831,10 +2837,7 @@ get_create_tls_context(dig_query_t *query, const bool is_https,
}
if (store != NULL) {
const char *hostname =
query->lookup->tls_hostname_set
? query->lookup->tls_hostname
: query->userarg;
const char *hostname = get_tls_sni_hostname(query);
/*
* According to RFC 8310, Subject field MUST NOT be
* inspected when verifying hostname for DoT. Only
@ -3048,7 +3051,8 @@ start_tcp(dig_query_t *query) {
}
isc_nm_streamdnsconnect(netmgr, &localaddr, &query->sockaddr,
tcp_connected, connectquery,
local_timeout, tlsctx, sess_cache,
local_timeout, tlsctx,
get_tls_sni_hostname(query), sess_cache,
proxy_type, ppi);
#if HAVE_LIBNGHTTP2
} else if (query->lookup->https_mode) {
@ -3068,14 +3072,15 @@ start_tcp(dig_query_t *query) {
isc_nm_httpconnect(netmgr, &localaddr, &query->sockaddr, uri,
!query->lookup->https_get, tcp_connected,
connectquery, tlsctx, sess_cache,
connectquery, tlsctx,
get_tls_sni_hostname(query), sess_cache,
local_timeout, proxy_type, ppi);
#endif
} else {
isc_nm_streamdnsconnect(netmgr, &localaddr, &query->sockaddr,
tcp_connected, connectquery,
local_timeout, NULL, NULL, proxy_type,
ppi);
local_timeout, NULL, NULL, NULL,
proxy_type, ppi);
}
return;

View file

@ -378,16 +378,18 @@ run(void) {
connect_cb, NULL, timeout);
break;
case TCP:
isc_nm_streamdnsconnect(
netmgr, &sockaddr_local, &sockaddr_remote, connect_cb,
NULL, timeout, NULL, NULL, ISC_NM_PROXY_NONE, NULL);
isc_nm_streamdnsconnect(netmgr, &sockaddr_local,
&sockaddr_remote, connect_cb, NULL,
timeout, NULL, NULL, NULL,
ISC_NM_PROXY_NONE, NULL);
break;
case DOT: {
isc_tlsctx_createclient(&tls_ctx);
isc_nm_streamdnsconnect(
netmgr, &sockaddr_local, &sockaddr_remote, connect_cb,
NULL, timeout, tls_ctx, NULL, ISC_NM_PROXY_NONE, NULL);
isc_nm_streamdnsconnect(netmgr, &sockaddr_local,
&sockaddr_remote, connect_cb, NULL,
timeout, tls_ctx, NULL, NULL,
ISC_NM_PROXY_NONE, NULL);
break;
}
#if HAVE_LIBNGHTTP2
@ -408,7 +410,8 @@ run(void) {
}
isc_nm_httpconnect(netmgr, &sockaddr_local, &sockaddr_remote,
req_url, is_post, connect_cb, NULL, tls_ctx,
NULL, timeout, ISC_NM_PROXY_NONE, NULL);
NULL, NULL, timeout, ISC_NM_PROXY_NONE,
NULL);
} break;
#endif
default:

View file

@ -2007,10 +2007,16 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
"connecting from %s to %s, timeout %u", localbuf,
peerbuf, resp->timeout);
char *hostname = NULL;
if (resp->transport != NULL) {
hostname = dns_transport_get_remote_hostname(
resp->transport);
}
isc_nm_streamdnsconnect(disp->mgr->nm, &disp->local,
&disp->peer, tcp_connected, disp,
resp->timeout, tlsctx, sess_cache,
ISC_NM_PROXY_NONE, NULL);
resp->timeout, tlsctx, hostname,
sess_cache, ISC_NM_PROXY_NONE, NULL);
break;
case DNS_DISPATCHSTATE_CONNECTING:

View file

@ -494,6 +494,7 @@ void
isc_nm_proxystreamconnect(isc_nm_t *mgr, isc_sockaddr_t *local,
isc_sockaddr_t *peer, isc_nm_cb_t cb, void *cbarg,
unsigned int timeout, isc_tlsctx_t *tlsctx,
const char *sni_hostname,
isc_tlsctx_client_session_cache_t *client_sess_cache,
isc_nm_proxyheader_info_t *proxy_info);
/*%<
@ -616,6 +617,7 @@ void
isc_nm_streamdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local,
isc_sockaddr_t *peer, isc_nm_cb_t cb, void *cbarg,
unsigned int timeout, isc_tlsctx_t *tlsctx,
const char *sni_hostname,
isc_tlsctx_client_session_cache_t *client_sess_cache,
isc_nm_proxy_type_t proxy_type,
isc_nm_proxyheader_info_t *proxy_info);
@ -666,7 +668,7 @@ isc_nm_listentls(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface,
void
isc_nm_tlsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc_nm_cb_t connect_cb, void *connect_cbarg,
isc_tlsctx_t *ctx,
isc_tlsctx_t *ctx, const char *sni_hostname,
isc_tlsctx_client_session_cache_t *client_sess_cache,
unsigned int timeout, bool proxy,
isc_nm_proxyheader_info_t *proxy_info);
@ -678,7 +680,7 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
void
isc_nm_httpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
const char *uri, bool POST, isc_nm_cb_t cb, void *cbarg,
isc_tlsctx_t *ctx,
isc_tlsctx_t *ctx, const char *sni_hostname,
isc_tlsctx_client_session_cache_t *client_sess_cache,
unsigned int timeout, isc_nm_proxy_type_t proxy_type,
isc_nm_proxyheader_info_t *proxy_info);

View file

@ -1464,7 +1464,7 @@ error:
void
isc_nm_httpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
const char *uri, bool post, isc_nm_cb_t cb, void *cbarg,
isc_tlsctx_t *tlsctx,
isc_tlsctx_t *tlsctx, const char *sni_hostname,
isc_tlsctx_client_session_cache_t *client_sess_cache,
unsigned int timeout, isc_nm_proxy_type_t proxy_type,
isc_nm_proxyheader_info_t *proxy_info) {
@ -1535,8 +1535,8 @@ isc_nm_httpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
if (tlsctx != NULL) {
isc_nm_tlsconnect(mgr, local, peer,
transport_connect_cb, sock, tlsctx,
client_sess_cache, timeout, false,
NULL);
sni_hostname, client_sess_cache,
timeout, false, NULL);
} else {
isc_nm_tcpconnect(mgr, local, peer,
transport_connect_cb, sock, timeout);
@ -1546,19 +1546,19 @@ isc_nm_httpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
if (tlsctx != NULL) {
isc_nm_tlsconnect(mgr, local, peer,
transport_connect_cb, sock, tlsctx,
client_sess_cache, timeout, true,
proxy_info);
sni_hostname, client_sess_cache,
timeout, true, proxy_info);
} else {
isc_nm_proxystreamconnect(
mgr, local, peer, transport_connect_cb, sock,
timeout, NULL, NULL, proxy_info);
timeout, NULL, NULL, NULL, proxy_info);
}
break;
case ISC_NM_PROXY_ENCRYPTED:
INSIST(tlsctx != NULL);
isc_nm_proxystreamconnect(
mgr, local, peer, transport_connect_cb, sock, timeout,
tlsctx, client_sess_cache, proxy_info);
tlsctx, sni_hostname, client_sess_cache, proxy_info);
break;
default:
UNREACHABLE();

View file

@ -516,6 +516,7 @@ struct isc_nmsocket {
isc_tlsctx_t **listener_tls_ctx; /*%< A context reference per
worker */
size_t n_listener_tls_ctx;
char *sni_hostname;
isc_tlsctx_client_session_cache_t *client_sess_cache;
bool client_session_saved;
isc_nmsocket_t *tlslistener;

View file

@ -459,6 +459,7 @@ void
isc_nm_proxystreamconnect(isc_nm_t *mgr, isc_sockaddr_t *local,
isc_sockaddr_t *peer, isc_nm_cb_t cb, void *cbarg,
unsigned int timeout, isc_tlsctx_t *tlsctx,
const char *sni_hostname,
isc_tlsctx_client_session_cache_t *client_sess_cache,
isc_nm_proxyheader_info_t *proxy_info) {
isc_result_t result = ISC_R_FAILURE;
@ -501,8 +502,9 @@ isc_nm_proxystreamconnect(isc_nm_t *mgr, isc_sockaddr_t *local,
nsock, nsock->connect_timeout);
} else {
isc_nm_tlsconnect(mgr, local, peer, proxystream_connect_cb,
nsock, tlsctx, client_sess_cache,
nsock->connect_timeout, false, NULL);
nsock, tlsctx, sni_hostname,
client_sess_cache, nsock->connect_timeout,
false, NULL);
}
}

View file

@ -387,6 +387,7 @@ void
isc_nm_streamdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local,
isc_sockaddr_t *peer, isc_nm_cb_t cb, void *cbarg,
unsigned int timeout, isc_tlsctx_t *tlsctx,
const char *sni_hostname,
isc_tlsctx_client_session_cache_t *client_sess_cache,
isc_nm_proxy_type_t proxy_type,
isc_nm_proxyheader_info_t *proxy_info) {
@ -418,7 +419,7 @@ isc_nm_streamdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local,
} else {
isc_nm_tlsconnect(
mgr, local, peer, streamdns_transport_connected,
nsock, tlsctx, client_sess_cache,
nsock, tlsctx, sni_hostname, client_sess_cache,
nsock->connect_timeout, false, proxy_info);
}
break;
@ -427,20 +428,20 @@ isc_nm_streamdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local,
isc_nm_proxystreamconnect(mgr, local, peer,
streamdns_transport_connected,
nsock, nsock->connect_timeout,
NULL, NULL, proxy_info);
NULL, NULL, NULL, proxy_info);
} else {
isc_nm_tlsconnect(
mgr, local, peer, streamdns_transport_connected,
nsock, tlsctx, client_sess_cache,
nsock, tlsctx, sni_hostname, client_sess_cache,
nsock->connect_timeout, true, proxy_info);
}
break;
case ISC_NM_PROXY_ENCRYPTED:
INSIST(tlsctx != NULL);
isc_nm_proxystreamconnect(mgr, local, peer,
streamdns_transport_connected, nsock,
nsock->connect_timeout, tlsctx,
client_sess_cache, proxy_info);
isc_nm_proxystreamconnect(
mgr, local, peer, streamdns_transport_connected, nsock,
nsock->connect_timeout, tlsctx, sni_hostname,
client_sess_cache, proxy_info);
break;
default:
UNREACHABLE();

View file

@ -868,6 +868,14 @@ initialize_tls(isc_nmsocket_t *sock, bool server) {
sock->tlsstream.server = server;
sock->tlsstream.nsending = 0;
sock->tlsstream.state = TLS_INIT;
if (sock->tlsstream.sni_hostname != NULL) {
INSIST(sock->client);
const int ret = SSL_set_tlsext_host_name(
sock->tlsstream.tls, sock->tlsstream.sni_hostname);
if (ret != 1) {
goto error;
}
}
return ISC_R_SUCCESS;
error:
isc_tls_free(&sock->tlsstream.tls);
@ -1201,7 +1209,7 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t result, void *cbarg);
void
isc_nm_tlsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc_nm_cb_t connect_cb, void *connect_cbarg,
isc_tlsctx_t *ctx,
isc_tlsctx_t *ctx, const char *sni_hostname,
isc_tlsctx_client_session_cache_t *client_sess_cache,
unsigned int timeout, bool proxy,
isc_nm_proxyheader_info_t *proxy_info) {
@ -1223,6 +1231,10 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
sock->connect_cbarg = connect_cbarg;
sock->connect_timeout = timeout;
isc_tlsctx_attach(ctx, &sock->tlsstream.ctx);
if (sni_hostname != NULL) {
sock->tlsstream.sni_hostname =
isc_mem_strdup(sock->worker->mctx, sni_hostname);
}
sock->client = true;
if (client_sess_cache != NULL) {
INSIST(isc_tlsctx_client_session_cache_getctx(
@ -1234,7 +1246,7 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
if (proxy) {
isc_nm_proxystreamconnect(mgr, local, peer, tcp_connected, sock,
sock->connect_timeout, NULL, NULL,
proxy_info);
NULL, proxy_info);
} else {
isc_nm_tcpconnect(mgr, local, peer, tcp_connected, sock,
sock->connect_timeout);
@ -1334,6 +1346,10 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) {
if (sock->tlsstream.ctx != NULL) {
isc_tlsctx_free(&sock->tlsstream.ctx);
}
if (sock->tlsstream.sni_hostname != NULL) {
isc_mem_free(sock->worker->mctx,
sock->tlsstream.sni_hostname);
}
if (sock->tlsstream.client_sess_cache != NULL) {
INSIST(sock->client);
isc_tlsctx_client_session_cache_detach(

View file

@ -213,7 +213,7 @@ connect_send_request(isc_nm_t *mgr, const char *uri, bool post,
}
isc_nm_httpconnect(mgr, NULL, &tcp_listen_addr, uri, post,
connect_send_cb, data, ctx, client_sess_cache,
connect_send_cb, data, ctx, NULL, client_sess_cache,
timeout, get_proxy_type(), NULL);
}
@ -698,7 +698,7 @@ doh_timeout_recovery(void *arg ISC_ATTR_UNUSED) {
ISC_NM_HTTP_DEFAULT_PATH);
isc_nm_httpconnect(connect_nm, NULL, &tcp_listen_addr, req_url,
atomic_load(&POST), timeout_request_cb, NULL, ctx,
client_sess_cache, T_CONNECT, get_proxy_type(),
NULL, client_sess_cache, T_CONNECT, get_proxy_type(),
NULL);
}
@ -947,8 +947,8 @@ doh_recv_two(void *arg ISC_ATTR_UNUSED) {
isc_nm_httpconnect(connect_nm, NULL, &tcp_listen_addr, req_url,
atomic_load(&POST), doh_connect_send_two_requests_cb,
NULL, ctx, client_sess_cache, 5000, get_proxy_type(),
NULL);
NULL, ctx, NULL, client_sess_cache, 5000,
get_proxy_type(), NULL);
isc_loop_teardown(mainloop, listen_sock_close, listen_sock);
}

View file

@ -595,7 +595,7 @@ tcp_connect(isc_nm_t *nm) {
static void
tls_connect(isc_nm_t *nm) {
isc_nm_tlsconnect(nm, &tcp_connect_addr, &tcp_listen_addr,
connect_connect_cb, NULL, tcp_connect_tlsctx,
connect_connect_cb, NULL, tcp_connect_tlsctx, NULL,
tcp_tlsctx_client_sess_cache, T_CONNECT,
stream_use_PROXY, NULL);
}
@ -631,7 +631,7 @@ proxystream_connect(isc_nm_t *nm) {
isc_nm_proxystreamconnect(nm, &tcp_connect_addr, &tcp_listen_addr,
connect_connect_cb, NULL, T_CONNECT, tlsctx,
sess_cache, get_proxyheader_info());
NULL, sess_cache, get_proxyheader_info());
}
stream_connect_function
@ -680,10 +680,11 @@ stream_connect(isc_nm_cb_t cb, void *cbarg, unsigned int timeout) {
isc_refcount_increment0(&active_cconnects);
if (stream_use_TLS && !stream_PROXY_over_TLS) {
isc_nm_tlsconnect(
connect_nm, &tcp_connect_addr, &tcp_listen_addr, cb,
cbarg, tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache,
timeout, stream_use_PROXY, NULL);
isc_nm_tlsconnect(connect_nm, &tcp_connect_addr,
&tcp_listen_addr, cb, cbarg,
tcp_connect_tlsctx, NULL,
tcp_tlsctx_client_sess_cache, timeout,
stream_use_PROXY, NULL);
return;
} else if (stream_use_PROXY) {
isc_tlsctx_t *tlsctx = stream_PROXY_over_TLS
@ -694,7 +695,7 @@ stream_connect(isc_nm_cb_t cb, void *cbarg, unsigned int timeout) {
: NULL;
isc_nm_proxystreamconnect(connect_nm, &tcp_connect_addr,
&tcp_listen_addr, cb, cbarg, timeout,
tlsctx, sess_cache,
tlsctx, NULL, sess_cache,
get_proxyheader_info());
return;
} else {

View file

@ -63,7 +63,7 @@ static void
tcpdns_connect(isc_nm_t *nm) {
isc_nm_streamdnsconnect(nm, &tcp_connect_addr, &tcp_listen_addr,
connect_connect_cb, tcpdns_connect, T_CONNECT,
NULL, NULL, get_proxy_type(), NULL);
NULL, NULL, NULL, get_proxy_type(), NULL);
}
ISC_LOOP_TEST_IMPL(tcpdns_noop) {
@ -73,7 +73,7 @@ ISC_LOOP_TEST_IMPL(tcpdns_noop) {
isc_refcount_increment0(&active_cconnects);
isc_nm_streamdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
connect_success_cb, tcpdns_connect, T_CONNECT,
NULL, NULL, get_proxy_type(), NULL);
NULL, NULL, NULL, get_proxy_type(), NULL);
}
ISC_LOOP_TEST_IMPL(tcpdns_noresponse) {
@ -82,7 +82,7 @@ ISC_LOOP_TEST_IMPL(tcpdns_noresponse) {
isc_refcount_increment0(&active_cconnects);
isc_nm_streamdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
connect_connect_cb, tcpdns_connect, T_CONNECT,
NULL, NULL, get_proxy_type(), NULL);
NULL, NULL, NULL, get_proxy_type(), NULL);
}
ISC_LOOP_TEST_IMPL(tcpdns_timeout_recovery) {

View file

@ -63,7 +63,7 @@ static void
tlsdns_connect(isc_nm_t *nm) {
isc_nm_streamdnsconnect(
nm, &tcp_connect_addr, &tcp_listen_addr, connect_connect_cb,
tlsdns_connect, T_CONNECT, tcp_connect_tlsctx,
tlsdns_connect, T_CONNECT, tcp_connect_tlsctx, NULL,
tcp_tlsctx_client_sess_cache, get_proxy_type(), NULL);
}
@ -74,7 +74,7 @@ ISC_LOOP_TEST_IMPL(tlsdns_noop) {
isc_refcount_increment0(&active_cconnects);
isc_nm_streamdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
connect_success_cb, tlsdns_connect, T_CONNECT,
tcp_connect_tlsctx,
tcp_connect_tlsctx, NULL,
tcp_tlsctx_client_sess_cache, get_proxy_type(),
NULL);
}
@ -85,7 +85,7 @@ ISC_LOOP_TEST_IMPL(tlsdns_noresponse) {
isc_refcount_increment0(&active_cconnects);
isc_nm_streamdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
connect_connect_cb, tlsdns_connect, T_CONNECT,
tcp_connect_tlsctx,
tcp_connect_tlsctx, NULL,
tcp_tlsctx_client_sess_cache, get_proxy_type(),
NULL);
}
@ -109,7 +109,7 @@ ISC_LOOP_TEST_IMPL(tlsdns_timeout_recovery) {
isc_nm_streamdnsconnect(
connect_nm, &tcp_connect_addr, &tcp_listen_addr,
connect_connect_cb, tlsdns_connect, T_SOFT, tcp_connect_tlsctx,
tcp_tlsctx_client_sess_cache, get_proxy_type(), NULL);
NULL, tcp_tlsctx_client_sess_cache, get_proxy_type(), NULL);
}
ISC_LOOP_TEST_IMPL(tlsdns_recv_one) {