Fix negative responses
Previously if the resolver was asked for a record it didn't have, it would return a response with a NS record in the authority section. This is incorrect, as the lack of answer indicates to the resolver that it should try that NS record as the next step, resulting in a loop: $ dig @8.8.8.8 rbf-seed.btc.petertodd.org TXT +trace <snip> rbf-seed.btc.petertodd.org. 300 IN NS rbf-seed-ns1.btc.petertodd.org. rbf-seed.btc.petertodd.org. 300 IN NS rbf-seed-ns2.btc.petertodd.org. ;; Received 141 bytes from 205.251.193.174#53(ns-430.awsdns-53.com) in 426 ms rbf-seed.btc.petertodd.org. 40000 IN NS rbf-seed-ns2.btc.petertodd.org. ;; BAD (HORIZONTAL) REFERRAL ;; Received 88 bytes from 185.52.1.173#53(rbf-seed-ns2.btc.petertodd.org) in 108 ms rbf-seed.btc.petertodd.org. 40000 IN NS rbf-seed-ns2.btc.petertodd.org. ;; BAD (HORIZONTAL) REFERRAL ;; Received 88 bytes from 185.52.1.173#53(rbf-seed-ns2.btc.petertodd.org) in 108 ms <snip> rbf-seed.btc.petertodd.org. 40000 IN NS rbf-seed-ns2.btc.petertodd.org. ;; BAD (HORIZONTAL) REFERRAL dig: too many lookups The correct response in the authority section of a negative response is a SOA record, which indicates that the answer is authoritative and the resolver can consider the record missing and stop looking for it: $ dig @8.8.8.8 rbf-seed.btc.petertodd.org TXT +trace <snip> rbf-seed.btc.petertodd.org. 300 IN NS rbf-seed-ns1.btc.petertodd.org. rbf-seed.btc.petertodd.org. 300 IN NS rbf-seed-ns2.btc.petertodd.org. ;; Received 141 bytes from 205.251.196.185#53(ns-1209.awsdns-23.org) in 740 ms rbf-seed.btc.petertodd.org. 40000 IN SOA rbf-seed-ns1.btc.petertodd.org. pete.petertodd.org. 1435846201 604800 86400 2592000 604800 ;; Received 128 bytes from 104.236.95.174#53(rbf-seed-ns1.btc.petertodd.org) in 31 ms There have been a few reports of problems resolving seed domains on some ISPs - hopefully this was the root cause.
This commit is contained in:
parent
85fb114ed5
commit
5eca8e269a
1 changed files with 27 additions and 13 deletions
40
dns.c
40
dns.c
|
@ -287,18 +287,23 @@ ssize_t static dnshandle(dns_opt_t *opt, const unsigned char *inbuf, size_t insi
|
||||||
unsigned char *outpos = outbuf+(inpos-inbuf);
|
unsigned char *outpos = outbuf+(inpos-inbuf);
|
||||||
unsigned char *outend = outbuf + BUFLEN;
|
unsigned char *outend = outbuf + BUFLEN;
|
||||||
|
|
||||||
// printf("DNS: Request host='%s' type=%i class=%i\n", name, typ, cls);
|
// printf("DNS: Request host='%s' type=%i class=%i\n", name, typ, cls);
|
||||||
|
|
||||||
// calculate size of authority section
|
// calculate max size of authority section
|
||||||
|
|
||||||
int auth_size = 0;
|
int max_auth_size = 0;
|
||||||
|
|
||||||
if (!((typ == TYPE_NS || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY))) {
|
if (!((typ == TYPE_NS || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY))) {
|
||||||
// authority section will be necessary
|
// authority section will be necessary, either NS or SOA
|
||||||
unsigned char *oldpos = outpos;
|
unsigned char *newpos = outpos;
|
||||||
write_record_ns(&oldpos, outend, "", offset, CLASS_IN, 0, opt->ns);
|
write_record_ns(&newpos, outend, "", offset, CLASS_IN, 0, opt->ns);
|
||||||
auth_size = oldpos - outpos;
|
max_auth_size = newpos - outpos;
|
||||||
// printf("Authority section will claim %i bytes\n", auth_size);
|
|
||||||
|
newpos = outpos;
|
||||||
|
write_record_soa(&newpos, outend, "", offset, CLASS_IN, opt->nsttl, opt->ns, opt->mbox, time(NULL), 604800, 86400, 2592000, 604800);
|
||||||
|
if (max_auth_size < newpos - outpos)
|
||||||
|
max_auth_size = newpos - outpos;
|
||||||
|
// printf("Authority section will claim %i bytes max\n", max_auth_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Answer section
|
// Answer section
|
||||||
|
@ -307,14 +312,14 @@ ssize_t static dnshandle(dns_opt_t *opt, const unsigned char *inbuf, size_t insi
|
||||||
|
|
||||||
// NS records
|
// NS records
|
||||||
if ((typ == TYPE_NS || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) {
|
if ((typ == TYPE_NS || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) {
|
||||||
int ret2 = write_record_ns(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->nsttl, opt->ns);
|
int ret2 = write_record_ns(&outpos, outend - max_auth_size, "", offset, CLASS_IN, opt->nsttl, opt->ns);
|
||||||
// printf("wrote NS record: %i\n", ret2);
|
// printf("wrote NS record: %i\n", ret2);
|
||||||
if (!ret2) { outbuf[7]++; have_ns++; }
|
if (!ret2) { outbuf[7]++; have_ns++; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// SOA records
|
// SOA records
|
||||||
if ((typ == TYPE_SOA || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY) && opt->mbox) {
|
if ((typ == TYPE_SOA || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY) && opt->mbox) {
|
||||||
int ret2 = write_record_soa(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->nsttl, opt->ns, opt->mbox, time(NULL), 604800, 86400, 2592000, 604800);
|
int ret2 = write_record_soa(&outpos, outend - max_auth_size, "", offset, CLASS_IN, opt->nsttl, opt->ns, opt->mbox, time(NULL), 604800, 86400, 2592000, 604800);
|
||||||
// printf("wrote SOA record: %i\n", ret2);
|
// printf("wrote SOA record: %i\n", ret2);
|
||||||
if (!ret2) { outbuf[7]++; }
|
if (!ret2) { outbuf[7]++; }
|
||||||
}
|
}
|
||||||
|
@ -327,9 +332,9 @@ ssize_t static dnshandle(dns_opt_t *opt, const unsigned char *inbuf, size_t insi
|
||||||
while (n < naddr) {
|
while (n < naddr) {
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
if (addr[n].v == 4)
|
if (addr[n].v == 4)
|
||||||
ret = write_record_a(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]);
|
ret = write_record_a(&outpos, outend - max_auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]);
|
||||||
else if (addr[n].v == 6)
|
else if (addr[n].v == 6)
|
||||||
ret = write_record_aaaa(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]);
|
ret = write_record_aaaa(&outpos, outend - max_auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]);
|
||||||
// printf("wrote A record: %i\n", ret);
|
// printf("wrote A record: %i\n", ret);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
n++;
|
n++;
|
||||||
|
@ -340,13 +345,22 @@ ssize_t static dnshandle(dns_opt_t *opt, const unsigned char *inbuf, size_t insi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authority section
|
// Authority section
|
||||||
if (!have_ns) {
|
if (!have_ns && outbuf[7]) {
|
||||||
int ret2 = write_record_ns(&outpos, outend, "", offset, CLASS_IN, opt->nsttl, opt->ns);
|
int ret2 = write_record_ns(&outpos, outend, "", offset, CLASS_IN, opt->nsttl, opt->ns);
|
||||||
// printf("wrote NS record: %i\n", ret2);
|
// printf("wrote NS record: %i\n", ret2);
|
||||||
if (!ret2) {
|
if (!ret2) {
|
||||||
outbuf[9]++;
|
outbuf[9]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!outbuf[7]) {
|
||||||
|
// Didn't include any answers, so reply with SOA as this is a negative
|
||||||
|
// response. If we replied with NS above we'd create a bad horizontal
|
||||||
|
// referral loop, as the NS response indicates where the resolver should
|
||||||
|
// try next.
|
||||||
|
int ret2 = write_record_soa(&outpos, outend, "", offset, CLASS_IN, opt->nsttl, opt->ns, opt->mbox, time(NULL), 604800, 86400, 2592000, 604800);
|
||||||
|
// printf("wrote SOA record: %i\n", ret2);
|
||||||
|
if (!ret2) { outbuf[9]++; }
|
||||||
|
}
|
||||||
|
|
||||||
// set AA
|
// set AA
|
||||||
outbuf[2] |= 4;
|
outbuf[2] |= 4;
|
||||||
|
|
Loading…
Reference in a new issue