While reading up on gethostbyaddr on PHP.net, I saw a nice idea for using fsockopen to connect over UDP port 53 to any Public DNS server, like Google's 8.8.8.8, and sending the reverse addr lookup in oh about 100 bytes, then getting the response in oh about 150 bytes! All in less than a second. This would be extremely valuable for use in things like my online header tool because it's faster than any other method. As usual, I went a bit overboard optimizing it to be lean and fast.

It's also a fairly decent example of how to use fsockopen in general.. Fsockopen enables super-hero-like tricks.

Table of Contents

  1. Introduction
    1. PHP fsockopen for DNS lookups
      1. Using the 6 fastest DNS servers
    2. The gethostbyaddr source
    3. Download and Copy Code

PHP fsockopen for DNS lookups

The function has 3 arguments.

  • An ip address to lookup.
  • A DNS server to query.
  • And a timeout in seconds.

Using the 6 fastest DNS servers

This list includes OpenDNS, UltraDNS, Level3, RoadRunner, and of course, Google DNS (see wikipedia for more).

$ip = '208.86.158.195';
foreach ( array('8.8.8.8', '156.154.70.1', '208.67.222.222', '156.154.70.1', '209.244.0.4', '216.146.35.35') as $dns) {
  echo gethostbyaddr_timeout( $ip, $dns, 1 );
}

The gethostbyaddr source

View the syntax highlighted source.

.



function gethostbyaddr_timeout( $ip, $dns, $timeout = 3 ) {
	// idea from http://www.php.net/manual/en/function.gethostbyaddr.php#46869
	// https://www.askapache.com/pub/php/gethostbyaddr.php
	
    // random transaction number (for routers etc to get the reply back)
    $data = rand( 10, 77 ) . "\1\0\0\1\0\0\0\0\0\0";
	
	// octals in the array, keys are strlen of bit
	$bitso = array("","\1","\2","\3" );
	foreach( array_reverse( explode( '.', $ip ) ) as $bit ) {
		$l=strlen($bit);
		$data.="{$bitso[$l]}".$bit;
	}
	
    // and the final bit of the request
	$data .= "\7in-addr\4arpa\0\0\x0C\0\1";
		
    // create UDP socket
	$errno = $errstr = 0;
    $fp = fsockopen( "udp://{$dns}", 53, $errno, $errstr, $timeout );
	if( ! $fp || ! is_resource( $fp ) )
		return $errno;

	if( function_exists( 'socket_set_timeout' ) ) {
		socket_set_timeout( $fp, $timeout );
	} elseif ( function_exists( 'stream_set_timeout' ) ) {
		stream_set_timeout( $fp, $timeout );
	}


    // send our request (and store request size so we can cheat later)
    $requestsize = fwrite( $fp, $data );
	$max_rx = $requestsize * 3;
	
	$start = time();
	$responsesize = 0;
	while ( $received < $max_rx && ( ( time() - $start ) < $timeout ) && ($buf = fread( $fp, 1 ) ) !== false ) {
		$responsesize++;
		$response .= $buf;
	}
	//echo "[tx: $requestsize bytes]  [rx: {$responsesize} bytes]";

    // hope we get a reply
    if ( is_resource( $fp ) )
		fclose( $fp );

	// if empty response or bad response, return original ip
    if ( empty( $response ) || bin2hex( substr( $response, $requestsize + 2, 2 ) ) != '000c' )
		return $ip;
		
	// set up our variables
	$host = '';
	$len = $loops = 0;
	
	// set our pointer at the beginning of the hostname uses the request size from earlier rather than work it out
	$pos = $requestsize + 12;
	do {
		// get segment size
		$len = unpack( 'c', substr( $response, $pos, 1 ) );
		
		// null terminated string, so length 0 = finished - return the hostname, without the trailing .
		if ( $len[1] == 0 )
			return substr( $host, 0, -1 );
			
		// add segment to our host
		$host .= substr( $response, $pos + 1, $len[1] ) . '.';
		
		// move pointer on to the next segment
		$pos += $len[1] + 1;
		
		// recursion protection
		$loops++;
	}
	while ( $len[1] != 0 && $loops < 20 );
	
	// return the ip in case 
	return $ip;
}


