Having IPv4 address ranges for a given country, how would one generate random address? For example, a single current set of ranges (one of many) for Singapore is:
+----------+----------+--------------+
| ip_from | ip_to | country_code |
+----------+----------+--------------+
| 18925568 | 18926079 | SG |
+----------+----------+--------------+
FAQ(3) explains that
IP_Number = 16777216*w + 65536*x + 256*y + z
where
IP_Address = w.x.y.z
IP_Number
standing either for ip_from
or ip_to
. For the Singapore range presented above, it gives me:
16777216*w + 65536*x + 256*y + z >= 18925568; // from
16777216*w + 65536*x + 256*y + z <= 18926079; // to
How can I generate random w
, x
, y
and z
?
Here is a testable implementation (in JavaScript since that can be run directly here) and a little bit of a description.
First you need to generate random number from the specified range. If you have a function (let's call it random
) that generates random real numbers between 0 and 0.999... [0,1)
then you can do this.
num = (random() * (end - start + 1)) + start
Then you need to use mod 256
4 times to split the number into 4 parts and also use div 256
3 times on the given number (the fourth div
operation would be unnecessary but if we are doing it in loop then we can just keep it there for the sake of simplicity as it doesn't change a thing).
(% - modulo, // - div)
first = num % 256
num = num // 256
second = num % 256
num = num // 256
third = num % 256
num = num // 256
fourth = num % 256
You can then push them into an array [fourth, third, second, first]
(note the order here) and do some validation - some addresses are reserved for private internets so if you happen to generate one of them, just throw it away and generate a new one (you can either loop or recurse here till you generate a valid one).
Ip addresses in these ranges are reserved according to RFC 1918:
10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
And here is the implementation.
const start = 18925568;
const end = 18926079;
function _generateRandomIp(start, end) {
let r = Math.floor(Math.random() * (end - start + 1)) + start;
const ip = [];
for (let i = 0; i < 4; i++) {
ip.push(r % 256);
r = Math.floor(r / 256);
}
return ip.reverse(); // put the results mod/div into correct order
}
function generateRandomIp(start, end) {
let ip = _generateRandomIp(start, end);
let valid = true;
// ip can't be of format 10.xxx.xxx.xxx
if (ip[0] === 10) { valid = false; }
// ip can't be of format 172.16.xxx.xxx
if (ip[0] === 172 && ip[1] === 16) { valid = false; }
// ip can't be of format 192.168.xxx.xxx
if (ip[0] === 192 && ip[1] === 168) { valid = false; }
if (valid === true) {
return ip.join('.'); // convert ip to string format
} else {
return generateRandomIp(start, end); // try again
}
}
const ip = generateRandomIp(start, end);
console.log(ip);
The above snippet will generate a random ip address in that range each time you run it.
And here is the test case from the page that you have mentioned which says that number 3401190660
should be converted into 202.186.13.4
, so let's just switch that randomly generated number for this one and try it.
const start = 18925568;
const end = 18926079;
function _generateRandomIp(start, end) {
let r = 3401190660; // here is that specific number
const ip = [];
for (let i = 0; i < 4; i++) {
ip.push(r % 256);
r = Math.floor(r / 256);
}
return ip.reverse(); // put the results mod/div into correct order
}
function generateRandomIp(start, end) {
let ip = _generateRandomIp(start, end);
let valid = true;
// ip can't be of format 10.xxx.xxx.xxx
if (ip[0] === 10) { valid = false; }
// ip can't be of format 172.16.xxx.xxx
if (ip[0] === 172 && ip[1] === 16) { valid = false; }
// ip can't be of format 192.168.xxx.xxx
if (ip[0] === 192 && ip[1] === 168) { valid = false; }
if (valid === true) {
return ip.join('.'); // convert ip to string format
} else {
return generateRandomIp(start, end); // try again
}
}
const ip = generateRandomIp(start, end);
console.log(ip);
And as we can see, this algorithm produced the correct result.