Подтвердить что ты не робот

Хранение адресов IPv6 в MySQL

Как было запрошено в ipv6-способные функции inet_aton и inet_ntoa, необходимые", в настоящее время нет функции MySQL для хранения адресов IPv6. Каким будет рекомендуемый тип/функция данных для хранения/вставки? (Я не собираюсь хранить их как строку). Я также не хочу отделять адрес IPv6 от 2 INT.

4b9b3361

Ответ 1

Как насчет:

BINARY(16)

Это должно быть достаточно эффективным.

В настоящее время нет функции для преобразования текстовых IPv6-адресов из/в двоичный файл на сервере MySQL, как указано в этом отчете об ошибке. Вам нужно либо сделать это в своем приложении, либо, возможно, сделать UDF (пользовательская функция) на сервере MySQL, чтобы это сделать.

UPDATE:

MySQL 5.6.3 имеет поддержку адресов IPv6, см. следующее: " INET6_ATON (expr)".

Тип данных VARBINARY(16) вместо BINARY(16), как я предложил ранее. Единственная причина этого в том, что функции MySQL работают как для IPv6, так и для IPv4-адресов. BINARY(16) подходит для хранения только адресов IPv6 и сохраняет один байт. VARBINARY(16) следует использовать при работе с адресами IPv6 и IPv4.

Реализация для более старых версий MySQL и MariaDB см. в следующем: " РАСШИРЕНИЕ MYSQL 5 С ФУНКЦИЯМИ IPV6.

Ответ 2

Никто не опубликовал полный рабочий ответ (и во многих примерах используется Windows ::1 который может вводить в заблуждение для реальных (или "производственных") сред) где угодно (по крайней мере, я могу найти), так что вот:

  1. Формат для хранения.
  2. Пример запроса INSERT с использованием достаточно сложного IP-адреса IPv6.
  3. Пример SELECT, запрос, который вы будете иметь возможность echo на IPv6 IP - адрес клиента.
  4. Устранение неполадок, чтобы убедиться, что вы не пропустили ни один устаревший код.

Я изменил все имена столбцов на ipv6 чтобы отразить, что они должным образом поддерживают IPv6 (и это позволяет вам сохранить старый столбец ip без изменений). Можно сохранить столбец ip столбце ipv6 а затем просто DROP столбец ip только вы убедитесь, что преобразование сработало; когда у меня действительно будет время, я добавлю это в этот пост.

Тип данных IPv6

Как уже упоминалось, VARBINARY 16 - желательный путь, пока AMD не благословит нас 128-битными процессорами, а базы данных не будут обновлены для поддержки 128-битных целых чисел (я правильно сказал?). IPv6 128-битный, а не 64-битный.

CREATE TABLE 'example'
(
'id' INT(11) NOT NULL AUTO_INCREMENT,
'ipv6' VARBINARY(16) NOT NULL,
PRIMARY KEY ('id')
)
COLLATE='utf8mb4_unicode_520_ci'
ENGINE=InnoDB;

IPv6 INSERT Query

Очевидно, нам нужно сохранить IP-адрес IPv6, прежде чем мы сможем SELECT его; Вот код PHP/SQL:

$ipv6 = mysqli_real_escape_string($db,'FE80:0000:0000:0000:0202:B3FF:FE1E:8329');
$query1 = "INSERT INTO example (ipv6) VALUES (INET6_ATON('$ipv6'));";

IPv6 SELECT Query

Код PHP/SQL:

$ipv6 = mysqli_real_escape_string($db,'FE80:0000:0000:0000:0202:B3FF:FE1E:8329');
$query2 = "SELECT INET6_NTOA(ipv6) AS ipv6 FROM example WHERE ipv6=INET6_ATON('$ipv6');";

Это вернет fe80::202:b3ff:fe1e:8329; нет, не полный IPv6 (то есть FE80:0000:0000:0000:0202:B3FF:FE1E:8329), это сжатая/сокращенная версия. Существует код, делающий его официальной полноформатной версией, но это экономит время для меня и других, потому что эта Q/A - та, которая продолжает появляться.

Важно: только то, что некоторые IPv6-адреса выглядят так, как будто они вписываются в bigint, не означает, что через две минуты кто-то с большим IPv6-адресом не остановится и не нанесет ущерб.

Надеемся, что это спасет некоторых людей от безумия открытия еще двух дюжин вкладок. Когда у меня будет время в будущем, я добавлю дополнительный код PHP, который расширяет сжатый IPv6 до полного формального формата.


Поиск проблемы

Если по какой-то причине сохранение и/или получение адресов IPv6 не работает, возьмите себе копию Advanced Find and Replace (работает в Wine быстрее, чем встроенный в Linux grep); используйте это преимущественно для поиска, а не замены. Убедитесь, что ваш код соответствует везде в вашем программном обеспечении.

  • Все переменные $ip должны быть преобразованы в $ipv6 чтобы вы знали, что этот бит покрыт.
  • Не забудьте удалить окончание ) для следующих четырех шагов:
  • Искать все экземпляры PHP inet_pton( функции и удалять их).
  • Найдите все экземпляры PHP inet_ntop( функции и удалите их).
  • Найдите все экземпляры SQL INET_ATON( функции и удалите их).
  • Найдите все экземпляры SQL INET_NTOA( функции и удалите их).
  • Найдите все экземпляры $ipv6 и убедитесь, что все экземпляры IP-IN-TO-SQL используют INET6_ATON('$ipv6') а все экземпляры, где IP-FROM-SQL, используют INET6_NTOA(ipv6) AS ipv6.
  • Найдите все экземпляры $row1['ip'] и замените их на $row1['ipv6'].
  • Убедитесь, что все экземпляры $ipv6 = используют следующий код (с измененной ссылкой на объект базы данных): $ipv6 = (isset($_SERVER['REMOTE_ADDR']) && strlen($_SERVER['REMOTE_ADDR']) > 0)? mysqli_real_escape_string($db,$_SERVER['REMOTE_ADDR']): mysqli_real_escape_string($db,getenv('REMOTE_ADDR')); $ipv6 = (isset($_SERVER['REMOTE_ADDR']) && strlen($_SERVER['REMOTE_ADDR']) > 0)? mysqli_real_escape_string($db,$_SERVER['REMOTE_ADDR']): mysqli_real_escape_string($db,getenv('REMOTE_ADDR')); ,
  • Убедитесь, что в ваших тестах используются только что протестированные IP-адреса, а не потенциально испорченные версии, если вы знаете, что что-то не так до начала отладки.

Ответ 3

Отличный пример, однако я отметил следующее. Это работает, только если одна версия mysql имеет функцию INET6_ATON. В противном случае сообщение об ошибке может быть что - то вроде: что FUNCTION DOES NOT EXIST.