blog
Get an IP range for a domain using PHP
One of my server hosting providers tells me that outgoing traffic from their data center can have any IP address within a /22 range. So starting with the domain, I wanted to create a list of all of the IP addresses within that range to put in a whitelist. This was actually a bit trickier than it sounds. I ended up using a lot of binary operators and bitwise masking. Since PHP doesn’t support unsigned int’s, I had to do a bit of extra masking to account for a possible sign bit. So here’s my code (below). I execute an nslookup and then parse the results for the IP address. I then apply the range mask and create an array of IP addresses. This code works for both Windows and Linux.
<?php
define ('CRLF', "\r\n");
setlocale(LC_ALL, 'us');
date_default_timezone_set("UTC");
header('Content-Type: text/plain');
$ips = getip('pmierau.com/30');
foreach ($ips as $ip)
print $ip.CRLF;
exit;
/*
* Get the array of IP addresses for a specific domain
*
* If a range is specified for the domain (i.e. xyz.com/24), the returned array returns
* IP aaddresses for the entire range (i.e. 256 addresses for a /24 range)
*/
function getip($url)
{
$ips = array();
$urlparts = explode('/', $url);
if (isset($urlparts[1]))
{
$range = (int)$urlparts[1];
$url = $urlparts[0];
}
else
{
$range = 0;
}
$cmd = 'nslookup '.$url;
$descriptorspec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w"));
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process))
{
$results = stream_get_contents($pipes[1]);
$results .= stream_get_contents($pipes[2]);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
$return_value = proc_close($process);
// Parse the font information
$lines = explode("\n", $results);
$answer = false;
foreach ($lines as $line)
{
$line = trim($line);
if (false !== strpos($line, $url))
{
$answer = true;
}
elseif ($answer && ((false !== strpos($line, 'Address:')) || (false !== strpos($line, 'Addresses:'))))
{
$parts = explode(':', $line);
$ip = trim($parts[1]);
if ($range == 0)
{
$ips[] = $ip;
}
else
{
$binaryip = binaryip($ip);
$mask = (0xffffffff << (32 - $range)) & 0xffffffff;
$startbinaryip = $binaryip & $mask;
$n = (~$mask) + 1;
for ($ip = $startbinaryip, $i = $n; $i != 0; $ip++, $i--)
$ips[] = ipv4ip($ip);
}
return $ips;
}
}
}
$ips[] = '?.?.?.?';
return $ips;
}
/*
* Convert an IPV4 address to it's binary equivalent
*/
function binaryip($ip)
{
$ipparts = explode('.', $ip);
$binaryip = 0;
foreach ($ipparts as $ippart)
{
$binaryip = $binaryip << 8;
$binaryip |= (int)$ippart;
}
return $binaryip;
}
/*
* Convert a binary IP address to traditional IPV4 format
*/
function ipv4ip($binaryip)
{
$ip1 = (($binaryip & 0xff000000) >> 24) & 0x000000ff;
$ip2 = ($binaryip & 0x00ff0000) >> 16;
$ip3 = ($binaryip & 0x0000ff00) >> 8;
$ip4 = ($binaryip & 0x000000ff);
return $ip1.'.'.$ip2.'.'.$ip3.'.'.$ip4;
}
?>
This entry was posted on Thursday, March 8th, 2012 at 5:39 pm and is filed under Software Development . You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
