PHP has a couple DNS functions you can use to perform record lookups.
Most of us are familiar with the two basic ones – gethostbyname() and gethostbyaddr(), both of which perform a single function – returning a hostname or IP address. Here’s an example of both:
<?php
$ip = gethostbyname("v-nessa.net");
$host = gethostbyaddr("69.174.114.71");
echo "v-nessa.net has the IP $ip, which reverses to $host";
?>
The above will return:
v-nessa.net has the IP 69.174.114.71, which has a PTR of server.v-nessa.net
Similarly to gethostbyname, there’s gethostbynamel which is useful for hostnames with multiple A records:
$ips = gethostbynamel("test.v-nessa.net");
foreach ($ips as $ip => $value){
echo $value . "\n";
}
Will return:
69.174.114.71
69.174.115.243
A more advanced function is dns_get_record, which can pull any valid record for a hostname or IP. Think about the dig command you use in Unix to find DNS records:
nessa@nessa-desktop:~$ dig +short v-nessa.net A
69.174.114.71
The dns_get_record function works in a similar way, and can obtain the following DNS record types:
DNS_A, DNS_CNAME, DNS_HINFO, DNS_MX, DNS_NS, DNS_PTR, DNS_SOA, DNS_TXT, DNS_AAAA, DNS_SRV, DNS_NAPTR, DNS_A6, DNS_ALL or DNS_ANY.
The following will give you a similar result:
$recs = dns_get_record("v-nessa.net", DNS_A);
print_r($recs);
Will return:
Array
(
[0] => Array
(
[host] => v-nessa.net
[type] => A
[ip] => 69.174.114.71
[class] => IN
[ttl] => 13728
)
)
If you want to obtain multiple DNS types, you can do so by separating the record types with a plus sign:
$recs = dns_get_record("v-nessa.net", DNS_A + DNS_MX);
Will return:
Array
(
[0] => Array
(
[host] => v-nessa.net
[type] => A
[ip] => 69.174.114.71
[class] => IN
[ttl] => 13736
)
[1] => Array
(
[host] => v-nessa.net
[type] => MX
[pri] => 0
[target] => v-nessa.net
[class] => IN
[ttl] => 14145
)
)
You’ll notice that the output is a double array, so to call individual values you can do either of the following:
// will return the IP for array 0 ( A record)
echo $recs[0]['ip'];
// will return results for common records
foreach ($recs as $type => $value){
echo $value[ip] . "\n";
}
Similar to the example above, you can use the DNS_ALL type to show any records available for the hostname, and use a minus sign to exclude certain record types. For example, the below code will return all DNS results for v-nessa.net, but exclude NS records:
$recs = dns_get_record("v-nessa.net", DNS_ALL - DNS_NS );
foreach ($recs as $type => $value){
echo $value[type] . "\n";
}
The following records were returned:
A
SOA
MX
TXT
Here’s a more practical example – a simple PHP DNS lookup script. Say you have a form on your site that allows a user to type in a hostname and select a type of record: A, MX, NS, and TXT. The passed form values are $host and $type, and the below script will accept the variables and output the results according to the record type:
HTML Form:
<form action="dns.php" method="POST">
Hostname: <input type="text" name="host" />
Type: <select name="type">
<option value="a">A</option>
<option value="mx">MX</option>
<option value="ns">NS</option>
<option value="txt">TXT</option> </select>
</form>
PHP Script (dns.php):
<?php
if(!empty($_POST['host']) && !empty($_POST['type'])){
// Grab variable from form and define valid types
$host = $_POST['host'];
$type = strtoupper($_POST['type');
$validtypes=array("A","MX","NS","TXT");
// Check that dns type is defined or allowed
if(!defined("DNS_" . $type) or !in_array($type,$validtypes)){
echo "Invalid DNS Type!";
}else{
$type = constant("DNS_" . $type);
$rec = dns_get_record($host, $type);
// Set result types - can be modified by using available elements from $rec array
switch($type){
case DNS_A:
$recvals=array("Hostname" => "host","Type" => "type", "IP" => "ip");
break;
case DNS_MX:
$recvals=array("Hostname" => "host","Type" => "type", "Target" => "target", "Priority" => "pri");
break;
case DNS_NS:
$recvals=array("Hostname" => "host","Type" => "type", "Target" => "target");
break;
case DNS_TXT:
$recvals=array("Hostname" => "host","Type" => "type", "Record" => "txt");
break;
}
// Output results
foreach ($rec as $arr => $num){
foreach ($recvals as $title => $value){
echo $title . " : " . $num[$value] . "\n";
}
}
}
} else {
echo "Either hostname or record type is missing";
}
It’s of course easy to modify the above code accordingly, and I’m sure there may be better ways to do this. Feel free to post your own code snippets or comments.