]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add PROXY support to Stream DNS
authorArtem Boldariev <artem@boldariev.com>
Tue, 9 May 2023 12:13:05 +0000 (15:13 +0300)
committerArtem Boldariev <artem@boldariev.com>
Wed, 6 Dec 2023 13:15:24 +0000 (15:15 +0200)
This commit makes it possible to use Stream DNS on top of PROXY Stream
either directly or indirectly (in the case when TLS is involved).

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
tests/isc/tcpdns_test.c
tests/isc/tlsdns_test.c

index 23166be3a9db21d2177f28ab29bec8a38a9c29e0..801965c2f8c51642fe463b3c5c09bb30ada60a8f 100644 (file)
@@ -2184,7 +2184,7 @@ run_server(void *arg) {
 
        CHECK(isc_nm_listenstreamdns(netmgr, ISC_NM_LISTEN_ONE, &addr,
                                     ns_client_request, ifp, accept_cb, ifp, 10,
-                                    NULL, NULL, &ifp->tcplistensocket));
+                                    NULL, NULL, false, &ifp->tcplistensocket));
        ifp->flags |= NS_INTERFACEFLAG_LISTENING;
        isc_async_current(loopmgr, sendquery, ifp->tcplistensocket);
 
index 17c4e388d5c23512d8627f772e654b26f9576cf0..5a7664cde3bea1cee532035fd052fbcbf715c7e2 100644 (file)
@@ -3024,7 +3024,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, sess_cache,
+                                       false, NULL);
 #if HAVE_LIBNGHTTP2
        } else if (query->lookup->https_mode) {
                char uri[4096] = { 0 };
@@ -3049,7 +3050,7 @@ start_tcp(dig_query_t *query) {
        } else {
                isc_nm_streamdnsconnect(netmgr, &localaddr, &query->sockaddr,
                                        tcp_connected, connectquery,
-                                       local_timeout, NULL, NULL);
+                                       local_timeout, NULL, NULL, false, NULL);
        }
 
        return;
index 872651cd69768a2172914b0d1fd9006f5864987e..f32fa6770e48469435639aa0f52555b8291c3bd4 100644 (file)
@@ -380,14 +380,14 @@ run(void) {
        case TCP:
                isc_nm_streamdnsconnect(netmgr, &sockaddr_local,
                                        &sockaddr_remote, connect_cb, NULL,
-                                       timeout, NULL, NULL);
+                                       timeout, NULL, NULL, false, NULL);
                break;
        case DOT: {
                isc_tlsctx_createclient(&tls_ctx);
 
                isc_nm_streamdnsconnect(netmgr, &sockaddr_local,
                                        &sockaddr_remote, connect_cb, NULL,
-                                       timeout, tls_ctx, NULL);
+                                       timeout, tls_ctx, NULL, false, NULL);
                break;
        }
 #if HAVE_LIBNGHTTP2
index 6186a7a2a08e3e2b18fd2f6c3363a2e8bb073542..1a78534b37d852b89adb16b36a542af58efeeb2b 100644 (file)
@@ -250,14 +250,14 @@ run(void) {
        case TCP:
                result = isc_nm_listenstreamdns(
                        netmgr, ISC_NM_LISTEN_ALL, &sockaddr, read_cb, NULL,
-                       accept_cb, NULL, 0, NULL, NULL, &sock);
+                       accept_cb, NULL, 0, NULL, NULL, false, &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, &sock);
+                       accept_cb, NULL, 0, NULL, tls_ctx, false, &sock);
                break;
        }
 #if HAVE_LIBNGHTTP2
index b68692fbb918e3747bad0b1f3ccfbcd6176220fe..05a864ad42e7c434a3e15a7d97dfdf6723f4cae9 100644 (file)
@@ -1970,9 +1970,9 @@ 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);
+               isc_nm_streamdnsconnect(
+                       disp->mgr->nm, &disp->local, &disp->peer, tcp_connected,
+                       disp, resp->timeout, tlsctx, sess_cache, false, NULL);
                break;
 
        case DNS_DISPATCHSTATE_CONNECTING:
index cd47e77243bfc115f001319f190279e39fe3e23e..1bbdb522594a04c0b3451803ff56ab50affc4d27 100644 (file)
@@ -407,7 +407,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,
-                      isc_nmsocket_t **sockp);
+                      bool proxy, isc_nmsocket_t **sockp);
 /*%<
  * Start listening for DNS messages over the TCP interface 'iface', using
  * net manager 'mgr'.
@@ -427,6 +427,9 @@ isc_nm_listenstreamdns(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface,
  * Passing a non-NULL value as 'tlsctx' instructs the underlying code
  * to create a DNS over TLS listener.
  *
+ * Passing 'proxy == true' instruct the code that a PROXY header is
+ * sent before any data after the connection is accepted.
+ *
  * 'quota' is passed to isc_nm_listentcp() when opening the raw TCP socket.
  */
 
