Categories
Web

PHP gethostbyaddr($ip) too slow

Working on a project, I needed to perform reverse DNS lookups of IP addresses in PHP. The native function gethostbyaddr() seems to be very slow. I managed to vastly improve the speed of the lookups by switching to dns_get_record().

gethostbyaddr($ip);

I didn’t run any statistics to compare the two, but the effect on the tool was significant. Feel free to conduct your own testing.

# 2024-04-30 web-performance.ch
function gethostbyaddrl($ip, $retries = 3) {
    $hostnames = []; // Initialize the variable at the start of the function

    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
        // IPv4 Reverse Lookup
        $reverseIp = implode('.', array_reverse(explode('.', $ip))) . '.in-addr.arpa';
    } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
        // IPv6 Reverse Lookup
        $uncompressed = implode('', unpack('H*hex', inet_pton($ip)));
        $reverseIp = '';
        for ($i = strlen($uncompressed) - 1; $i >= 0; $i--) {
            $reverseIp .= $uncompressed[$i] . '.';
        }
        $reverseIp .= 'ip6.arpa';
    } else {
        return false; // Not a valid IP address
    }

    $attempt = 0;
    while ($attempt < $retries) {
        try {
            $records = dns_get_record($reverseIp, DNS_PTR);
            if ($records) {
                foreach ($records as $record) {
                    if (isset($record['target'])) {
                        $hostnames[] = $record['target'];
                    }
                }
            }
            return (!empty($hostnames)) ? $hostnames : FALSE;
        } catch (Exception $e) {
            // Increment the attempt counter and retry if the limit is not reached
            $attempt++;
            if ($attempt >= $retries) {
                return FALSE; // Return false if all retries are exhausted
            }
        }
    }
}

// Example usage
$ipv4Address = '8.8.8.8';
$ipv6Address = '2001:4860:4860::8888';
echo "IPv4: ";
$hostnames = gethostbyaddrl($ipv4Address);
echo $hostnames ? implode(', ', $hostnames) : "No hostnames found for IP $ipv4Address";
echo "\nIPv6: ";
$hostnames = gethostbyaddrl($ipv6Address);
echo $hostnames ? implode(', ', $hostnames) : "No hostnames found for IP $ipv6Address";

Somehow, at first I did not think this was worth posting. However, it does not appear to be a super common answer yet if you google for this issue. So, I went ahead and made this quick post.