Grease EDNS version response

This commit is contained in:
Mark Andrews
2025-03-11 11:37:20 +11:00
parent 6bf9957950
commit 7d7233dbce
+72 -3
View File
@@ -1042,6 +1042,17 @@ ns_client_addopt(ns_client_t *client, dns_message_t *message,
unsigned char expire[4];
unsigned char advtimo[2];
dns_aclenv_t *env = NULL;
unsigned char version = 0;
unsigned int grease_rate = 0;
time_t grease_until = 0;
bool grease_response_edns_flags = false;
bool grease_response_edns_option = false;
bool grease_response_edns_version = false;
uint32_t grease_edns_known_flags = ~0;
time_t tnow = time(NULL);
#define GREASE \
(grease_rate > 0 ? (grease_rate >= isc_random_uniform(99) + 1) : false)
REQUIRE(NS_CLIENT_VALID(client));
REQUIRE(opt != NULL && *opt == NULL);
@@ -1049,6 +1060,38 @@ ns_client_addopt(ns_client_t *client, dns_message_t *message,
env = client->manager->aclenv;
view = client->view;
/*
* Grease normal QUERY responses.
*/
if (view != NULL && message->opcode == dns_opcode_query &&
(message->rcode == dns_rcode_noerror ||
message->rcode == dns_rcode_nxdomain))
{
dns_peer_t *peer = NULL;
isc_netaddr_t srcip;
grease_rate = view->grease_rate;
grease_until = view->grease_until;
grease_edns_known_flags = view->grease_edns_known_flags;
grease_response_edns_flags = view->grease_response_edns_flags;
grease_response_edns_option = view->grease_response_edns_option;
grease_response_edns_version =
view->grease_response_edns_version;
isc_netaddr_fromsockaddr(&srcip, &client->peeraddr);
result = dns_peerlist_peerbyaddr(view->peers, &srcip, &peer);
if (result == ISC_R_SUCCESS && peer != NULL) {
dns_peer_getrespednsflags(peer,
&grease_response_edns_flags);
dns_peer_getrespednsoption(
peer, &grease_response_edns_option);
dns_peer_getrespednsversion(
peer, &grease_response_edns_version);
}
}
if (view != NULL) {
udpsize = dns_view_getudpsize(view);
} else {
@@ -1057,6 +1100,32 @@ ns_client_addopt(ns_client_t *client, dns_message_t *message,
flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
/*
* Don't grease EDNS flags if there is an unknown flag in the request.
*/
if ((client->extflags & ~grease_edns_known_flags & 0xffff) != 0) {
grease_response_edns_flags = false;
}
if (grease_response_edns_flags && tnow < grease_until && GREASE) {
uint16_t ednsflags = 1 << isc_random_uniform(14);
ednsflags &= ~grease_edns_known_flags;
flags |= ednsflags;
}
if (grease_response_edns_option && tnow < grease_until && GREASE) {
uint16_t code = 100 + isc_random_uniform(65000 - 100);
INSIST(count < DNS_EDNSOPTIONS);
ednsopts[count].code = code;
ednsopts[count].length = 0;
ednsopts[count].value = NULL;
count++;
}
if (grease_response_edns_version && tnow < grease_until && GREASE) {
version = 1 + isc_random_uniform(254);
}
/* Set EDNS options if applicable */
if (WANTNSID(client)) {
if (client->manager->sctx->server_id != NULL) {
@@ -1230,8 +1299,8 @@ no_nsid:
}
}
result = dns_message_buildopt(message, opt, 0, udpsize, flags, ednsopts,
count);
result = dns_message_buildopt(message, opt, version, udpsize, flags,
ednsopts, count);
return result;
}
@@ -1652,7 +1721,7 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) {
result = DNS_R_BADVERS;
}
ns_client_error(client, result);
return (result);
return result;
}
ns_stats_increment(client->manager->sctx->nsstats,