From: Artem Boldariev Date: Fri, 19 May 2023 11:28:52 +0000 (+0300) Subject: Stream DNS: add PROXY over TLS support X-Git-Tag: v9.19.19~10^2~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=eb52015db18416b1193f822e758c884b6eaa5c88;p=thirdparty%2Fbind9.git Stream DNS: add PROXY over TLS support This commit extends Stream DNS with PROXY over TLS support. --- diff --git a/bin/delv/delv.c b/bin/delv/delv.c index 801965c2f8c..25ff05e857c 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -2184,7 +2184,8 @@ run_server(void *arg) { CHECK(isc_nm_listenstreamdns(netmgr, ISC_NM_LISTEN_ONE, &addr, ns_client_request, ifp, accept_cb, ifp, 10, - NULL, NULL, false, &ifp->tcplistensocket)); + NULL, NULL, ISC_NM_PROXY_NONE, + &ifp->tcplistensocket)); ifp->flags |= NS_INTERFACEFLAG_LISTENING; isc_async_current(loopmgr, sendquery, ifp->tcplistensocket); diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index e494189bb5b..afca0d557e6 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -3025,7 +3025,7 @@ start_tcp(dig_query_t *query) { isc_nm_streamdnsconnect(netmgr, &localaddr, &query->sockaddr, tcp_connected, connectquery, local_timeout, tlsctx, sess_cache, - false, NULL); + ISC_NM_PROXY_NONE, NULL); #if HAVE_LIBNGHTTP2 } else if (query->lookup->https_mode) { char uri[4096] = { 0 }; @@ -3050,7 +3050,8 @@ start_tcp(dig_query_t *query) { } else { isc_nm_streamdnsconnect(netmgr, &localaddr, &query->sockaddr, tcp_connected, connectquery, - local_timeout, NULL, NULL, false, NULL); + local_timeout, NULL, NULL, + ISC_NM_PROXY_NONE, NULL); } return; diff --git a/bin/tests/test_client.c b/bin/tests/test_client.c index e26b2e657ea..81b3896e7fe 100644 --- a/bin/tests/test_client.c +++ b/bin/tests/test_client.c @@ -378,16 +378,16 @@ run(void) { connect_cb, NULL, timeout); break; case TCP: - isc_nm_streamdnsconnect(netmgr, &sockaddr_local, - &sockaddr_remote, connect_cb, NULL, - timeout, NULL, NULL, false, NULL); + isc_nm_streamdnsconnect( + netmgr, &sockaddr_local, &sockaddr_remote, connect_cb, + NULL, timeout, 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, false, NULL); + isc_nm_streamdnsconnect( + netmgr, &sockaddr_local, &sockaddr_remote, connect_cb, + NULL, timeout, tls_ctx, NULL, ISC_NM_PROXY_NONE, NULL); break; } #if HAVE_LIBNGHTTP2 diff --git a/bin/tests/test_server.c b/bin/tests/test_server.c index 2dad8cf4f8b..95cf3e0b152 100644 --- a/bin/tests/test_server.c +++ b/bin/tests/test_server.c @@ -248,16 +248,18 @@ run(void) { read_cb, NULL, &sock); break; case TCP: - result = isc_nm_listenstreamdns( - netmgr, ISC_NM_LISTEN_ALL, &sockaddr, read_cb, NULL, - accept_cb, NULL, 0, NULL, NULL, false, &sock); + result = isc_nm_listenstreamdns(netmgr, ISC_NM_LISTEN_ALL, + &sockaddr, read_cb, NULL, + accept_cb, NULL, 0, NULL, NULL, + ISC_NM_PROXY_NONE, &sock); break; case DOT: { isc_tlsctx_createserver(NULL, NULL, &tls_ctx); result = isc_nm_listenstreamdns( netmgr, ISC_NM_LISTEN_ALL, &sockaddr, read_cb, NULL, - accept_cb, NULL, 0, NULL, tls_ctx, false, &sock); + accept_cb, NULL, 0, NULL, tls_ctx, ISC_NM_PROXY_NONE, + &sock); break; } #if HAVE_LIBNGHTTP2 diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 05a864ad42e..603add2ba35 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -1970,9 +1970,10 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) { "connecting from %s to %s, timeout %u", localbuf, peerbuf, resp->timeout); - isc_nm_streamdnsconnect( - disp->mgr->nm, &disp->local, &disp->peer, tcp_connected, - disp, resp->timeout, tlsctx, sess_cache, false, NULL); + isc_nm_streamdnsconnect(disp->mgr->nm, &disp->local, + &disp->peer, tcp_connected, disp, + resp->timeout, tlsctx, sess_cache, + ISC_NM_PROXY_NONE, NULL); break; case DNS_DISPATCHSTATE_CONNECTING: diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index e6058227f7a..18a2f79c3db 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -103,6 +103,20 @@ typedef struct isc_nm_proxyheader_info { * Information to put into the PROXYv2 header when establishing a connection. */ +typedef enum isc_nm_proxy_type { + ISC_NM_PROXY_NONE = 0, + ISC_NM_PROXY_PLAIN = 1, + ISC_NM_PROXY_ENCRYPTED = 2 +} isc_nm_proxy_type_t; +/*%< + * PROXYv2 support type: + * + * - ISC_NM_PROXY_NONE - no PROXY headers are expected; + * - ISC_NM_PROXY_PLAIN - PROXY headers are sent ahead of any encryption, right + * after TCP connection establishment; + * - ISC_NM_PROXY_ENCRYPTED - PROXY headers are sent after TLS handshakes. + */ + void isc_netmgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, isc_nm_t **netgmrp); /*%< @@ -407,7 +421,7 @@ isc_nm_listenstreamdns(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, isc_nm_recv_cb_t recv_cb, void *recv_cbarg, isc_nm_accept_cb_t accept_cb, void *accept_cbarg, int backlog, isc_quota_t *quota, isc_tlsctx_t *tlsctx, - bool proxy, isc_nmsocket_t **sockp); + isc_nm_proxy_type_t proxy_type, isc_nmsocket_t **sockp); /*%< * Start listening for DNS messages over the TCP interface 'iface', using * net manager 'mgr'. @@ -581,9 +595,10 @@ isc_nm_checkaddr(const isc_sockaddr_t *addr, isc_socktype_t type); 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 *sslctx, + unsigned int timeout, isc_tlsctx_t *tlsctx, isc_tlsctx_client_session_cache_t *client_sess_cache, - bool proxy, isc_nm_proxyheader_info_t *proxy_info); + isc_nm_proxy_type_t proxy_type, + isc_nm_proxyheader_info_t *proxy_info); /*%< * Establish a DNS client connection via a TCP or TLS connection, bound to * the address 'local' and connected to the address 'peer'. diff --git a/lib/isc/netmgr/streamdns.c b/lib/isc/netmgr/streamdns.c index 63e680eccc3..9460121e029 100644 --- a/lib/isc/netmgr/streamdns.c +++ b/lib/isc/netmgr/streamdns.c @@ -369,9 +369,10 @@ error: 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 *ctx, + unsigned int timeout, isc_tlsctx_t *tlsctx, isc_tlsctx_client_session_cache_t *client_sess_cache, - bool proxy, isc_nm_proxyheader_info_t *proxy_info) { + isc_nm_proxy_type_t proxy_type, + isc_nm_proxyheader_info_t *proxy_info) { isc_nmsocket_t *nsock = NULL; isc__networker_t *worker = NULL; @@ -390,21 +391,42 @@ isc_nm_streamdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, nsock->connect_cbarg = cbarg; nsock->connect_timeout = timeout; - if (ctx == NULL && !proxy) { - INSIST(client_sess_cache == NULL); - isc_nm_tcpconnect(mgr, local, peer, - streamdns_transport_connected, nsock, - nsock->connect_timeout); - } else if (ctx == NULL && proxy) { - INSIST(client_sess_cache == NULL); + switch (proxy_type) { + case ISC_NM_PROXY_NONE: + if (tlsctx == NULL) { + INSIST(client_sess_cache == NULL); + isc_nm_tcpconnect(mgr, local, peer, + streamdns_transport_connected, nsock, + nsock->connect_timeout); + } else { + isc_nm_tlsconnect( + mgr, local, peer, streamdns_transport_connected, + nsock, tlsctx, client_sess_cache, + nsock->connect_timeout, false, proxy_info); + } + break; + case ISC_NM_PROXY_PLAIN: + if (tlsctx == NULL) { + isc_nm_proxystreamconnect(mgr, local, peer, + streamdns_transport_connected, + nsock, nsock->connect_timeout, + NULL, NULL, proxy_info); + } else { + isc_nm_tlsconnect( + mgr, local, peer, streamdns_transport_connected, + nsock, tlsctx, 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, proxy_info); - } else { - isc_nm_tlsconnect(mgr, local, peer, - streamdns_transport_connected, nsock, ctx, - client_sess_cache, nsock->connect_timeout, - proxy, proxy_info); + nsock->connect_timeout, tlsctx, + client_sess_cache, proxy_info); + break; + default: + UNREACHABLE(); } } @@ -722,8 +744,8 @@ isc_nm_listenstreamdns(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, isc_nm_recv_cb_t recv_cb, void *recv_cbarg, isc_nm_accept_cb_t accept_cb, void *accept_cbarg, int backlog, isc_quota_t *quota, isc_tlsctx_t *tlsctx, - bool proxy, isc_nmsocket_t **sockp) { - isc_result_t result; + isc_nm_proxy_type_t proxy_type, isc_nmsocket_t **sockp) { + isc_result_t result = ISC_R_FAILURE; isc_nmsocket_t *listener = NULL; isc__networker_t *worker = NULL; @@ -743,19 +765,42 @@ isc_nm_listenstreamdns(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, listener->recv_cb = recv_cb; listener->recv_cbarg = recv_cbarg; - if (tlsctx == NULL && !proxy) { - result = isc_nm_listentcp(mgr, workers, iface, - streamdns_accept_cb, listener, - backlog, quota, &listener->outer); - } else if (tlsctx == NULL && proxy) { + switch (proxy_type) { + case ISC_NM_PROXY_NONE: + if (tlsctx == NULL) { + result = isc_nm_listentcp( + mgr, workers, iface, streamdns_accept_cb, + listener, backlog, quota, &listener->outer); + } else { + result = isc_nm_listentls(mgr, workers, iface, + streamdns_accept_cb, listener, + backlog, quota, tlsctx, false, + &listener->outer); + } + break; + case ISC_NM_PROXY_PLAIN: + if (tlsctx == NULL) { + result = isc_nm_listenproxystream( + mgr, workers, iface, streamdns_accept_cb, + listener, backlog, quota, NULL, + &listener->outer); + } else { + result = isc_nm_listentls(mgr, workers, iface, + streamdns_accept_cb, listener, + backlog, quota, tlsctx, true, + &listener->outer); + } + break; + case ISC_NM_PROXY_ENCRYPTED: + INSIST(tlsctx != NULL); result = isc_nm_listenproxystream( mgr, workers, iface, streamdns_accept_cb, listener, - backlog, quota, &listener->outer); - } else { - result = isc_nm_listentls( - mgr, workers, iface, streamdns_accept_cb, listener, - backlog, quota, tlsctx, proxy, &listener->outer); - } + backlog, quota, tlsctx, &listener->outer); + break; + default: + UNREACHABLE(); + }; + if (result != ISC_R_SUCCESS) { listener->closed = true; isc__nmsocket_detach(&listener); diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index 3561acd21db..1e38498bbd4 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -488,7 +488,8 @@ ns_interface_listentcp(ns_interface_t *ifp) { result = isc_nm_listenstreamdns( ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns_client_request, ifp, ns__client_tcpconn, ifp, ifp->mgr->backlog, - &ifp->mgr->sctx->tcpquota, NULL, false, &ifp->tcplistensocket); + &ifp->mgr->sctx->tcpquota, NULL, ISC_NM_PROXY_NONE, + &ifp->tcplistensocket); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "creating TCP socket: %s", @@ -521,7 +522,7 @@ ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) { result = isc_nm_listenstreamdns( ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns_client_request, ifp, ns__client_tcpconn, ifp, ifp->mgr->backlog, - &ifp->mgr->sctx->tcpquota, sslctx, false, + &ifp->mgr->sctx->tcpquota, sslctx, ISC_NM_PROXY_NONE, &ifp->tcplistensocket); if (result != ISC_R_SUCCESS) { diff --git a/tests/dns/dispatch_test.c b/tests/dns/dispatch_test.c index feb4af4b2d5..2516b0b2b0e 100644 --- a/tests/dns/dispatch_test.c +++ b/tests/dns/dispatch_test.c @@ -607,7 +607,7 @@ ISC_LOOP_TEST_IMPL(dispatch_timeout_tcp_response) { /* Server */ result = isc_nm_listenstreamdns( netmgr, ISC_NM_LISTEN_ONE, &tcp_server_addr, noop_nameserver, - NULL, accept_cb, NULL, 0, NULL, NULL, false, &sock); + NULL, accept_cb, NULL, 0, NULL, NULL, ISC_NM_PROXY_NONE, &sock); assert_int_equal(result, ISC_R_SUCCESS); /* ensure we stop listening after the test is done */ @@ -639,7 +639,7 @@ ISC_LOOP_TEST_IMPL(dispatch_tcp_response) { /* Server */ result = isc_nm_listenstreamdns( netmgr, ISC_NM_LISTEN_ONE, &tcp_server_addr, nameserver, NULL, - accept_cb, NULL, 0, NULL, NULL, false, &sock); + accept_cb, NULL, 0, NULL, NULL, ISC_NM_PROXY_NONE, &sock); assert_int_equal(result, ISC_R_SUCCESS); isc_loop_teardown(isc_loop_main(loopmgr), stop_listening, sock); @@ -676,7 +676,8 @@ ISC_LOOP_TEST_IMPL(dispatch_tls_response) { /* Server */ result = isc_nm_listenstreamdns( netmgr, ISC_NM_LISTEN_ONE, &tls_server_addr, nameserver, NULL, - accept_cb, NULL, 0, NULL, tls_listen_tlsctx, false, &sock); + accept_cb, NULL, 0, NULL, tls_listen_tlsctx, ISC_NM_PROXY_NONE, + &sock); assert_int_equal(result, ISC_R_SUCCESS); isc_loop_teardown(isc_loop_main(loopmgr), stop_listening, sock); @@ -782,7 +783,7 @@ ISC_LOOP_TEST_IMPL(dispatch_gettcp) { /* Server */ result = isc_nm_listenstreamdns( netmgr, ISC_NM_LISTEN_ONE, &tcp_server_addr, nameserver, NULL, - accept_cb, NULL, 0, NULL, NULL, false, &sock); + accept_cb, NULL, 0, NULL, NULL, ISC_NM_PROXY_NONE, &sock); assert_int_equal(result, ISC_R_SUCCESS); /* ensure we stop listening after the test is done */ @@ -814,7 +815,7 @@ ISC_LOOP_TEST_IMPL(dispatch_newtcp) { /* Server */ result = isc_nm_listenstreamdns( netmgr, ISC_NM_LISTEN_ONE, &tcp_server_addr, nameserver, NULL, - accept_cb, NULL, 0, NULL, NULL, false, &sock); + accept_cb, NULL, 0, NULL, NULL, ISC_NM_PROXY_NONE, &sock); assert_int_equal(result, ISC_R_SUCCESS); /* ensure we stop listening after the test is done */