Check if an IP address is private
Ok this is 7 years old post. But I thought I can share my solution, so that maybe someone somewhere somehow might find it helpful.
My solution is based on the builtin PHP filter_var() function. Which means I do not have to pre-define all the private ranges or the reserved ones every single time I need to validate a given value. Or loop through the ranges. Instead I let PHP worries about it for me.
class IP
{
static public function is_ip($ip=NULL) : bool
{
return filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6
) === $ip ? TRUE : FALSE;
}
static public function is_ipv4($ip=NULL) : bool
{
return filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4
) === $ip ? TRUE : FALSE;
}
static public function is_ipv6($ip=NULL) : bool
{
return filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_IPV6
) === $ip ? TRUE : FALSE;
}
static public function is_public_ip($ip=NULL) : bool
{
return filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
) === $ip ? TRUE : FALSE;
}
static public function is_public_ipv4($ip=NULL) : bool
{
return filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
) === $ip ? TRUE : FALSE;
}
static public function is_public_ipv6($ip=NULL) : bool
{
return filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
) === $ip ? TRUE : FALSE;
}
static public function is_private_ip($ip=NULL) : bool
{
return self::is_ip($ip) && !self::is_public_ip($ip);
}
static public function is_private_ipv4($ip=NULL) : bool
{
return self::is_ipv4($ip) && !self::is_public_ipv4($ip);
}
static public function is_private_ipv6($ip=NULL) : bool
{
return self::is_ipv6($ip) && !self::is_public_ipv6($ip);
}
}
It allows you to validate the given value in general whether or not it is an IP. or be more specific about it. you can validate the following types:
- IP
- IPv4
- IPv6
- public IP
- public IPv4
- public IPv6
- private IP
- private IPv4
- private IPv6
let's test it:
$arr = array(
'127.0.0.0', '127.0.0.1', '127.1.2.3', '127.1.2.255',
'192.168.0.0', '192.168.0.1', '192.168.2.3', '192.168.2.255',
'172.16.0.0', '172.16.0.1', '172.16.2.3', '172.16.2.255',
'172.19.0.0', '172.19.0.1', '172.19.2.3', '172.19.2.255',
'10.0.0.0', '10.0.0.1', '10.0.2.3', '10.0.2.255',
'10.5.0.0', '10.5.0.1', '10.5.2.3', '10.5.2.255',
'8.8.8.8', '8.8.4.4', '255.255.255',
'182.168.1.300', '256.1.2.3', '0.500.0.0',
'I am not an IP', NULL, '185.128.72.151'
);
foreach ($arr as $item) {
echo "$item --> " . (IP::is_private_ip($item) === TRUE ? 'is private' : 'is NOT private or NOT an IP') . PHP_EOL;
}
I think this should solve the problem.
filter_var used with the following validation rules will return false if the IP address is a private one.
$user_ip = '127.0.0.1';
filter_var(
$user_ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
)
Check the links above for the php documentation
function ip_is_private ($ip) {
$pri_addrs = array (
'10.0.0.0|10.255.255.255', // single class A network
'172.16.0.0|172.31.255.255', // 16 contiguous class B network
'192.168.0.0|192.168.255.255', // 256 contiguous class C network
'169.254.0.0|169.254.255.255', // Link-local address also refered to as Automatic Private IP Addressing
'127.0.0.0|127.255.255.255' // localhost
);
$long_ip = ip2long ($ip);
if ($long_ip != -1) {
foreach ($pri_addrs AS $pri_addr) {
list ($start, $end) = explode('|', $pri_addr);
// IF IS PRIVATE
if ($long_ip >= ip2long ($start) && $long_ip <= ip2long ($end)) {
return true;
}
}
}
return false;
}
See http://mebsd.com/coding-snipits/check-private-ip-function-php.html
You might also want to check out about the private address spaces here