我正在尝试在给定IP地址子网的情况下生成一个随机IP地址。有大量资源可用于生成随机IP,但我要求它可以从特定子网内生成。
我使用了一个名为netmask的npm模块-但是实现起来绝对不是很完美。谁能给我一些巧妙的建议吗?
var netmask = require("netmask").Netmask
var block = new netmask('10.0.0.0/24')
console.log(block) // gives block details
var blockSize = block.size - 1 ;
var randomIndex = Math.floor(Math.random() * blockSize ) +1; // generate a random number less than the size of the block
console.log("randomIndex is: " + randomIndex);
block.forEach(function(ip, long, index){
if(index == randomIndex){
console.log('IP: ' + ip)
console.log('INDEX: ' + index)
// cannot break! this is a forEach :(
}
});
答案 0 :(得分:4)
这很容易,没有任何其他依赖关系,尽管我没有给您确切的答案,但可以了解IP的总体工作方式以及如何解决您的问题。如果您自己这样做,那么本课将更有价值。
让我们以10.0.0.0/20
CIDR为例。让我们将10.0.0.0
转换为位:
00001010.00000000.00000000.00000000
由于这是从左侧开始的网络,因此我们剥离了20位,因此对于主机,我们只剩下0000.00000000
(这里的.
点仅出于可读性):
00001010.00000000.00000000.00000000 Network
XXXXXXXX.XXXXXXXX.XXXX0000.00000000 Strip 20 bits of the subnet
无论如何,都用剩余比特对每个八位字节进行混洗,例如,我们可以得到0101.10001010
。避免只使用1
(1111.11111111
)的主机,因为它是广播IP,它仍然是有效的IP,尽管对于主机而言却不是。将子网部分与主机部分连接在一起。我们得到:
// S=Subnet, H=Host
SSSSSSSS.SSSSSSSS.SSSSHHHH.HHHHHHHH
00001010.00000000.00000101.10001010
是10.0.5.138
。由于编写过程很有趣,因此我可以为您提供自己的实现,该实现不涉及任何字符串操作。如您所见,IPv4地址是2 ^ 32无符号整数。因此,我们可以应用基本数学。
let ipv4 = {
random: function (subnet, mask) {
// generate random address (integer)
// if the mask is 20, then it's an integer between
// 1 and 2^(32-20)
let randomIp = Math.floor(Math.random() * Math.pow(2, 32 - mask)) + 1;
return this.lon2ip(this.ip2lon(subnet) | randomIp);
},
ip2lon: function (address) {
let result = 0;
address.split('.').forEach(function(octet) {
result <<= 8;
result += parseInt(octet, 10);
});
return result >>> 0;
},
lon2ip: function (lon) {
return [lon >>> 24, lon >> 16 & 255, lon >> 8 & 255, lon & 255].join('.');
}
};
// unit test
console.log(
"192.168.0.35" === ipv4.lon2ip(ipv4.ip2lon('192.168.0.35')) ?
'Test passed' :
'Test failed'
);
for (let i = 0; i < 5; i++) {
console.log(ipv4.random('10.0.0.0', 8));
}
答案 1 :(得分:1)
(我在等您发布我的函数,然后再发布我的函数。)
这是我自己的版本,基于emix的答案。
我试图使用循环和数组函数使其最容易理解。
第一个代码段
// Function to convert string of numbers to 01010101 with leading zeros
function StrToBlock(str) {
return ("00000000" + (+str).toString(2)).slice(-8);
}
// Function to convert 01010101 to string of numbers
function BlockToStr(block) {
return parseInt(block, 2);
}
// Main function
function GetRandomIP(netmask) {
// Split netmask
var netmasks = netmask.split("/");
var maskBlocks = netmasks[0].split(".");
var maskLength = netmasks[1];
// Loop for each address part
var blockBits = '';
maskBlocks.forEach(function(block) {
// Convert to bits
blockBits = blockBits + StrToBlock(block);
});
// Here, blockBits is something like 00110101001101010011010100110101
// Loop for each bit
var ipBits = [];
var ipBlocks = [];
for (var i = 0; i < 32; i++) {
// If in mask, take the mask bit, else, a random 0 or 1
var bit = (i < maskLength) ? blockBits[i] : Math.round(Math.random());
ipBits.push(bit);
// If block is full, convert back to a decimal string
if (ipBits.length == 8) {
ipBlocks.push(BlockToStr(ipBits.join('')));
ipBits = []; // Erase to start a new block
}
}
// Return address as string
return ipBlocks.join('.');
}
// Different tests
console.log(GetRandomIP('255.255.255.0/8'));
console.log(GetRandomIP('255.255.255.0/24'));
console.log(GetRandomIP('10.0.0.0/24'));
⋅ ⋅ ⋅
第二个片段 (我认为已增强)
// Function to convert string of numbers to 01010101 with leading zeros
function StrToBlock(str) {
return ("00000000" + (+str).toString(2)).slice(-8);
}
// Function to convert 01010101 to string of numbers
function BlockToStr(block) {
return parseInt(block, 2);
}
// Main function
function GetRandomIP(netmask) {
// Split netmask
var netmasks = netmask.split("/");
var maskBlocks = netmasks[0].split(".");
var maskLength = netmasks[1];
// Loop for each of the 4 address parts
var blockBits = '';
maskBlocks.forEach(function(block) {
blockBits = blockBits + StrToBlock(block);
});
// Copy mask and then add some random bits
var ipBits = blockBits.substring(0, maskLength);
for (var i = maskLength; i < 32; i++) {
ipBits = ipBits + Math.round(Math.random());
}
// Split and convert back to decimal strings
var ipBlocks = ipBits.match(/.{8}/g);
ipBlocks.forEach(function(block, i) {
ipBlocks[i] = BlockToStr(block);
});
// Return address as string
return ipBlocks.join('.');
}
// Different tests
console.log(GetRandomIP('255.255.255.0/8'));
console.log(GetRandomIP('255.255.255.0/24'));
console.log(GetRandomIP('10.0.0.0/24'));
答案 2 :(得分:0)
基于emix的答案-
function getIPFromSubnet(subnetRange) {
// subnetRange = "10.0.0.0/24"
const subnet = subnetRange.split('/')[0]; // 10.0.0.0
const mask = subnetRange.split('/')[1]; // 24
const ipArray = subnet.split('.'); //["10", "0", "0", "0"]
var ipInBinary = ""; // will contain the binary equivalent of the iP
// for each element in the array, convert from decimal to binary
for (let quad of ipArray) {
let octet = parseInt(quad, 10).toString(2)
// we need each octet to be 8 bits. So provide padding for those which are less than 8 bits
// 0101 becomes 00000101
let octetLength = octet.length
if (octetLength < 8) {
let octDiff = 8 - octetLength;
octet = "0".repeat(octDiff) + octet
}
// concat all the octets into a 32 bit binary
ipInBinary = ipInBinary.concat(octet) // 00001010000000000000000000000000
}
// console.log("ipInBinary: ", ipInBinary);
// strip the subnet from the entire address:
let subnetBinary = ipInBinary.slice(0, mask) // 000010100000000000000000
let hostsBinary = ipInBinary.slice(mask, ipInBinary.length) // 00000000
var randomBinarySubstitute = "";
const randomPool = "10101010101010101010101010101010" //fix this nonsense later.
for (let i = 0; i < 32 - mask; i++) {
randomBinarySubstitute += randomPool[Math.floor(Math.random() * ipInBinary.length)]
}
let newIPBinary = subnetBinary + randomBinarySubstitute;
let finalIP = "";
// split the 32 bit binary IP into an array of 8 bits, each representing an octate
let finalIPArray_binary = newIPBinary.match(/.{8}/g) // ["00001010", "00000000", "00000000", "10001010"]
// convert the binary quad array to decimal dotted quad
for (let element of finalIPArray_binary) {
finalIP = finalIP + "." + parseInt(element, 2);
finalIP = finalIP.replace(/^\./, ""); // remnove the leading .
}
console.log("FinalIP", finalIP)
return finalIP
}
getIPFromSubnet('10.0.0.0/16')