]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Stream DNS: add PROXY over TLS support
authorArtem Boldariev <artem@boldariev.com>
Fri, 19 May 2023 11:28:52 +0000 (14:28 +0300)
committerArtem Boldariev <artem@boldariev.com>
Wed, 6 Dec 2023 13:15:25 +0000 (15:15 +0200)
This commit extends Stream DNS with PROXY over TLS support.

bin/delv/delv.c
bin/dig/dighost.c
bin/tests/test_client.c
bin/tests/test_server.c
lib/dns/dispatch.c
lib/isc/include/isc/netmgr.h
lib/isc/netmgr/streamdns.c
lib/ns/interfacemgr.c
tests/dns/dispatch_test.c

index 801965c2f8c51642fe463b3c5c09bb30ada60a8f..25ff05e857c320f740c4da3e3338a5a1f3b09822 100644 (file)
@@ -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);
 
index e494189bb5b4371234f596c6781f5b310c1ab19c..afca0d557e68e8f58d4ee5e844809932ada6a311 100644 (file)
@@ -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;
index e26b2e657ea9755b01900c82cd976468cbcc343c..81b3896e7fe2bcb36bd7d7f8dc297d4728a9d798 100644 (file)
@@ -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
index 2dad8cf4f8bafa538753cf45d165115d03c21f8f..95cf3e0b1527baa127b163cd2e9f1abae43b403b 100644 (file)
@@ -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
index 05a864ad42e7c434a3e15a7d97dfdf6723f4cae9..603add2ba3548a52e3b3fff6ad7be43f06b2127c 100644 (file)
@@ -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:
index e6058227f7acb6c7370d91cabda38d3529002e60..18a2f79c3dba7218c736df19aadc23ecf35e11b6 100644 (file)
@@ -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'.
index 63e680eccc3b23414af085ca29bbd42dd1a1af6c..9460121e0298c35d54396ac673bed98077772424 100644 (file)
@@ -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);
index 3561acd21db022ae7d2eb3a3d5bda59a1d7c2e67..1e38498bbd419fa17aae4ab90c6899f54138ca29 100644 (file)
@@ -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) {
index feb4af4b2d5460438a949d839d20dd67e2239035..2516b0b2b0e2bbccc3b8f1880bfbd57d3c40276a 100644 (file)
@@ -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 */