vlsm subredes subneteo redes paso online convertir calculo calcular calculadora binario php ip cidr

subredes - Obtención de la lista de direcciones IP de la notación CIDR en PHP



subneteo de redes (12)

Aquí hay una función rápida de 64 bits para hacerlo, por favor comente la línea de retorno que no necesita. Aceptar cualquier Ipv4 válido con o sin un prefijo de enrutamiento CIDR válido, por ejemplo, 63.161.156.0/ 24 o 63.161.156.0

<?php function cidr2range($ipv4){ if ($ip=strpos($ipv4,''/'')) {$n_ip=(1<<(32-substr($ipv4,1+$ip)))-1; $ip_dec=ip2long(substr($ipv4,0,$ip)); } else {$n_ip=0; $ip_dec=ip2long($ipv4); } $ip_min=$ip_dec&~$n_ip; $ip_max=$ip_min+$n_ip; #Array(2) of Decimal Values Range return [$ip_min,$ip_max]; #Array(2) of Ipv4 Human Readable Range return [long2ip($ip_min),long2ip($ip_max)]; #Array(2) of Ipv4 and Subnet Range return [long2ip($ip_min),long2ip(~$n_ip)]; #Array(2) of Ipv4 and Wildcard Bits return [long2ip($ip_min),long2ip($n_ip)]; #Integer Number of Ipv4 in Range return ++$n_ip; }

Para ejecutarse rápidamente, la función no verifica la entrada, pero formalmente debe ser una cadena que coincida con la siguiente expresión regular

#^(?:((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))/.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))/.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))/.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))(?:/((?:(?:0)|(?:3[0-2])|(?:[1-2]?[0-9]))))?)$#

Si desea verificar la entrada antes de usar la función

<?php if (is_string($ipv4) && preg_match(''#^(?:((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))/.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))/.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))/.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))(?:/((?:(?:0)|(?:3[0-2])|(?:[1-2]?[0-9]))))?)$#'',$ipv4)) { #This is a valid ipv4 with or without CIDR Routing Prefix $result=cidr2range($ipv4); print_r($result); }

Para obtener el rango completo como una matriz para una IP determinada (con o sin el prefijo de enrutamiento CIDR) puede usar el siguiente código pero tenga cuidado porque, por ejemplo, 25.25.25.25/16, devuelva una matriz con 65536 elementos y puede quedarse sin ella fácilmente. memoria utilizando un prefijo de enrutamiento más pequeño

<?php $result=cidr2range($ipv4); for($ip_dec=$result[0];$ip_dec<=$result[1];$ip_dec++) $full_range[$ip_dec]=long2ip($ip_dec); print_r($full_range);

Para comprobar rápidamente si un determinado ipv4 coincide con un CIDR determinado , puede hacerlo en línea como en este ejemplo

<?php $given_cidr=''55.55.55.0/24''; $given_ipv4=''55.55.55.55''; if(($range=cidr2range($given_cidr)) && ($check=ip2long($given_ipv4))!==false && $check>=$range[0] && $check<=$range[1]) { echo ''Yes, ''.$given_ipv4.'' is included in ''.$given_cidr; } else { echo ''No, ''.$given_ipv4.'' is not included in ''.$given_cidr; }

Para comprobar rápidamente si un determinado ipv4 coincide con una matriz determinada de IP (con o sin el prefijo de enrutamiento CIDR)

<?php #This code is checking if a given ip belongs to googlebot $given_ipv4=''74.125.61.208''; $given_cidr_array=[''108.59.93.43/32'',''108.59.93.40/31'',''108.59.93.44/30'',''108.59.93.32/29'',''108.59.93.48/28'',''108.59.93.0/27'',''108.59.93.64/26'',''108.59.93.192/26'',''108.59.92.192/27'',''108.59.92.128/26'',''108.59.92.96/27'',''108.59.92.0/27'',''108.59.94.208/29'',''108.59.94.192/28'',''108.59.94.240/28'',''108.59.94.128/26'',''108.59.94.16/29'',''108.59.94.0/28'',''108.59.94.32/27'',''108.59.94.64/26'',''108.59.95.0/24'',''108.59.88.0/22'',''108.59.81.0/27'',''108.59.80.0/24'',''108.59.82.0/23'',''108.59.84.0/22'',''108.170.217.128/28'',''108.170.217.160/27'',''108.170.217.192/26'',''108.170.217.0/25'',''108.170.216.0/24'',''108.170.218.0/23'',''108.170.220.0/22'',''108.170.208.0/21'',''108.170.192.0/20'',''108.170.224.0/19'',''108.177.0.0/17'',''104.132.0.0/14'',''104.154.0.0/15'',''104.196.0.0/14'',''107.167.160.0/19'',''107.178.192.0/18'',''125.17.82.112/30'',''125.16.7.72/30'',''74.125.0.0/16'',''72.14.192.0/18'',''77.109.131.208/28'',''77.67.50.32/27'',''66.102.0.0/20'',''66.227.77.144/29'',''66.249.64.0/19'',''67.148.177.136/29'',''64.124.98.104/29'',''64.71.148.240/29'',''64.68.64.64/26'',''64.68.80.0/20'',''64.41.221.192/28'',''64.41.146.208/28'',''64.9.224.0/19'',''64.233.160.0/19'',''65.171.1.144/28'',''65.170.13.0/28'',''65.167.144.64/28'',''65.220.13.0/24'',''65.216.183.0/24'',''70.32.132.0/23'',''70.32.128.0/22'',''70.32.136.0/21'',''70.32.144.0/20'',''85.182.250.128/26'',''85.182.250.0/25'',''80.239.168.192/26'',''80.149.20.0/25'',''61.246.224.136/30'',''61.246.190.124/30'',''63.237.119.112/29'',''63.226.245.56/29'',''63.158.137.224/29'',''63.166.17.128/25'',''63.161.156.0/24'',''63.88.22.0/23'',''41.206.188.128/26'',''12.234.149.240/29'',''12.216.80.0/24'',''8.34.217.24/29'',''8.34.217.0/28'',''8.34.217.32/27'',''8.34.217.64/26'',''8.34.217.128/25'',''8.34.216.0/24'',''8.34.218.0/23'',''8.34.220.0/22'',''8.34.208.128/29'',''8.34.208.144/28'',''8.34.208.160/27'',''8.34.208.192/26'',''8.34.208.0/25'',''8.34.209.0/24'',''8.34.210.0/23'',''8.34.212.0/22'',''8.35.195.128/28'',''8.35.195.160/27'',''8.35.195.192/26'',''8.35.195.0/25'',''8.35.194.0/24'',''8.35.192.0/23'',''8.35.196.0/22'',''8.35.200.0/21'',''8.8.8.0/24'',''8.8.4.0/24'',''8.6.48.0/21'',''4.3.2.0/24'',''23.236.48.0/20'',''23.251.128.0/19'',''216.239.32.0/19'',''216.252.220.0/22'',''216.136.145.128/27'',''216.33.229.160/29'',''216.33.229.144/29'',''216.34.7.176/28'',''216.58.192.0/19'',''216.109.75.80/28'',''216.74.130.48/28'',''216.74.153.0/27'',''217.118.234.96/28'',''208.46.199.160/29'',''208.44.48.240/29'',''208.21.209.0/28'',''208.184.125.240/28'',''209.185.108.128/25'',''209.85.128.0/17'',''213.200.103.128/26'',''213.200.99.192/26'',''213.155.151.128/26'',''199.192.112.224/29'',''199.192.112.192/27'',''199.192.112.128/26'',''199.192.112.0/25'',''199.192.113.176/28'',''199.192.113.128/27'',''199.192.113.192/26'',''199.192.113.0/25'',''199.192.115.80/28'',''199.192.115.96/27'',''199.192.115.0/28'',''199.192.115.128/25'',''199.192.114.192/26'',''199.192.114.0/25'',''199.223.232.0/21'',''198.108.100.192/28'',''195.16.45.144/29'',''192.104.160.0/23'',''192.158.28.0/22'',''192.178.0.0/15'',''206.160.135.240/28'',''207.223.160.0/20'',''203.222.167.144/28'',''173.255.125.72/29'',''173.255.125.80/28'',''173.255.125.96/27'',''173.255.125.0/27'',''173.255.125.128/25'',''173.255.124.240/29'',''173.255.124.232/29'',''173.255.124.192/27'',''173.255.124.128/29'',''173.255.124.144/28'',''173.255.124.160/27'',''173.255.124.48/29'',''173.255.124.32/28'',''173.255.124.0/27'',''173.255.124.64/26'',''173.255.126.0/23'',''173.255.122.128/26'',''173.255.122.64/26'',''173.255.123.0/24'',''173.255.121.128/26'',''173.255.121.0/25'',''173.255.120.0/24'',''173.255.117.32/27'',''173.255.117.64/26'',''173.255.117.128/25'',''173.255.116.192/27'',''173.255.116.128/26'',''173.255.116.0/25'',''173.255.118.0/23'',''173.255.112.0/22'',''173.194.0.0/16'',''172.102.8.0/21'',''172.253.0.0/16'',''172.217.0.0/16'',''162.216.148.0/22'',''162.222.176.0/21'',''180.87.33.64/26'',''128.177.109.0/26'',''128.177.119.128/25'',''128.177.163.0/25'',''130.211.0.0/16'',''142.250.0.0/15'',''146.148.0.0/17'']; echo ''<pre>''; $in_range=false; if (($given_ipv4_dec=ip2long($given_ipv4))!==false) { foreach($given_cidr_array as $given_cidr){ if(($range=cidr2range($given_cidr)) && $given_ipv4_dec>=$range[0] && $given_ipv4_dec<=$range[1]) { $in_range=true; echo $given_ipv4.'' matched ''.$given_cidr.'' (''.join(array_map(''long2ip'',$range),'' - '').")/n"; } } } echo $given_ipv4.'' is probably''.($in_range?'''':'' not'').'' a Googlebot IP'';

Espero que estas pocas líneas te hayan ayudado ...

¿Hay alguna forma (o función / clase) de obtener la lista de direcciones IP de una notación CIDR?

Por ejemplo, tengo 73.35.143.32/27 CIDR y quiero obtener la lista de todos los IP en esta notación. ¿Alguna sugerencia?

Gracias.


Bueno, es una máscara de bits: 73.35.143.32/27 significa que 27 bits son la máscara de red, y el resto está disponible para asignar a los nodos de la red:

73.35.143.32

en binario es esto (puntos mostrados para legibilidad):

01001001.00100011.10001111.00100000

La máscara de red es de 27 bits:

11111111.11111111.11111111.11100000

Así que solo pueden Y Juntos y obtener esto:

01001001.00100011.10001111.001 00000 network prefix (27 bits) | node address (5 bits)

Desde aquí, puede simplemente enumerar todas las combinaciones en la dirección del nodo (00000 es 0, 11111 es 31, por lo que un simple bucle es suficiente), y tendrá todos los hosts disponibles.

La conversión de este pseudocódigo a PHP se deja como un ejercicio para el lector;)

Ah, y la advertencia de desaprobación obligatoria: IPv4 ahora está lleno, considere también IPv6.


Editaré la class aforementioned para contener un método para eso. Aquí está el código que se me ocurrió que podría ayudarte hasta entonces.

function cidrToRange($cidr) { $range = array(); $cidr = explode(''/'', $cidr); $range[0] = long2ip((ip2long($cidr[0])) & ((-1 << (32 - (int)$cidr[1])))); $range[1] = long2ip((ip2long($range[0])) + pow(2, (32 - (int)$cidr[1])) - 1); return $range; } var_dump(cidrToRange("73.35.143.32/27")); //////////////////OUTPUT//////////////////////// // array(2) { // [0]=> // string(12) "73.35.143.32" // [1]=> // string(12) "73.35.143.63" // } /////////////////////////////////////////////////

Devuelve el extremo inferior del rango de ip como la primera entrada de la matriz, y luego devuelve el extremo superior como la segunda entrada.


Esto devuelve una matriz de ips:

function get_list_ip($ip_addr_cidr){ $ip_arr = explode("/", $ip_addr_cidr); $bin = ""; for($i=1;$i<=32;$i++) { $bin .= $ip_arr[1] >= $i ? ''1'' : ''0''; } $ip_arr[1] = bindec($bin); $ip = ip2long($ip_arr[0]); $nm = $ip_arr[1]; $nw = ($ip & $nm); $bc = $nw | ~$nm; $bc_long = ip2long(long2ip($bc)); for($zm=1;($nw + $zm)<=($bc_long - 1);$zm++) { $ret[]=long2ip($nw + $zm); } return $ret; }


Esto se repite en cada dirección IP en un bloque CIDR usando una función anónima:

cidrl(''194.168.0.1/28'', $error_code, function($address) { // Do something. print "$address/n"; });

O, como una matriz:

$addresses = cidrl(''194.168.0.1/28'', $error_code);

Fuente:

function cidrl($cidr, &$error_code = 0, $callback = null) { $error_code = 0; sscanf($cidr, "%[^/]/%u", $network, $bits); $addr = ip2long($network); if ($addr === false) { $error_code = 2; return false; } if ($bits == 32) { if (is_callable($callback)) { $callback(long2ip($addr)); return array(); } return array(long2ip($addr)); } if ($bits > 32) { $error_code = 3; return false; } $mask = ~(0xFFFFFFFF >> $bits); $addr_start = $addr & $mask; $addr_end = ($addr & $mask) | ~$mask; $addresses = array(); for ($i = $addr_start; $i <= $addr_end; $i++) { if (is_callable($callback)) $callback(long2ip($i)); else $addresses[] = long2ip($i); } return $addresses; }

Código de: https://github.com/emden-norfolk/cidrl/tree/master/php


Extensión a la respuesta de @jonavon . Si necesita lista plana de IPs. Puedes convertir su función como abajo.

function cidrToRange($value) { $range = array(); $split = explode(''/'', $value); if (!empty($split[0]) && is_scalar($split[1]) && filter_var($split[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { $rangeStart = ip2long($split[0]) & ((-1 << (32 - (int)$split[1]))); $rangeEnd = ip2long($split[0]) + pow(2, (32 - (int)$split[1])) - 1; for ($i = $rangeStart; $i <= $rangeEnd; $i++) { $range[] = long2ip($i); } return $range; } else { return $value; } }


Hay una pequeña solución: cuando alguien coloca un prefijo de IP como: 127.0.0.15/26, esta función devuelve la última dirección IP mala. En esta función está en la línea 4 (comienza: $ rango [1] ...) cambiado $ cidr [0] a $ rango [0] - ahora su retorno es la última dirección IP válida para cada IP dentro del rango.

function cidrToRange($cidr) { $range = array(); $cidr = explode(''/'', $cidr); $range[0] = long2ip((ip2long($cidr[0])) & ((-1 << (32 - (int)$cidr[1])))); $range[1] = long2ip((ip2long($range[0])) + pow(2, (32 - (int)$cidr[1])) - 1); return $range; } var_dump(cidrToRange("127.0.0.15/26"));

Antes de arreglar

array(2) { [0]=> string(9) "127.0.0.0" [1]=> string(10) "127.0.0.78" } string(41) "127.0.0.15/26 >> 2130706432 -> 2130706510"

Después de arreglar

array(2) { [0]=> string(9) "127.0.0.0" [1]=> string(10) "127.0.0.63" } string(41) "127.0.0.15/26 >> 2130706432 -> 2130706495"


Hej. También necesitaba esta función y edito 1 otra para devolverme la lista de todas las direcciones IP del rango. Esto devolverá la lista de direcciones IP de la notación CIDR. Disfrútala ;)

<?php $ip_addr_cidr = "192.256.0.0/16"; $ip_arr = explode(''/'', $ip_addr_cidr); $bin = ''''; for($i=1;$i<=32;$i++) { $bin .= $ip_arr[1] >= $i ? ''1'' : ''0''; } $ip_arr[1] = bindec($bin); $ip = ip2long($ip_arr[0]); $nm = ip2long($ip_arr[1]); $nw = ($ip & $nm); $bc = $nw | (~$nm); echo "Number of Hosts: " . ($bc - $nw - 1) . "<br/>"; echo "Host Range: " . long2ip($nw + 1) . " -> " . long2ip($bc - 1) . "<br/>". "<br/>"; for($zm=1;($nw + $zm)<=($bc - 1);$zm++) { echo long2ip($nw + $zm). "<br/>"; } ?>


No creo que class devuelva una lista de direcciones IP, pero proporciona algunos métodos útiles para trabajar con bloques CIDR.


Se me ocurre una mejor idea

$ip_from= long2ip(ip2long($ip)& (-1<<(32-$net_mask))); $ip_to= long2ip(ip2long($ip)| (~(-1<<(32-$net_mask))));

PS: $ ip es una dirección ipv4 como 60.12.34.5; $ net_mask es una máscara int net como 25;

Es muy rápido debido a la operación de cambio de bit


Tuve algunos problemas con las versiones anteriores, varios errores de PHP como un offset indefinido, etc.

Encontré lo que creo que es una mejor manera de hacerlo sin los errores que se detallan a continuación.

Esto toma las direcciones IP de notación CIDR de IPV4 y se puede usar para obtener las direcciones IP de inicio / finalización del rango de CIDR o contar el número total de direcciones IP en una base de datos de direcciones IP.

$count = 0; $result = $sia_db_con->query("SELECT `ip_address` FROM `ip4` WHERE `ip_ban_active`=''True'' ORDER BY ip4.added ASC"); while ($row = $result->fetch_array()) { $pos = strpos($row[0], "/"); $ip_arr = [0 => substr($row[0], 0, $pos), 1 => substr($row[0], $pos+1)]; $start = cidr2ip($ip_arr)[0]; $end = cidr2ip($ip_arr)[1]; $count = $count + (ip2long($end) - ip2long($start)) + 1; } unset($result, $row, $pos, $ip_arr, $start, $end, $range); function cidr2ip($cidr) { $start = ip2long($cidr[0]); $nm = $cidr[1]; $num = pow(2, 32 - $nm); $end = $start + $num - 1; $range = [0 => $cidr[0], 1 => long2ip($end)]; unset($start, $nm, $num, $end); return $range; }

El secreto aquí es la forma en que creo la variable $ ip_arr. En lugar de utilizar PHP Explode, establezco las dimensiones de la matriz manualmente para cada dirección IP. Esta es, por supuesto, una versión de la base de datos del código y se desplaza por todas las direcciones IP de la base de datos que cumplen los criterios de búsqueda.


Versión fija del script Kosmonaft:

function get_list_ip($ip_addr_cidr){ $ip_arr = explode("/", $ip_addr_cidr); $bin = ""; for($i=1;$i<=32;$i++) { $bin .= $ip_arr[1] >= $i ? ''1'' : ''0''; } $ip_arr[1] = bindec($bin); $ip = ip2long($ip_arr[0]); $nm = $ip_arr[1]; $nw = ($ip & $nm); $bc = $nw | ~$nm; $bc_long = ip2long(long2ip($bc)); echo "Number of Hosts: " . ($bc_long - $nw - 1) . "<br/>"; echo "Host Range: " . long2ip($nw + 1) . " -> " . long2ip($bc - 1) . "<br/>". "<br/>"; for($zm=1;($nw + $zm)<=($bc_long - 1);$zm++) { echo long2ip($nw + $zm). "<br/>"; } }