As per RFC 2308, add SOA to authoriative answers with nodata, or errors

This commit is contained in:
Deon George 2023-11-12 18:14:53 +11:00
parent 85243d128e
commit ea42a347eb
1 changed files with 45 additions and 31 deletions

View File

@ -91,6 +91,7 @@ final class DNS extends BaseProtocol
* Handle a DNS query
*
* https://www.ietf.org/rfc/rfc1035.txt
* https://www.ietf.org/rfc/rfc2308.txt
* https://github.com/guyinatuxedo/dns-fuzzer/blob/master/dns.md
*
* labels 63 octets or less
@ -119,7 +120,7 @@ final class DNS extends BaseProtocol
// If the wrong class
if ($this->query->class !== self::DNS_QUERY_IN) {
Log::error(sprintf('%s:! We only service Internet queries [%d]',self::LOGKEY,$this->query->class));
return $this->reply(self::DNS_NOTIMPLEMENTED);
return $this->reply(self::DNS_NOTIMPLEMENTED,[],$this->soa());
}
$dos = Domain::select(['id','name','dnsdomain'])->active();
@ -148,15 +149,7 @@ final class DNS extends BaseProtocol
return $this->reply(
self::DNS_NOERROR,
[serialize([
$this->domain_split(gethostname()),
$this->domain_split(Str::replace('@','.',config('app.mail.mail_from','nobody@'.gethostname()))),
1,
self::DEFAULT_TTL,
self::DEFAULT_TTL,
self::DEFAULT_TTL,
self::DEFAULT_TTL
]) => self::DNS_TYPE_SOA],
$this->soa(),
[],
[serialize($this->domain_split(gethostname())) => self::DNS_TYPE_NS],
);
@ -255,7 +248,7 @@ final class DNS extends BaseProtocol
]) => self::DNS_TYPE_SRV]);
} else {
return $this->nameerr();
return $this->nodata();
}
case self::DNS_TYPE_TXT:
@ -279,7 +272,7 @@ final class DNS extends BaseProtocol
default:
Log::error(sprintf('%s:! We dont support DNS query types [%d]',self::LOGKEY,$this->query->type));
return $this->reply(self::DNS_NOTIMPLEMENTED);
return $this->reply(self::DNS_NOTIMPLEMENTED,[],$this->soa());
}
}
@ -294,11 +287,36 @@ final class DNS extends BaseProtocol
return pack('n',$offset | (3 << 14));
}
/**
* Split a domain into a DNS domain string
*
* @param string $domain
* @return string
*/
private function domain_split(string $domain): string
{
$a = '';
foreach (explode('.',$domain) as $item)
$a .= pack('C',strlen($item)).$item;
$a .= "\x00";
return $a;
}
private function nameerr(): int
{
Log::error(sprintf('%s:! DNS query for a resource we dont manage [%s]',self::LOGKEY,$this->query->domain));
return $this->reply(self::DNS_NAMEERR);
return $this->reply(self::DNS_NAMEERR,[],$this->soa());
}
private function nodata(): int
{
Log::error(sprintf('%s:! DNS query for a resource we dont manage [%s] in our zone(s)',self::LOGKEY,$this->query->domain));
return $this->reply(self::DNS_NOERROR,[],$this->soa());
}
/**
@ -384,24 +402,6 @@ final class DNS extends BaseProtocol
return TRUE;
}
/**
* Split a domain into a DNS domain string
*
* @param string $domain
* @return string
*/
private function domain_split(string $domain): string
{
$a = '';
foreach (explode('.',$domain) as $item)
$a .= pack('C',strlen($item)).$item;
$a .= "\x00";
return $a;
}
/**
* Return a DNS Resource Record
*
@ -458,4 +458,18 @@ final class DNS extends BaseProtocol
return $reply;
}
private function soa(): array
{
return
[serialize([
$this->domain_split(gethostname()),
$this->domain_split(Str::replace('@','.',config('app.mail.mail_from','nobody@'.gethostname()))),
1, // Serial
self::DEFAULT_TTL, // Refresh
self::DEFAULT_TTL, // Retry
self::DEFAULT_TTL*7,// Expire
self::DEFAULT_TTL // Minimum cache
]) => self::DNS_TYPE_SOA];
}
}