mirror of
https://github.com/yarrick/iodine.git
synced 2025-10-28 03:29:51 +00:00
Merge pull request #120 from luizluca/nxdomain_for_underscore
Answer NXDOMAIN for _.xxx.yyy.top.domain
This commit is contained in:
65
src/dns.c
65
src/dns.c
@@ -390,6 +390,71 @@ int dns_encode_a_response(char *buf, size_t buflen, struct query *q)
|
||||
return len;
|
||||
}
|
||||
|
||||
int dns_encode_nxdomain(char *buf, size_t buflen, struct query *q, const char *zone)
|
||||
{
|
||||
char rnamebuf[256];
|
||||
char nsbuf[256];
|
||||
HEADER *header;
|
||||
char *soa_start;
|
||||
char *p;
|
||||
|
||||
if (buflen < sizeof(HEADER))
|
||||
return 0;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
header = (HEADER*)buf;
|
||||
|
||||
header->id = htons(q->id);
|
||||
header->qr = 1; // response
|
||||
header->opcode = 0;
|
||||
header->aa = 1; // authoritative
|
||||
header->tc = 0;
|
||||
header->rd = 0;
|
||||
header->ra = 0;
|
||||
header->rcode = 3; // NXDOMAIN
|
||||
|
||||
header->qdcount = htons(1);
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(1); // We'll include SOA
|
||||
header->arcount = htons(0);
|
||||
|
||||
p = buf + sizeof(HEADER);
|
||||
|
||||
// Question section
|
||||
putname(&p, buflen - (p - buf), q->name);
|
||||
CHECKLEN(4);
|
||||
putshort(&p, q->type);
|
||||
putshort(&p, C_IN);
|
||||
|
||||
// Authority section (SOA)
|
||||
CHECKLEN(10);
|
||||
putname(&p, buflen - (p - buf), zone); // zone name (owner of SOA)
|
||||
putshort(&p, T_SOA);
|
||||
putshort(&p, C_IN);
|
||||
putlong(&p, 60); // TTL
|
||||
|
||||
soa_start = p;
|
||||
p += 2; // skip rdlength (to be filled later)
|
||||
|
||||
// Primary NS and responsible mailbox
|
||||
snprintf(nsbuf, sizeof(nsbuf), "ns.%s", zone);
|
||||
putname(&p, buflen - (p - buf), nsbuf);
|
||||
snprintf(rnamebuf, sizeof(rnamebuf), "hostmaster.%s", zone);
|
||||
putname(&p, buflen - (p - buf), rnamebuf);
|
||||
|
||||
// SOA fields: serial, refresh, retry, expire, minimum
|
||||
putlong(&p, 1); // serial
|
||||
putlong(&p, 3600); // refresh
|
||||
putlong(&p, 1800); // retry
|
||||
putlong(&p, 604800); // expire
|
||||
putlong(&p, 60); // minimum
|
||||
|
||||
int soalen = p - soa_start - 2;
|
||||
putshort(&soa_start, soalen); // fill in rdlength
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
#undef CHECKLEN
|
||||
|
||||
unsigned short dns_get_id(char *packet, size_t packetlen)
|
||||
|
||||
@@ -31,6 +31,7 @@ int dns_encode(char *, size_t, struct query *, qr_t, const char *, size_t);
|
||||
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q,
|
||||
char *topdomain);
|
||||
int dns_encode_a_response(char *buf, size_t buflen, struct query *q);
|
||||
int dns_encode_nxdomain(char *buf, size_t buflen, struct query *q, const char *zone);
|
||||
unsigned short dns_get_id(char *packet, size_t packetlen);
|
||||
int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t);
|
||||
|
||||
|
||||
@@ -1597,6 +1597,27 @@ handle_a_request(int dns_fd, struct query *q, int fakeip)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_underscore_request(int dns_fd, struct query *q, const char *topdomain)
|
||||
{
|
||||
char buf[64*1024];
|
||||
int len;
|
||||
|
||||
len = dns_encode_nxdomain(buf, sizeof(buf), q, topdomain);
|
||||
if (len < 1) {
|
||||
warnx("dns_encode_nxdomain doesn't fit");
|
||||
return;
|
||||
}
|
||||
|
||||
if (debug >= 2) {
|
||||
fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes NXDOMAIN reply\n",
|
||||
format_addr(&q->from, q->fromlen), q->type, q->name, len);
|
||||
}
|
||||
if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
|
||||
warn("nxdomain reply send error");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
forward_query(int bind_fd, struct query *q)
|
||||
{
|
||||
@@ -1719,6 +1740,18 @@ tunnel_dns(int tun_fd, int dns_fd, struct dnsfd *dns_fds, int bind_fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle A-type query for _.***.topdomain. It happens when
|
||||
*
|
||||
* https://datatracker.ietf.org/doc/html/rfc7816 (qname minimisation)
|
||||
* https://github.com/isc-projects/bind9/commit/ae52c2117eba9fa0778125f4e10834d673ab811b
|
||||
* */
|
||||
if (q.type == T_A &&
|
||||
(q.name[0] == '_') &&
|
||||
q.name[1] == '.') {
|
||||
handle_underscore_request(dns_fd, &q, topdomain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (q.type) {
|
||||
case T_NULL:
|
||||
case T_PRIVATE:
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef unsigned int in_addr_t;
|
||||
#define T_CNAME DNS_TYPE_CNAME
|
||||
#define T_MX DNS_TYPE_MX
|
||||
#define T_TXT DNS_TYPE_TXT
|
||||
#define T_SOA DNS_TYPE_SOA
|
||||
#define T_SRV DNS_TYPE_SRV
|
||||
|
||||
#define C_IN 1
|
||||
|
||||
Reference in New Issue
Block a user