I am getting the IP address of a user using $_SERVER['REMOTE_ADDR'] who tries to visit my site. I have different boxes with different IDS and different CIDR entries in my database for each box. I want to check if the user IP exists in any of the CIDR or not for a specific box. If it exists then he is allowed to enter otherwise not. let suppose the user IP is
127.0.0.1
suppose The CIDR entries for box 12 is
192.168.1.20/27
192.168.0.10/32
The CIDR entries are stored in a column in database
if he come with an IP that comes inside this range then he should be allowed to enter the site otherwise not. I want to check his ip against each CIDR entry.
Any ideas please?
Thanks
Run a network utility such as ipconfig , ifconfig , ip , etc. Look for netmask or Subnet Mask . Common values are 255.255. 255.0 which is CIDR /24 or 255.255.
CIDR addresses are made up of two sets of numbers: a prefix, which is the binary representation of the network address -- similar to what would be seen in a normal IP address -- and a suffix, which declares the total number of bits in the entire address. For example, CIDR notation may look like: 192.168.
Class A IP addresses range from 1.0.0.0 to 127.255.255.255 , with a default mask of 255.0.0.0 (or /8 in CIDR). This means that Class A addressing can have a total of 128 (27) networks and 16,777,214 (224-2) usable addresses per network.
OK, try following this 5 simple steps...
1. Store your CIDRs into array (read 'em from database; guess you know how to get this)
$cidrs = array(
'192.168.1.20/27',
'192.168.0.10/32'
);
2. Get user's IP (remote address)
$user_ip = $_SERVER['REMOTE_ADDR'];
3. Add this function
function IPvsCIDR($user_ip, $cidr) {
$parts = explode('/', $cidr);
$ipc = explode('.', $parts[0]);
foreach ($ipc as &$v)
$v = str_pad(decbin($v), 8, '0', STR_PAD_LEFT);
$ipc = substr(join('', $ipc), 0, $parts[1]);
$ipu = explode('.', $user_ip);
foreach ($ipu as &$v)
$v = str_pad(decbin($v), 8, '0', STR_PAD_LEFT);
$ipu = substr(join('', $ipu), 0, $parts[1]);
return $ipu == $ipc;
}
4. Compare user's IP address against $cidrs
$validaddr = false;
foreach ($cidrs as $addr)
if (IPvsCIDR($user_ip, $addr)) {
$validaddr = true;
break;
}
5. Decide what to do with user
if ($validaddr) {
echo "CORRECT IP ADDRESS";
}
else {
echo "INCORRECT IP ADDRESS";
}
That's it!
how this function works. It converts CIDR address-part (x.x.x.x) into binary string and takes first N digits. Then it does same job with user's IP and checks do values match.
function testUserIP($user_ip, $cidrs) {
$ipu = explode('.', $user_ip);
foreach ($ipu as &$v)
$v = str_pad(decbin($v), 8, '0', STR_PAD_LEFT);
$ipu = join('', $ipu);
$res = false;
foreach ($cidrs as $cidr) {
$parts = explode('/', $cidr);
$ipc = explode('.', $parts[0]);
foreach ($ipc as &$v) $v = str_pad(decbin($v), 8, '0', STR_PAD_LEFT);
$ipc = substr(join('', $ipc), 0, $parts[1]);
$ipux = substr($ipu, 0, $parts[1]);
$res = ($ipc === $ipux);
if ($res) break;
}
return $res;
}
$user_ip = $_SERVER['REMOTE_ADDR'];
$cidrs = array('192.168.1.20/27', '192.168.0.10/32');
if (testUserIP($user_ip, $cidrs)) {
// user ip is ok
}
else {
// access denied
}
I've been using this function for a while:
<?php
/**
* Returns TRUE if given IPv4 address belongs to given network, FALSE otherwhise
*
* @param string $str_ip IP address in '127.0.0.1' format
* @param string $str_range Network and mask as '127.0.0.0/8', '127.0.0.0/255.0.0.0' or '127.0.0.1'
* @return bool
*
* @version v2011-08-30
*/
function ip_belongs_to_network($str_ip, $str_range){
// Extract mask
list($str_network, $str_mask) = array_pad(explode('/', $str_range), 2, NULL);
if( is_null($str_mask) ){
// No mask specified: range is a single IP address
$mask = 0xFFFFFFFF;
}elseif( (int)$str_mask==$str_mask ){
// Mask is an integer: it's a bit count
$mask = 0xFFFFFFFF << (32 - (int)$str_mask);
}else{
// Mask is in x.x.x.x format
$mask = ip2long($str_mask);
}
$ip = ip2long($str_ip);
$network = ip2long($str_network);
$lower = $network & $mask;
$upper = $network | (~$mask & 0xFFFFFFFF);
return $ip>=$lower && $ip<=$upper;
}
Update:
Actually all the CIDR entries are in database in my case. How can I check an IP with all tose CIDR entries will a foreach loop can work?
It depends on how many entries you have. A PHP loop is fine for a couple of ranges, but having 50 of them would imply launching 50 SQL queries! In that case, you should probably switch to a database approach. E.g., you could store ranges in two columns (lower IP address and upper IP address). That way, all you need to do would be this:
$sql = 'SELECT COUNT(1) AS belongs_to_at_least_one_range
FROM ranges
WHERE :remote_address BETWEEN lower_address AND upper_address
LIMIT 1';
$params = array(
'remote_address' => ip2long($_SERVER['REMOTE_ADDR']),
);
(Or fetch all matches if you need that.)
can u please explain this line of code
list($str_network, $str_mask) = array_pad(explode('/', $str_range), 2, NULL);
explode('/', $str_range)
// Split the string at `/` characters
array_pad(explode('/', $str_range), 2, NULL);
// Fill with NULLs if we have less than 2 items
list($str_network, $str_mask) =
// Store first part in `$str_network` and second part in `$str_mask`
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With