]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: lower connection timeout for DoT connections in opportunistic mode 21470/head
authorLennart Poettering <lennart@poettering.net>
Mon, 22 Nov 2021 17:32:57 +0000 (18:32 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 22 Nov 2021 21:33:40 +0000 (22:33 +0100)
Fixes: #20801
src/resolve/resolved-dns-stream.c
src/resolve/resolved-dns-stream.h
src/resolve/resolved-dns-stub.c
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-llmnr.c

index 3e6505cd75b879c00ffcbd33526d43fd2ac82f62..719f6219bf01de395c1a7d907c9127328ffa759c 100644 (file)
@@ -10,7 +10,6 @@
 #include "resolved-dns-stream.h"
 #include "resolved-manager.h"
 
-#define DNS_STREAM_TIMEOUT_USEC (10 * USEC_PER_SEC)
 #define DNS_STREAMS_MAX 128
 
 #define DNS_QUERIES_PER_STREAM 32
@@ -437,7 +436,7 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
 
         /* If we did something, let's restart the timeout event source */
         if (progressed && s->timeout_event_source) {
-                r = sd_event_source_set_time_relative(s->timeout_event_source, DNS_STREAM_TIMEOUT_USEC);
+                r = sd_event_source_set_time_relative(s->timeout_event_source, DNS_STREAM_ESTABLISHED_TIMEOUT_USEC);
                 if (r < 0)
                         log_warning_errno(errno, "Couldn't restart TCP connection timeout, ignoring: %m");
         }
@@ -482,7 +481,8 @@ int dns_stream_new(
                 DnsStreamType type,
                 DnsProtocol protocol,
                 int fd,
-                const union sockaddr_union *tfo_address) {
+                const union sockaddr_union *tfo_address,
+                usec_t connect_timeout_usec) {
 
         _cleanup_(dns_stream_unrefp) DnsStream *s = NULL;
         int r;
@@ -523,7 +523,7 @@ int dns_stream_new(
                         m->event,
                         &s->timeout_event_source,
                         clock_boottime_or_monotonic(),
-                        DNS_STREAM_TIMEOUT_USEC, 0,
+                        connect_timeout_usec, 0,
                         on_stream_timeout, s);
         if (r < 0)
                 return r;
index 470d446ddbb295cd4a4b23df753a83b7f85259cf..96b977f62808831aaef9c26f4baa3a14712adc9a 100644 (file)
@@ -15,6 +15,18 @@ typedef struct DnsStubListenerExtra DnsStubListenerExtra;
 #include "resolved-dns-packet.h"
 #include "resolved-dnstls.h"
 
+/* Various timeouts for establishing TCP connections. First the default time-out for that. */
+#define DNS_STREAM_DEFAULT_TIMEOUT_USEC (10 * USEC_PER_SEC)
+
+/* In the DNS stub, be more friendly for incoming connections, than we are to ourselves for outgoing ones */
+#define DNS_STREAM_STUB_TIMEOUT_USEC (30 * USEC_PER_SEC)
+
+/* In opportunistic TLS mode, lower timeouts */
+#define DNS_STREAM_OPPORTUNISTIC_TLS_TIMEOUT_USEC (3 * USEC_PER_SEC)
+
+/* Once connections are established apply this timeout once nothing happens anymore */
+#define DNS_STREAM_ESTABLISHED_TIMEOUT_USEC (10 * USEC_PER_SEC)
+
 typedef enum DnsStreamType {
         DNS_STREAM_LOOKUP,        /* Outgoing connection to a classic DNS server */
         DNS_STREAM_LLMNR_SEND,    /* Outgoing LLMNR TCP lookup */
@@ -81,7 +93,7 @@ struct DnsStream {
         LIST_FIELDS(DnsStream, streams);
 };
 
-int dns_stream_new(Manager *m, DnsStream **s, DnsStreamType type, DnsProtocol protocol, int fd, const union sockaddr_union *tfo_address);
+int dns_stream_new(Manager *m, DnsStream **s, DnsStreamType type, DnsProtocol protocol, int fd, const union sockaddr_union *tfo_address, usec_t timeout);
 #if ENABLE_DNS_OVER_TLS
 int dns_stream_connect_tls(DnsStream *s, void *tls_session);
 #endif
index 09fd7d2418e18e3fb3b9d236b92b44b4912f4ab1..73590e3f9bddef82e6456034471e07fb9ed9e577 100644 (file)
@@ -950,10 +950,8 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
                 _cleanup_free_ char *dipa = NULL;
 
                 r = in_addr_to_string(p->family, &p->destination, &dipa);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to format destination address: %m");
-                        return;
-                }
+                if (r < 0)
+                        return (void) log_error_errno(r, "Failed to format destination address: %m");
 
                 log_debug("Got request to DNS proxy address 127.0.0.54, enabling bypass logic.");
                 bypass = true;
@@ -1076,7 +1074,7 @@ static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t reve
                 return -errno;
         }
 
-        r = dns_stream_new(m, &stream, DNS_STREAM_STUB, DNS_PROTOCOL_DNS, cfd, NULL);
+        r = dns_stream_new(m, &stream, DNS_STREAM_STUB, DNS_PROTOCOL_DNS, cfd, NULL, DNS_STREAM_STUB_TIMEOUT_USEC);
         if (r < 0) {
                 safe_close(cfd);
                 return r;
@@ -1150,6 +1148,9 @@ static int manager_dns_stub_fd(
         union sockaddr_union sa;
         int r;
 
+        assert(m);
+        assert(listen_addr);
+
         if (type == SOCK_DGRAM)
                 event_source = address_is_proxy(family, listen_addr) ? &m->dns_proxy_stub_udp_event_source : &m->dns_stub_udp_event_source;
         else if (type == SOCK_STREAM)
@@ -1188,6 +1189,10 @@ static int manager_dns_stub_fd(
                 if (r < 0)
                         return r;
         } else if (type == SOCK_DGRAM) {
+                /* Turn off Path MTU Discovery for UDP, for security reasons. See socket_disable_pmtud() for
+                 * a longer discussion. (We only do this for sockets that are potentially externally
+                 * accessible, i.e. the proxy stub one. For the non-proxy one we instead set the TTL to 1,
+                 * see above, so that packets don't get routed at all.) */
                 r = socket_disable_pmtud(fd, family);
                 if (r < 0)
                         log_debug_errno(r, "Failed to disable UDP PMTUD, ignoring: %m");
index 594ce5e27b9e877576076dbd56cef24667c2ceb4..0cf99127124859ec3cbf2dbe2e448cd977b24d49 100644 (file)
@@ -673,6 +673,7 @@ static uint16_t dns_transaction_port(DnsTransaction *t) {
 }
 
 static int dns_transaction_emit_tcp(DnsTransaction *t) {
+        usec_t stream_timeout_usec = DNS_STREAM_DEFAULT_TIMEOUT_USEC;
         _cleanup_(dns_stream_unrefp) DnsStream *s = NULL;
         _cleanup_close_ int fd = -1;
         union sockaddr_union sa;
@@ -708,6 +709,14 @@ static int dns_transaction_emit_tcp(DnsTransaction *t) {
                 else
                         fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, dns_transaction_port(t), &sa);
 
+                /* Lower timeout in DNS-over-TLS opportunistic mode. In environments where DoT is blocked
+                 * without ICMP response overly long delays when contacting DoT servers are nasty, in
+                 * particular if multiple DNS servers are defined which we try in turn and all are
+                 * blocked. Hence, substantially lower the timeout in that case. */
+                if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) &&
+                    dns_server_get_dns_over_tls_mode(t->server) == DNS_OVER_TLS_OPPORTUNISTIC)
+                        stream_timeout_usec = DNS_STREAM_OPPORTUNISTIC_TLS_TIMEOUT_USEC;
+
                 type = DNS_STREAM_LOOKUP;
                 break;
 
@@ -745,7 +754,7 @@ static int dns_transaction_emit_tcp(DnsTransaction *t) {
                 if (fd < 0)
                         return fd;
 
-                r = dns_stream_new(t->scope->manager, &s, type, t->scope->protocol, fd, &sa);
+                r = dns_stream_new(t->scope->manager, &s, type, t->scope->protocol, fd, &sa, stream_timeout_usec);
                 if (r < 0)
                         return r;
 
index ce2db7d4b02fe17f3552781b55caa84ec41a03be..32483006b1e8639eb3ded36586d2d808979227cb 100644 (file)
@@ -313,7 +313,7 @@ static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *u
                 return -errno;
         }
 
-        r = dns_stream_new(m, &stream, DNS_STREAM_LLMNR_RECV, DNS_PROTOCOL_LLMNR, cfd, NULL);
+        r = dns_stream_new(m, &stream, DNS_STREAM_LLMNR_RECV, DNS_PROTOCOL_LLMNR, cfd, NULL, DNS_STREAM_DEFAULT_TIMEOUT_USEC);
         if (r < 0) {
                 safe_close(cfd);
                 return r;