?>

Download and Copy Code

Or download from: gethostbyaddr.txt


function gethostbyaddr_timeout( $ip, $dns, $timeout = 3 ) {
	// idea from http://www.php.net/manual/en/function.gethostbyaddr.php#46869
	// https://www.askapache.com/pub/php/gethostbyaddr.php
	
    // random transaction number (for routers etc to get the reply back)
    $data = rand( 10, 77 ) . "\1\0\0\1\0\0\0\0\0\0";
	
	// octals in the array, keys are strlen of bit
	$bitso = array("","\1","\2","\3" );
	foreach( array_reverse( explode( '.', $ip ) ) as $bit ) {
		$l=strlen($bit);
		$data.="{$bitso[$l]}".$bit;
	}
	
    // and the final bit of the request
	$data .= "\7in-addr\4arpa\0\0\x0C\0\1";
		
    // create UDP socket
	$errno = $errstr = 0;
    $fp = fsockopen( "udp://{$dns}", 53, $errno, $errstr, $timeout );
	if( ! $fp || ! is_resource( $fp ) )
		return $errno;

	if( function_exists( 'socket_set_timeout' ) ) {
		socket_set_timeout( $fp, $timeout );
	} elseif ( function_exists( 'stream_set_timeout' ) ) {
		stream_set_timeout( $fp, $timeout );
	}


    // send our request (and store request size so we can cheat later)
    $requestsize = fwrite( $fp, $data );
	$max_rx = $requestsize * 3;
	
	$start = time();
	$responsesize = 0;
	while ( $responsesize < $max_rx && ( ( time() - $start ) < $timeout ) && ($buf = fread( $fp, 1 ) ) !== false ) {
		$responsesize++;
		$response .= $buf;
	}
	// echo "[tx: $requestsize bytes]  [rx: {$responsesize} bytes]";

    // hope we get a reply
    if ( is_resource( $fp ) )
		fclose( $fp );

	// if empty response or bad response, return original ip
    if ( empty( $response ) || bin2hex( substr( $response, $requestsize + 2, 2 ) ) != '000c' )
		return $ip;
		
	// set up our variables
	$host = '';
	$len = $loops = 0;
	
	// set our pointer at the beginning of the hostname uses the request size from earlier rather than work it out
	$pos = $requestsize + 12;
	do {
		// get segment size
		$len = unpack( 'c', substr( $response, $pos, 1 ) );
		
		// null terminated string, so length 0 = finished - return the hostname, without the trailing .
		if ( $len[1] == 0 )
			return substr( $host, 0, -1 );
			
		// add segment to our host
		$host .= substr( $response, $pos + 1, $len[1] ) . '.';
		
		// move pointer on to the next segment
		$pos += $len[1] + 1;
		
		// recursion protection
		$loops++;
	}
	while ( $len[1] != 0 && $loops < 20 );
	
	// return the ip in case 
	return $ip;
}

PHP fsockopen for FAST DNS lookups over UDP - AskApache

Charles Torvalds
28 Jan 2014

DNS, fsockopen, gethostbyaddr, Google, networking, OpenDNS, PHP, socket, udp, UltraDNS

  • Site Map WireShark GNU Non-GNU Tor Project cURL TLDP - Documentation
  • Htaccess Files Hacking Htaccess Javascript Linux Optimization PHP Security Shell Scripting WordPress
  • Base64 Image Converter Raw HTTP Header Debugger Graphical ASCII Text Generator Mac Address Vendor Lookup Who Am I – Your IP Information Request Method Security Scanner .htpasswd file Generator Compress CSS DNS Tracer
Copyright © 2025 AskApache
  • Site Map
  • Htaccess Files
  • Hacking
  • Htaccess
  • Javascript
  • Linux
  • Optimization
  • PHP
  • Security
  • Shell Scripting
  • WordPress
  • Base64 Image Converter
  • Raw HTTP Header Debugger
  • Graphical ASCII Text Generator
  • Mac Address Vendor Lookup
  • Who Am I – Your IP Information
  • Request Method Security Scanner
  • .htpasswd file Generator
  • Compress CSS
  • DNS Tracer
Exit mobile version