UNPKG

get-ip-range

Version:

Simple utility to convert either CIDR notation or two IP addresses to an array of the range of IP addresses

113 lines (87 loc) 2.9 kB
import { toLong, fromLong } from 'ip'; // @ts-ignore import { Address4, Address6 } from 'ip-address'; // Set default max range let maxRange = 10000; const getIPv4 = (ip: string): Address4 | null => { try { return new Address4(ip); } catch (err) { return null; } }; const getIPv6 = (ip: string): Address6 | null => { try { return new Address6(ip); } catch (err) { return null; } }; const getRangev4 = (ip1: string, ip2: string) => { const ips = []; let firstAddressLong = toLong(ip1); const lastAddressLong = toLong(ip2); const totalIPs = lastAddressLong - firstAddressLong; // Prevent DoS if (totalIPs > maxRange) { throw new Error(`Too many IPs in range. Total number: ${totalIPs}. Max count is ${maxRange}, to increase, set the limit with the MAX_RANGE environment variable`) } for (firstAddressLong; firstAddressLong <= lastAddressLong; firstAddressLong++) ips.push(fromLong(firstAddressLong)); return ips; }; const getRangev6 = (ip1: string, ip2: string) => { const ips = []; const firstAddress = new Address6(ip1); const lastAddress = new Address6(ip2); for (let i = firstAddress.bigInteger(); i <= lastAddress.bigInteger(); i++) { ips.push(Address6.fromBigInteger(i).correctForm()); } return ips; }; const isCIDR = (ipCIDR: Address4 | Address6): boolean => Boolean(ipCIDR.parsedSubnet); const isRange = (ipRange: string): boolean => ipRange.indexOf('-') !== -1; const getIPRange = (ip1: string, ip2?: string): string[] => { if (process.env.MAX_RANGE && isNaN(parseInt(process.env.MAX_RANGE, 10))) { throw new Error('MAX_RANGE must be an integer'); } maxRange = parseInt(process.env.MAX_RANGE || '10000', 10); const ip1v4 = getIPv4(ip1); const ip1v6 = getIPv6(ip1); // // Two IPs // if (ip2) { // IPv4 const ip2v4 = getIPv4(ip2); if (ip1v4.valid && ip2v4.valid && !ip1v4.parsedSubnet && !ip2v4.parsedSubnet) { return getRangev4(ip1v4.correctForm(), ip2v4.correctForm()); } // IPv6 const ip2v6 = getIPv6(ip2); if (ip1v6.valid && ip2v6.valid && !ip1v6.parsedSubnet && !ip2v6.parsedSubnet) { return getRangev6(ip1v6.correctForm(), ip2v6.correctForm()); } // IPs do not match version, or are invalid throw new Error('Cannot get range of two IPs if they are not both valid and the same version'); } // // CIDR // if (isCIDR(ip1v4)) { return getRangev4(ip1v4.startAddress().correctForm(), ip1v4.endAddress().correctForm()); } if (isCIDR(ip1v6)) { return getRangev6(ip1v6.startAddress().correctForm(), ip1v6.endAddress().correctForm()); } // // Hyphenated Range // if (isRange(ip1)) { const [firstAddress, lastAddress] = ip1.split('-'); return getIPRange(firstAddress, lastAddress); } // Did not match any of the above throw new Error('IP supplied is not valid'); }; export { getIPRange };