mirror of
https://github.com/systemd/systemd.git
synced 2024-10-31 16:21:26 +03:00
resolved: in DNSSEC permissive mode, check if DO bit wasn't copied from request to response
If the server doesn't copy the DO bit from request to response, this is a very early and easy indication that it doesn#t support DNSSEC properly. Hence, let's immediately downgrade to non-DNSSEC mode if we see this – if permissive mode is on and this is allowed.
This commit is contained in:
parent
0761da386a
commit
d96275d8eb
@ -378,6 +378,17 @@ void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level) {
|
|||||||
s->packet_invalid = true;
|
s->packet_invalid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dns_server_packet_do_off(DnsServer *s, DnsServerFeatureLevel level) {
|
||||||
|
assert(s);
|
||||||
|
|
||||||
|
/* Invoked whenever the DO flag was not copied from our request to the response. */
|
||||||
|
|
||||||
|
if (s->possible_feature_level != level)
|
||||||
|
return;
|
||||||
|
|
||||||
|
s->packet_do_off = true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool dns_server_grace_period_expired(DnsServer *s) {
|
static bool dns_server_grace_period_expired(DnsServer *s) {
|
||||||
usec_t ts;
|
usec_t ts;
|
||||||
|
|
||||||
@ -494,6 +505,17 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
|
|||||||
* when we can't use EDNS because the DNS server doesn't support it. */
|
* when we can't use EDNS because the DNS server doesn't support it. */
|
||||||
log_level = LOG_NOTICE;
|
log_level = LOG_NOTICE;
|
||||||
|
|
||||||
|
} else if (s->packet_do_off &&
|
||||||
|
DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) &&
|
||||||
|
dns_server_get_dnssec_mode(s) != DNSSEC_YES) {
|
||||||
|
|
||||||
|
/* The server didn't copy the DO bit from request to response, thus DNSSEC is not
|
||||||
|
* correctly implemented, let's downgrade if that's allowed. */
|
||||||
|
|
||||||
|
log_debug("Detected server didn't copy DO flag from request to response, downgrading feature level...");
|
||||||
|
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
|
||||||
|
DNS_SERVER_FEATURE_LEVEL_EDNS0;
|
||||||
|
|
||||||
} else if (s->packet_rrsig_missing &&
|
} else if (s->packet_rrsig_missing &&
|
||||||
DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) &&
|
DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) &&
|
||||||
dns_server_get_dnssec_mode(s) != DNSSEC_YES) {
|
dns_server_get_dnssec_mode(s) != DNSSEC_YES) {
|
||||||
@ -653,6 +675,9 @@ bool dns_server_dnssec_supported(DnsServer *server) {
|
|||||||
if (server->packet_rrsig_missing)
|
if (server->packet_rrsig_missing)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (server->packet_do_off)
|
||||||
|
return false;
|
||||||
|
|
||||||
/* DNSSEC servers need to support TCP properly (see RFC5966), if they don't, we assume DNSSEC is borked too */
|
/* DNSSEC servers need to support TCP properly (see RFC5966), if they don't, we assume DNSSEC is borked too */
|
||||||
if (server->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS)
|
if (server->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS)
|
||||||
return false;
|
return false;
|
||||||
@ -898,6 +923,7 @@ void dns_server_reset_features(DnsServer *s) {
|
|||||||
|
|
||||||
s->packet_bad_opt = false;
|
s->packet_bad_opt = false;
|
||||||
s->packet_rrsig_missing = false;
|
s->packet_rrsig_missing = false;
|
||||||
|
s->packet_do_off = false;
|
||||||
|
|
||||||
s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC;
|
s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC;
|
||||||
|
|
||||||
@ -959,14 +985,16 @@ void dns_server_dump(DnsServer *s, FILE *f) {
|
|||||||
"\tSeen truncated packet: %s\n"
|
"\tSeen truncated packet: %s\n"
|
||||||
"\tSeen OPT RR getting lost: %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",
|
"\tSeen invalid packet: %s\n"
|
||||||
|
"\tServer dropped DO flag: %s\n",
|
||||||
s->received_udp_packet_max,
|
s->received_udp_packet_max,
|
||||||
s->n_failed_udp,
|
s->n_failed_udp,
|
||||||
s->n_failed_tcp,
|
s->n_failed_tcp,
|
||||||
yes_no(s->packet_truncated),
|
yes_no(s->packet_truncated),
|
||||||
yes_no(s->packet_bad_opt),
|
yes_no(s->packet_bad_opt),
|
||||||
yes_no(s->packet_rrsig_missing),
|
yes_no(s->packet_rrsig_missing),
|
||||||
yes_no(s->packet_invalid));
|
yes_no(s->packet_invalid),
|
||||||
|
yes_no(s->packet_do_off));
|
||||||
}
|
}
|
||||||
|
|
||||||
void dns_server_unref_stream(DnsServer *s) {
|
void dns_server_unref_stream(DnsServer *s) {
|
||||||
|
@ -85,6 +85,7 @@ struct DnsServer {
|
|||||||
bool packet_bad_opt:1; /* Set when OPT was missing or otherwise bad on reply */
|
bool packet_bad_opt:1; /* Set when OPT was missing or otherwise bad on reply */
|
||||||
bool packet_rrsig_missing:1; /* Set when RRSIG was missing */
|
bool packet_rrsig_missing:1; /* Set when RRSIG was missing */
|
||||||
bool packet_invalid:1; /* Set when we failed to parse a reply */
|
bool packet_invalid:1; /* Set when we failed to parse a reply */
|
||||||
|
bool packet_do_off:1; /* Set when the server didn't copy DNSSEC DO flag from request to response */
|
||||||
|
|
||||||
usec_t verified_usec;
|
usec_t verified_usec;
|
||||||
usec_t features_grace_period_usec;
|
usec_t features_grace_period_usec;
|
||||||
@ -124,6 +125,7 @@ void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level);
|
|||||||
void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level);
|
void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level);
|
||||||
void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level);
|
void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level);
|
||||||
void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level);
|
void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level);
|
||||||
|
void dns_server_packet_do_off(DnsServer *s, DnsServerFeatureLevel level);
|
||||||
|
|
||||||
DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s);
|
DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s);
|
||||||
|
|
||||||
|
@ -1279,6 +1279,10 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
|
|||||||
if (!p->opt)
|
if (!p->opt)
|
||||||
dns_server_packet_bad_opt(t->server, t->current_feature_level);
|
dns_server_packet_bad_opt(t->server, t->current_feature_level);
|
||||||
|
|
||||||
|
/* Report that the server didn't copy our query DO bit from request to response */
|
||||||
|
if (DNS_PACKET_DO(t->sent) && !DNS_PACKET_DO(t->received))
|
||||||
|
dns_server_packet_do_off(t->server, t->current_feature_level);
|
||||||
|
|
||||||
/* Report that we successfully received a packet */
|
/* Report that we successfully received a packet */
|
||||||
dns_server_packet_received(t->server, p->ipproto, t->current_feature_level, p->size);
|
dns_server_packet_received(t->server, p->ipproto, t->current_feature_level, p->size);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user