resolved: lower connection timeout for DoT connections in opportunistic mode

Fixes: #20801
This commit is contained in:
Lennart Poettering
2021-11-22 22:33:40 +01:00
parent e2ef1e9aea
commit e1158539e7
5 changed files with 38 additions and 12 deletions
+4 -4
View 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;
+13 -1
View 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
+10 -5
View 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");
+10 -1
View 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;
+1 -1
View 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;