@@ -574,7 +577,8 @@ 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,
-                       isc_tlsctx_client_session_cache_t *client_sess_cache);
+                       isc_tlsctx_client_session_cache_t *client_sess_cache,
+                       bool proxy, 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 3199cd61feed716fc1822781a28243615802a58f..63e680eccc3b23414af085ca29bbd42dd1a1af6c 100644 (file)
@@ -370,7 +370,8 @@ 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,
-                       isc_tlsctx_client_session_cache_t *client_sess_cache) {
+                       isc_tlsctx_client_session_cache_t *client_sess_cache,
+                       bool proxy, isc_nm_proxyheader_info_t *proxy_info) {
        isc_nmsocket_t *nsock = NULL;
        isc__networker_t *worker = NULL;
 
@@ -389,16 +390,21 @@ isc_nm_streamdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local,
        nsock->connect_cbarg = cbarg;
        nsock->connect_timeout = timeout;
 
-       if (ctx == NULL) {
+       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);
+               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,
-                                 false, NULL);
+                                 proxy, proxy_info);
        }
 }
 
@@ -716,7 +722,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,
-                      isc_nmsocket_t **sockp) {
+                      bool proxy, isc_nmsocket_t **sockp) {
        isc_result_t result;
        isc_nmsocket_t *listener = NULL;
        isc__networker_t *worker = NULL;
@@ -737,14 +743,18 @@ 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) {
+       if (tlsctx == NULL && !proxy) {
                result = isc_nm_listentcp(mgr, workers, iface,
                                          streamdns_accept_cb, listener,
                                          backlog, quota, &listener->outer);
+       } else if (tlsctx == NULL && proxy) {
+               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, false, &listener->outer);
+                       backlog, quota, tlsctx, proxy, &listener->outer);
        }
        if (result != ISC_R_SUCCESS) {
                listener->closed = true;
@@ -789,12 +799,14 @@ isc__nm_streamdns_cleanup_data(isc_nmsocket_t *sock) {
                break;
        case isc_nm_tlslistener:
        case isc_nm_tcplistener:
+       case isc_nm_proxystreamlistener:
                if (sock->streamdns.listener != NULL) {
                        isc__nmsocket_detach(&sock->streamdns.listener);
                }
                break;
        case isc_nm_tlssocket:
        case isc_nm_tcpsocket:
+       case isc_nm_proxystreamsocket:
                if (sock->streamdns.sock != NULL) {
                        isc__nmsocket_detach(&sock->streamdns.sock);
                }
index e6dc3579b82243dd54971ca35ece17e94f5f1d95..6524702095eab09d2d6d06824c3240f3f2d7a406 100644 (file)
@@ -488,7 +488,7 @@ 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, &ifp->tcplistensocket);
+               &ifp->mgr->sctx->tcpquota, NULL, false, &ifp->tcplistensocket);
        if (result != ISC_R_SUCCESS) {
                isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
                              "creating TCP socket: %s",
@@ -521,7 +521,8 @@ 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, &ifp->tcplistensocket);
+               &ifp->mgr->sctx->tcpquota, sslctx, false,
+               &ifp->tcplistensocket);
 
        if (result != ISC_R_SUCCESS) {
                isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
index 470c167286989c567052975cf41193ace29f2b31..feb4af4b2d5460438a949d839d20dd67e2239035 100644 (file)
@@ -605,9 +605,9 @@ ISC_LOOP_TEST_IMPL(dispatch_timeout_tcp_response) {
        *test = (test_dispatch_t){ 0 };
 
        /* Server */
-       result = isc_nm_listenstreamdns(netmgr, ISC_NM_LISTEN_ONE,
-                                       &tcp_server_addr, noop_nameserver, NULL,
-                                       accept_cb, NULL, 0, NULL, NULL, &sock);
+       result = isc_nm_listenstreamdns(
+               netmgr, ISC_NM_LISTEN_ONE, &tcp_server_addr, noop_nameserver,
+               NULL, accept_cb, NULL, 0, NULL, NULL, false, &sock);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        /* ensure we stop listening after the test is done */
@@ -637,9 +637,9 @@ ISC_LOOP_TEST_IMPL(dispatch_tcp_response) {
        *test = (test_dispatch_t){ 0 };
 
        /* Server */
-       result = isc_nm_listenstreamdns(netmgr, ISC_NM_LISTEN_ONE,
-                                       &tcp_server_addr, nameserver, NULL,
-                                       accept_cb, NULL, 0, NULL, NULL, &sock);
+       result = isc_nm_listenstreamdns(
+               netmgr, ISC_NM_LISTEN_ONE, &tcp_server_addr, nameserver, NULL,
+               accept_cb, NULL, 0, NULL, NULL, false, &sock);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        isc_loop_teardown(isc_loop_main(loopmgr), stop_listening, sock);
@@ -676,7 +676,7 @@ 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, &sock);
+               accept_cb, NULL, 0, NULL, tls_listen_tlsctx, false, &sock);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        isc_loop_teardown(isc_loop_main(loopmgr), stop_listening, sock);
@@ -780,9 +780,9 @@ ISC_LOOP_TEST_IMPL(dispatch_gettcp) {
        *test = (test_dispatch_t){ 0 };
 
        /* Server */
-       result = isc_nm_listenstreamdns(netmgr, ISC_NM_LISTEN_ONE,
-                                       &tcp_server_addr, nameserver, NULL,
-                                       accept_cb, NULL, 0, NULL, NULL, &sock);
+       result = isc_nm_listenstreamdns(
+               netmgr, ISC_NM_LISTEN_ONE, &tcp_server_addr, nameserver, NULL,
+               accept_cb, NULL, 0, NULL, NULL, false, &sock);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        /* ensure we stop listening after the test is done */
@@ -812,9 +812,9 @@ ISC_LOOP_TEST_IMPL(dispatch_newtcp) {
        *test = (test_dispatch_t){ 0 };
 
        /* Server */
-       result = isc_nm_listenstreamdns(netmgr, ISC_NM_LISTEN_ONE,
-                                       &tcp_server_addr, nameserver, NULL,
-                                       accept_cb, NULL, 0, NULL, NULL, &sock);
+       result = isc_nm_listenstreamdns(
+               netmgr, ISC_NM_LISTEN_ONE, &tcp_server_addr, nameserver, NULL,
+               accept_cb, NULL, 0, NULL, NULL, false, &sock);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        /* ensure we stop listening after the test is done */
index 058f10172728618d283be204b76c862a3f163be6..93b15839deb0916dd63dd2c4569049c8aff8b4b2 100644 (file)
@@ -53,7 +53,7 @@ start_listening(uint32_t nworkers, isc_nm_accept_cb_t accept_cb,
                isc_nm_recv_cb_t recv_cb) {
        isc_result_t result = isc_nm_listenstreamdns(
                listen_nm, nworkers, &tcp_listen_addr, recv_cb, NULL, accept_cb,
-               NULL, 128, NULL, NULL, &listen_sock);
+               NULL, 128, NULL, NULL, stream_use_PROXY, &listen_sock);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        isc_loop_teardown(mainloop, stop_listening, listen_sock);
@@ -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);
+                               NULL, NULL, stream_use_PROXY, 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);
+                               NULL, NULL, stream_use_PROXY, 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);
+                               NULL, NULL, stream_use_PROXY, NULL);
 }
 
 ISC_LOOP_TEST_IMPL(tcpdns_timeout_recovery) {
index 1e02b0a48342a89509b4c1e59177f083585bba2a..d238c831c166e33a5b7a6952c88e9ebb5eca7a3f 100644 (file)
@@ -52,7 +52,8 @@ start_listening(uint32_t nworkers, isc_nm_accept_cb_t accept_cb,
                isc_nm_recv_cb_t recv_cb) {
        isc_result_t result = isc_nm_listenstreamdns(
                listen_nm, nworkers, &tcp_listen_addr, recv_cb, NULL, accept_cb,
-               NULL, 128, NULL, tcp_listen_tlsctx, &listen_sock);
+               NULL, 128, NULL, tcp_listen_tlsctx, stream_use_PROXY,
+               &listen_sock);
        assert_int_equal(result, ISC_R_SUCCESS);
 
        isc_loop_teardown(mainloop, stop_listening, listen_sock);
@@ -60,10 +61,10 @@ start_listening(uint32_t nworkers, isc_nm_accept_cb_t accept_cb,
 
 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,
-                               tcp_tlsctx_client_sess_cache);
+       isc_nm_streamdnsconnect(
+               nm, &tcp_connect_addr, &tcp_listen_addr, connect_connect_cb,
+               tlsdns_connect, T_CONNECT, tcp_connect_tlsctx,
+               tcp_tlsctx_client_sess_cache, stream_use_PROXY, NULL);
 }
 
 ISC_LOOP_TEST_IMPL(tlsdns_noop) {
@@ -74,7 +75,8 @@ ISC_LOOP_TEST_IMPL(tlsdns_noop) {
        isc_nm_streamdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
                                connect_success_cb, tlsdns_connect, T_CONNECT,
                                tcp_connect_tlsctx,
-                               tcp_tlsctx_client_sess_cache);
+                               tcp_tlsctx_client_sess_cache, stream_use_PROXY,
+                               NULL);
 }
 
 ISC_LOOP_TEST_IMPL(tlsdns_noresponse) {
@@ -84,7 +86,8 @@ ISC_LOOP_TEST_IMPL(tlsdns_noresponse) {
        isc_nm_streamdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
                                connect_connect_cb, tlsdns_connect, T_CONNECT,
                                tcp_connect_tlsctx,
-                               tcp_tlsctx_client_sess_cache);
+                               tcp_tlsctx_client_sess_cache, stream_use_PROXY,
+                               NULL);
 }
 
 ISC_LOOP_TEST_IMPL(tlsdns_timeout_recovery) {
@@ -103,10 +106,10 @@ ISC_LOOP_TEST_IMPL(tlsdns_timeout_recovery) {
        connect_readcb = timeout_retry_cb;
        isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
        isc_refcount_increment0(&active_cconnects);
-       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);
+       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, stream_use_PROXY, NULL);
 }
 
 ISC_LOOP_TEST_IMPL(tlsdns_recv_one) {