mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-26 00:30:05 -04:00
Tighten DNS COOKIE response handling
Fallback to TCP when we have already seen a DNS COOKIE response from the given address and don't have one in this UDP response. This could be a server that has turned off DNS COOKIE support, a misconfigured anycast server with partial DNS COOKIE support, or a spoofed response. Falling back to TCP is the correct behaviour in all 3 cases.
This commit is contained in:
parent
8fed3b3e17
commit
0e3b1f5a25
1 changed files with 53 additions and 6 deletions
|
|
@ -2358,7 +2358,12 @@ add_serveraddr(uint8_t *buf, const size_t bufsize, const resquery_t *query) {
|
|||
return (addr2buf(buf, bufsize, &query->addrinfo->sockaddr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Client cookie is 8 octets.
|
||||
* Server cookie is [8..32] octets.
|
||||
*/
|
||||
#define CLIENT_COOKIE_SIZE 8U
|
||||
#define COOKIE_BUFFER_SIZE (8U + 32U)
|
||||
|
||||
static void
|
||||
compute_cc(const resquery_t *query, uint8_t *cookie, const size_t len) {
|
||||
|
|
@ -2603,7 +2608,7 @@ resquery_send(resquery_t *query) {
|
|||
bool reqnsid = res->view->requestnsid;
|
||||
bool sendcookie = res->view->sendcookie;
|
||||
bool tcpkeepalive = false;
|
||||
unsigned char cookie[64];
|
||||
unsigned char cookie[COOKIE_BUFFER_SIZE];
|
||||
uint16_t padding = 0;
|
||||
|
||||
/*
|
||||
|
|
@ -2675,9 +2680,11 @@ resquery_send(resquery_t *query) {
|
|||
fctx->res,
|
||||
dns_resstatscounter_cookieout);
|
||||
} else {
|
||||
compute_cc(query, cookie, 8);
|
||||
compute_cc(query, cookie,
|
||||
CLIENT_COOKIE_SIZE);
|
||||
ednsopts[ednsopt].value = cookie;
|
||||
ednsopts[ednsopt].length = 8;
|
||||
ednsopts[ednsopt].length =
|
||||
CLIENT_COOKIE_SIZE;
|
||||
inc_stats(
|
||||
fctx->res,
|
||||
dns_resstatscounter_cookienew);
|
||||
|
|
@ -7627,6 +7634,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
|||
result = dns_message_checksig(query->rmessage, fctx->res->view);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE3("signature check failed", result);
|
||||
if (result == DNS_R_UNEXPECTEDTSIG ||
|
||||
result == DNS_R_EXPECTEDTSIG) {
|
||||
rctx.nextitem = true;
|
||||
}
|
||||
rctx_done(&rctx, result);
|
||||
return;
|
||||
}
|
||||
|
|
@ -7643,6 +7654,40 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
|||
* ensured by the dispatch code).
|
||||
*/
|
||||
|
||||
/*
|
||||
* If we have had a server cookie and don't get one retry over TCP.
|
||||
* This may be a misconfigured anycast server or an attempt to send
|
||||
* a spoofed response. Skip if we have a valid tsig.
|
||||
*/
|
||||
if (dns_message_gettsig(query->rmessage, NULL) == NULL &&
|
||||
!query->rmessage->cc_ok && !query->rmessage->cc_bad &&
|
||||
(rctx.retryopts & DNS_FETCHOPT_TCP) == 0)
|
||||
{
|
||||
unsigned char cookie[COOKIE_BUFFER_SIZE];
|
||||
if (dns_adb_getcookie(fctx->adb, query->addrinfo, cookie,
|
||||
sizeof(cookie)) > CLIENT_COOKIE_SIZE)
|
||||
{
|
||||
if (isc_log_wouldlog(dns_lctx, ISC_LOG_INFO)) {
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_sockaddr_format(&query->addrinfo->sockaddr,
|
||||
addrbuf, sizeof(addrbuf));
|
||||
isc_log_write(
|
||||
dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
|
||||
"missing expected cookie from %s",
|
||||
addrbuf);
|
||||
}
|
||||
rctx.retryopts |= DNS_FETCHOPT_TCP;
|
||||
rctx.resend = true;
|
||||
rctx_done(&rctx, result);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* XXXMPA When support for DNS COOKIE becomes ubiquitous, fall
|
||||
* back to TCP for all non-COOKIE responses.
|
||||
*/
|
||||
}
|
||||
|
||||
rctx_edns(&rctx);
|
||||
|
||||
/*
|
||||
|
|
@ -8058,7 +8103,7 @@ rctx_opt(respctx_t *rctx) {
|
|||
uint16_t optlen;
|
||||
unsigned char *optvalue;
|
||||
dns_adbaddrinfo_t *addrinfo;
|
||||
unsigned char cookie[8];
|
||||
unsigned char cookie[CLIENT_COOKIE_SIZE];
|
||||
bool seen_cookie = false;
|
||||
bool seen_nsid = false;
|
||||
|
||||
|
|
@ -8095,8 +8140,10 @@ rctx_opt(respctx_t *rctx) {
|
|||
compute_cc(query, cookie, sizeof(cookie));
|
||||
INSIST(query->rmessage->cc_bad == 0 &&
|
||||
query->rmessage->cc_ok == 0);
|
||||
if (optlen >= 8U &&
|
||||
memcmp(cookie, optvalue, 8) == 0) {
|
||||
if (optlen >= CLIENT_COOKIE_SIZE &&
|
||||
memcmp(cookie, optvalue,
|
||||
CLIENT_COOKIE_SIZE) == 0)
|
||||
{
|
||||
query->rmessage->cc_ok = 1;
|
||||
inc_stats(fctx->res,
|
||||
dns_resstatscounter_cookieok);
|
||||
|
|
|
|||
Loading…
Reference in a new issue