Estoy trabajando en un proyecto que usa TypeScript y tengo acceso a un almacenamiento basado en valores clave. El requisito es encontrar datos relacionados con una sola IP (clave de coincidencia).
Desafortunadamente, la clave siempre es un CIDR que cubre muchas IP (para ahorrar almacenamiento debido a muchos registros). Durante mis pruebas no pude encontrar el CIDR correcto perteneciente a una IP específica.
Datos de ejemplo:
"103.21.244.0/24" - "data, lorem ipsum, etc"Ejemplo IP para encontrar:
"103.21.244.1"He probado varias bibliotecas como: ip-address , ip-num , ip-to-int , ipaddr.js y más, pero no puedo obtener el resultado que quiero.
Tal vez solo estoy siendo tonto y no entiendo la especificación de IP correctamente, o tal vez solo estoy haciendo un mal uso de estas bibliotecas, por favor ilumíneme.
Seguramente tiene que haber una manera sin llamar a API externas (como RIPE) y sin tener que almacenar miles de millones de IP en lugar de su CIDR.
Esencialmente, el requisito es bastante simple: "encontrar esta CLAVE (en CIDR) por esta IP (v4 o v6)".
Cualquier ayuda, consejo, soluciones de ejemplo son muy apreciadas.
La dirección IP se puede convertir a un solo número. La forma abcd es una representación en base 256 de un número de 32 bits. Convierta tanto la dirección como la máscara de subred a enteros. Luego use la operación "bit a bit y" para aplicar la máscara a las direcciones IP de destino y comparar con la dirección de red.
function addrToNumber(addr) { return addr.split(".").reduce((acc,cur,i)=> acc += (Number(cur) << ( (3-i) * 8) ) ,0) } function subnetMaskToNumber(mask) { return (0xffffffff << (32 - Number(mask))) & 0xffffffff; } const cidr = "103.21.244.0/24"; const [networkAddr,subnetMask] = cidr.split("/"); const ipAddr = "103.21.244.1"; const match = (addrToNumber(ipAddr) & subnetMaskToNumber(subnetMask)) == addrToNumber(networkAddr) console.log(match);Para generar todos los CIDR posibles para una dirección IP:
function addrToNumber(addr) { return addr.split(".").reduce((acc,cur,i)=> acc += (Number(cur) << ( (3-i) * 8) ) ,0) } function numberToAddr(num) { return `${(num >> 24) & 0xff}.${(num >> 16) & 0xff}.${(num >> 8) & 0xff}.${num & 0xff}` } const ipAddr = "103.21.244.1"; const ipValue = addrToNumber(ipAddr); let possibleCIDR = [...Array(33)].map((_,i)=>{ let mask = i == 0 ? 0 : (0xffffffff << (32 - i)) >>> 0; return `${numberToAddr(ipValue & mask)}/${i}`; }); console.log(possibleCIDR);Para generar posibles CIDR para IPv6, no se maneja la compresión de ceros.
const ipv6 = "2001:db8:85a3:8d3:1319:8a2e:370:7348"; const groups = ipv6.split(":"); let possibleCIDR = [...Array(129)].map((_,i)=>{ let groupIndex = Math.floor(i / 16); let mask = (i % 16) ? (0xffff << (16 - (i % 16))) & 0xffff : 0; return groups.map((value,j)=>{ return (j < groupIndex ? value : j == groupIndex ? parseInt(value,16) & mask : 0).toString(16) }).join(":") + `/${i}`; }); console.log(possibleCIDR);