Как создать случайный номер IPv4 для данной страны? - PullRequest
0 голосов
/ 17 мая 2018

Имея диапазоны адресов IPv4 для данной страны, как можно было бы генерировать случайный адрес?Например, текущий набор диапазонов (один из многих) для Сингапура:

+----------+----------+--------------+
| ip_from  | ip_to    | country_code |
+----------+----------+--------------+
| 18925568 | 18926079 | SG           |
+----------+----------+--------------+

source: lite.ip2location.com

FAQ (3) объясняет, что

IP_Number = 16777216*w + 65536*x + 256*y + z

, где

IP_Address = w.x.y.z

IP_Number означает либо ip_from, либо ip_to.Для сингапурского диапазона, представленного выше, он дает мне:

16777216*w + 65536*x + 256*y + z >= 18925568; // from
16777216*w + 65536*x + 256*y + z <= 18926079; // to

Как я могу генерировать случайные w, x, y и z?

1 Ответ

0 голосов
/ 17 мая 2018

Вот тестируемая реализация (в JavaScript, так как ее можно запустить прямо здесь) и немного описания.

Сначала вам нужно сгенерировать случайное число из указанного диапазона.Если у вас есть функция (назовем ее random), которая генерирует случайные действительные числа в диапазоне от 0 до 0,999 ... [0,1), тогда вы можете сделать это.

num = (random() * (end - start + 1)) + start

Тогда вам нужно использовать mod 256 4 раза, чтобы разделить число на 4 части, а также использовать div 256 3 раза для заданного числа (четвертая операция div была бы ненужной, но если мы делаем это в цикле, то мы можем просто держать ее там радипростоты, поскольку это ничего не меняет).

(% - modulo, // - div)

first = num % 256
num = num // 256

second = num % 256
num = num // 256

third = num % 256
num = num // 256

fourth = num % 256

Затем вы можете поместить их в массив [fourth, third, second, first] (обратите внимание на порядок здесь) и выполнить некоторую проверку - некоторые адреса зарезервированы для частных интернетов, так что если вам случится сгенерироватьодин из них, просто выбросьте его и сгенерируйте новый (вы можете зацикливаться или рекурсировать здесь, пока не создадите действительный).

IP-адреса в этих диапазонах зарезервированы в соответствии с 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) 

А вот и реализация.

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);

Приведенный выше фрагмент будет генерировать случайный IP-адрес в этом диапазоне при каждом запуске.

А вот тестовый пример со страницы, которую вы упомянули, который говорит, что число 3401190660 должно быть преобразовано в 202.186.13.4, так что давайте просто переключим это случайное число для этого и попробуем его.

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);

И, как мы видим, этот алгоритм дал правильный результат.

...