summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-11-22 18:32:57 +0100
committerLennart Poettering <lennart@poettering.net>2021-11-22 22:33:40 +0100
commite1158539e70310a7bb39d5a0c3411932f5caa6d0 (patch)
tree296a3a8b6f785e35bcc628e1eca2a99e9e6ffba0
parente2ef1e9aea24d89d1e92fa4675ddc330029b48bf (diff)
downloadsystemd-e1158539e70310a7bb39d5a0c3411932f5caa6d0.tar.gz
resolved: lower connection timeout for DoT connections in opportunistic mode
Fixes: #20801
-rw-r--r--src/resolve/resolved-dns-stream.c8
-rw-r--r--src/resolve/resolved-dns-stream.h14
-rw-r--r--src/resolve/resolved-dns-stub.c15
-rw-r--r--src/resolve/resolved-dns-transaction.c11
-rw-r--r--src/resolve/resolved-llmnr.c2
5 files changed, 38 insertions, 12 deletions
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
index 3e6505cd75..719f6219bf 100644
--- a/src/resolve/resolved-dns-stream.c
+++ b/src/resolve/resolved-dns-stream.c
@@ -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;
diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h
index 470d446ddb..96b977f628 100644
--- a/src/resolve/resolved-dns-stream.h
+++ b/src/resolve/resolved-dns-stream.h
@@ -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
diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c
index 09fd7d2418..73590e3f9b 100644
--- a/src/resolve/resolved-dns-stub.c
+++ b/src/resolve/resolved-dns-stub.c
@@ -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");
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 594ce5e27b..0cf9912712 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -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;
diff --git a/src/resolve/resolved-llmnr.c b/src/resolve/resolved-llmnr.c
index ce2db7d4b0..32483006b1 100644
--- a/src/resolve/resolved-llmnr.c
+++ b/src/resolve/resolved-llmnr.c
@@ -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;