-
-
Save stephanhuewe/8998156ff5148df86eaed92d415db197 to your computer and use it in GitHub Desktop.
Simple PHP code act as a dig tool to find dns records (using specific given nameservers)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$result = array(); | |
$result_html = ''; | |
function getDnsRecords($domain) { | |
$result = array(); | |
$servers = array("8.8.8.8", "8.8.8.8", "8.8.8.8", "8.8.8.8", "8.8.8.8", "8.8.8.8", "8.8.8.8", "8.8.8.8"); | |
foreach ($servers as $server) { | |
$dnsResult = dns_get_record_from($server, "A", $domain); | |
foreach ($dnsResult as $record) { | |
reset($record); | |
$host = $domain; | |
$type = "A"; | |
$value = $record; | |
$result[] = array( | |
'server' => $server, | |
'host' => $host, | |
'type' => $type, | |
'value' => $value | |
); | |
} | |
} | |
return $result; | |
} | |
if (isset($_POST['domain']) && !empty($_POST['domain'])) { | |
$domain = $_POST['domain']; | |
$domain_regex = '/[a-z\d][a-z\-\d\.]+[a-z\d]/i'; | |
if (preg_match($domain_regex, $domain)) { | |
if ($url = parse_url($domain)) { | |
if (isset($url['host'])) { | |
$result = getDnsRecords($url['host']); | |
} else if (isset($url['path'])) { | |
$result = getDnsRecords($domain); | |
} | |
} | |
} | |
if (empty($result)) { | |
$result_html = '<hr>Nothing found or Domain Invalid'; | |
} else { | |
$result_html .= "<hr>\n<table>\n"; | |
foreach ($result as $record) { | |
$result_html .= sprintf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", $record['server'], $record['host'], $record['type'], $record['value']); | |
} | |
$result_html .= "</table>\n"; | |
} | |
} | |
function dns_get_record_from(string $server, string $type, string $record): array | |
{ | |
// Source: https://github.com/metaregistrar/php-dns-client/blob/master/DNS/dnsData/dnsTypes.php | |
static $types = [ | |
1 => 'A', | |
2 => 'NS', | |
5 => 'CNAME', | |
6 => 'SOA', | |
12 => 'PTR', | |
15 => 'MX', | |
16 => 'TXT', | |
28 => 'AAAA', | |
255 => 'ANY', | |
]; | |
$typeid = array_search($type, $types, true); | |
if (!$typeid) { | |
throw new \InvalidArgumentException('Invalid type'); | |
} | |
$host = 'udp://' . $server; | |
if (!$socket = @fsockopen($host, 53, $errno, $errstr, 10)) { | |
throw new \RuntimeException('Failed to open socket to ' . $host); | |
} | |
$labels = explode('.', $record); | |
$question_binary = ''; | |
foreach ($labels as $label) { | |
$question_binary .= pack("C", strlen($label)); // size byte first | |
$question_binary .= $label; // then the label | |
} | |
$question_binary .= pack("C", 0); // end it off | |
$id = rand(1,255)|(rand(0,255)<<8); // generate the ID | |
// Set standard codes and flags | |
$flags = (0x0100 & 0x0300) | 0x0020; // recursion & queryspecmask | authenticated data | |
$opcode = 0x0000; // opcode | |
// Build the header | |
$header = ""; | |
$header .= pack("n", $id); | |
$header .= pack("n", $opcode | $flags); | |
$header .= pack("nnnn", 1, 0, 0, 0); | |
$header .= $question_binary; | |
$header .= pack("n", $typeid); | |
$header .= pack("n", 0x0001); // internet class | |
$headersize = strlen($header); | |
$headersizebin = pack("n", $headersize); | |
$request_size = fwrite($socket, $header, $headersize); | |
$rawbuffer = fread($socket, 4096); | |
fclose($socket); | |
if (strlen($rawbuffer) < 12) { | |
throw new \RuntimeException("DNS query return buffer too small"); | |
} | |
$pos = 0; | |
$read = function ($len) use (&$pos, $rawbuffer) { | |
$out = substr($rawbuffer, $pos, $len); | |
$pos += $len; | |
return $out; | |
}; | |
$read_name_pos = function ($offset) use ($rawbuffer) { | |
$out = []; | |
while (($len = ord(substr($rawbuffer, $offset, 1))) && $len > 0) { | |
$out[] = substr($rawbuffer, $offset + 1, $len); | |
$offset += $len + 1; | |
} | |
return $out; | |
}; | |
$read_name = function() use (&$read, $read_name_pos) { | |
$out = []; | |
while (($len = ord($read(1))) && $len > 0) { | |
if ($len >= 64) { | |
$offset = (($len & 0x3f) << 8) + ord($read(1)); | |
$out = array_merge($out, $read_name_pos($offset)); | |
break; | |
} | |
else { | |
$out[] = $read($len); | |
} | |
} | |
return implode('.', $out); | |
}; | |
$header = unpack("nid/nflags/nqdcount/nancount/nnscount/narcount", $read(12)); | |
$flags = sprintf("%016b\n", $header['flags']); | |
// No answers | |
if (!$header['ancount']) { | |
return []; | |
} | |
$is_authorative = $flags[5] == 1; | |
// Question section | |
if ($header['qdcount']) { | |
// Skip name | |
$read_name(); | |
// skip question part | |
$pos += 4; // 4 => QTYPE + QCLASS | |
} | |
$responses = []; | |
for ($a = 0; $a < $header['ancount']; $a++) { | |
$read_name(); // Skip name | |
$ans_header = unpack("ntype/nclass/Nttl/nlength", $read(10)); | |
$t = $types[$ans_header['type']] ?? null; | |
if ($type != 'ANY' && $t != $type) { | |
// Skip type that was not requested | |
$t = null; | |
} | |
switch ($t) { | |
case 'A': | |
$responses[] = implode(".", unpack("Ca/Cb/Cc/Cd", $read(4))); | |
break; | |
case 'AAAA': | |
$responses[] = implode(':', unpack("H4a/H4b/H4c/H4d/H4e/H4f/H4g/H4h", $read(16))); | |
break; | |
case 'MX': | |
$prio = unpack('nprio', $read(2)); // priority | |
$responses[$prio['prio']] = $read_name(); | |
break; | |
case 'NS': | |
case 'CNAME': | |
case 'PTR': | |
$responses[] = $read_name(); | |
break; | |
case 'TXT': | |
$responses[] = $read($ans_header['length']); | |
break; | |
default: | |
// Skip | |
$read($ans_header['length']); | |
break; | |
} | |
} | |
return $responses; | |
} | |
?> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>DNS Lookup</title> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> | |
<style> | |
body { | |
padding: 20px; | |
} | |
.form-inline { | |
margin-bottom: 10px; | |
} | |
table { | |
margin: auto; | |
width: 100%; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1 class="text-center">DNS Lookup</h1> | |
<form method="post"> | |
<div class="form-inline justify-content-center"> | |
<label for="domain">Domain:</label> | |
<input id="domain" type="text" name="domain" class="form-control mx-2" value="<?= empty($_POST['domain']) ? '' : $_POST['domain'] ?>"> | |
<button type="submit" class="btn btn-primary">Lookup</button> | |
</div> | |
</form> | |
<div class="mt-4"> | |
<?= $result_html ? $result_html : '' ?> | |
</div> | |
<hr> | |
</div> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment