diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-11-11 21:03:04 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-02-16 18:41:08 +0100 |
commit | 2c42a217a2ef4a62933290f5ef204bcf89ea52fd (patch) | |
tree | d4cd8308585e2480664cf3fb166ad2631bbd9392 /src/resolve/resolved-dns-server.c | |
parent | ccb4072e21f796b95143cd88061c5fad04d01268 (diff) | |
download | systemd-2c42a217a2ef4a62933290f5ef204bcf89ea52fd.tar.gz |
resolved: when we can't parse a packet, downgrade feature level
So far we didn't really handle the case where we can't parse a reply
packet. Since this apparently happens in real-life though, let's add
some minimal logic, to downgrade/restart if we see this.
Diffstat (limited to 'src/resolve/resolved-dns-server.c')
-rw-r--r-- | src/resolve/resolved-dns-server.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 40da80b39a..70bb7178dd 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -240,6 +240,7 @@ static void dns_server_reset_counters(DnsServer *s) { s->n_failed_tcp = 0; s->n_failed_tls = 0; s->packet_truncated = false; + s->packet_invalid = false; s->verified_usec = 0; /* Note that we do not reset s->packet_bad_opt and s->packet_rrsig_missing here. We reset them only when the @@ -366,6 +367,17 @@ void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", strna(dns_server_string_full(s))); } +void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level) { + assert(s); + + /* Invoked whenever we got a packet we couldn't parse at all */ + + if (s->possible_feature_level != level) + return; + + s->packet_invalid = true; +} + static bool dns_server_grace_period_expired(DnsServer *s) { usec_t ts; @@ -442,6 +454,22 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) { log_debug("Server doesn't support DNS-over-TLS, downgrading protocol..."); s->possible_feature_level--; + + } else if (s->packet_invalid && + s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP && + s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN) { + + /* Downgrade from DO to EDNS0 + from EDNS0 to UDP, from TLS+DO to plain TLS. Or in + * other words, if we receive a packet we cannot parse jump to the next lower feature + * level that actually has an influence on the packet layout (and not just the + * transport). */ + + log_debug("Got invalid packet from server, downgrading protocol..."); + s->possible_feature_level = + s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TLS_DO ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : + DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_EDNS0 : + DNS_SERVER_FEATURE_LEVEL_UDP; + } else if (s->packet_bad_opt && s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) { @@ -903,13 +931,15 @@ void dns_server_dump(DnsServer *s, FILE *f) { "\tFailed TCP attempts: %u\n" "\tSeen truncated packet: %s\n" "\tSeen OPT RR getting lost: %s\n" - "\tSeen RRSIG RR missing: %s\n", + "\tSeen RRSIG RR missing: %s\n" + "\tSeen invalid packet: %s\n", s->received_udp_packet_max, s->n_failed_udp, s->n_failed_tcp, yes_no(s->packet_truncated), yes_no(s->packet_bad_opt), - yes_no(s->packet_rrsig_missing)); + yes_no(s->packet_rrsig_missing), + yes_no(s->packet_invalid)); } void dns_server_unref_stream(DnsServer *s) { |