Enhancements to DNS server and notes for usage with bind
This commit is contained in:
@@ -3,15 +3,23 @@
|
||||
namespace App\Classes\Protocol\DNS;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
final class Query
|
||||
{
|
||||
private const LOGKEY = 'PDQ';
|
||||
|
||||
private string $buf;
|
||||
private int $class;
|
||||
private string $domain;
|
||||
private string $dns;
|
||||
private int $id;
|
||||
private int $type;
|
||||
|
||||
private int $arcount;
|
||||
private int $qdcount;
|
||||
|
||||
private RR $additional;
|
||||
|
||||
private Collection $labels;
|
||||
|
||||
// https://github.com/guyinatuxedo/dns-fuzzer/blob/master/dns.md
|
||||
@@ -34,6 +42,8 @@ final class Query
|
||||
|
||||
$this->id = $header['id'];
|
||||
$this->qdcount = $header['qdcount'];
|
||||
$this->arcount = $header['arcount'];
|
||||
$this->header = $header['header'];
|
||||
|
||||
// Get the domain elements
|
||||
$this->labels = collect();
|
||||
@@ -49,19 +59,40 @@ final class Query
|
||||
$this->type = $result['type'];
|
||||
$this->class = $result['class'];
|
||||
|
||||
$this->domain = substr($this->buf,$x=$this->header_len(),$rx_ptr-$x);
|
||||
$this->dns = substr($this->buf,$this->header_len(),$rx_ptr-$this->header_len());
|
||||
|
||||
// Do we have additional records
|
||||
if ($this->arcount) {
|
||||
// Additional records, EDNS: https://datatracker.ietf.org/doc/html/rfc6891
|
||||
if (($haystack = strstr(substr($this->buf,$rx_ptr+1+10),"\x00",true)) !== FALSE) {
|
||||
Log::error(sprintf('%s:! DNS additional record format error?',self::LOGKEY));
|
||||
// @todo catch this
|
||||
}
|
||||
|
||||
$this->additional = new RR(substr($this->buf,$rx_ptr,(strlen($haystack) === 0) ? NULL : strlen($haystack)));
|
||||
$rx_ptr += $this->additional->length;
|
||||
}
|
||||
|
||||
if (strlen($this->buf) !== $rx_ptr) {
|
||||
dd(['query remaining'=>strlen($this->buf)-$rx_ptr,'hex'=>hex_dump(substr($this->buf,$rx_ptr))]);
|
||||
}
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'class':
|
||||
case 'domain':
|
||||
case 'dns':
|
||||
case 'id':
|
||||
case 'labels':
|
||||
case 'qdcount':
|
||||
case 'arcount':
|
||||
case 'header':
|
||||
case 'type':
|
||||
return $this->{$key};
|
||||
|
||||
case 'domain':
|
||||
return $this->labels->join('.');
|
||||
}
|
||||
}
|
||||
|
||||
|
75
app/Classes/Protocol/DNS/RR.php
Normal file
75
app/Classes/Protocol/DNS/RR.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Protocol\DNS;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use App\Classes\Protocol\DNS;
|
||||
|
||||
final class RR
|
||||
{
|
||||
private const LOGKEY = 'PDR';
|
||||
|
||||
public Collection $labels;
|
||||
public int $type;
|
||||
public int $class;
|
||||
private string $buf;
|
||||
|
||||
public function __construct(string $buf)
|
||||
{
|
||||
$this->buf = $buf;
|
||||
$this->labels = collect();
|
||||
|
||||
$i = 0;
|
||||
|
||||
$domain = strstr($buf,"\x00",TRUE);
|
||||
$i += strlen($domain)+1;
|
||||
|
||||
$this->type = Arr::get(unpack('n',substr($buf,$i,2)),1);
|
||||
$this->class = Arr::get(unpack('n',substr($buf,$i+2,2)),1);
|
||||
$i += 4;
|
||||
|
||||
switch ($this->type) {
|
||||
case DNS::DNS_TYPE_CNAME:
|
||||
case DNS::DNS_TYPE_NS:
|
||||
case DNS::DNS_TYPE_DS:
|
||||
case DNS::DNS_TYPE_SOA:
|
||||
$i = 0;
|
||||
|
||||
while (($len=ord(substr($domain,$i++,1))) !== 0x00) {
|
||||
$this->labels->push(substr($buf,$i,$len));
|
||||
$i += $len;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DNS::DNS_TYPE_OPT:
|
||||
// Domain is 0x00
|
||||
$this->ttl = Arr::get(unpack('N',substr($buf,$i,4)),1);
|
||||
$this->rddata_len = Arr::get(unpack('n',substr($buf,$i+4,2)),1);
|
||||
$this->rddata = substr($buf,$i+6,$this->rddata_len);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
dd(['unknown type:'.$this->type,'buf'=>$this->buf]);
|
||||
}
|
||||
}
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'length':
|
||||
return strlen($this->buf);
|
||||
|
||||
default:
|
||||
throw new \Exception(sprintf('%s:Unknown key [%s]',self::LOGKEY,$key));
|
||||
}
|
||||
}
|
||||
|
||||
public function __tostring(): string
|
||||
{
|
||||
return $this->buf;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user