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

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

44 голосов
/ 06 августа 2011

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

Ответы [ 3 ]

82 голосов
/ 06 августа 2011

Как насчет:

BINARY(16)

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

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

ОБНОВЛЕНИЕ:

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 ".

8 голосов
/ 15 января 2018

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

  1. Формат для хранения.
  2. Пример INSERT запроса с использованием достаточно сложного IP-адреса IPv6.
  3. Пример SELECT запроса о том, что вы сможете echo вернуть IP-адрес IPv6 клиенту.
  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

Очевидно, нам нужно сохранить 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'));.
  • Убедитесь, что в ваших тестах используются недавно протестированных IP-адресов вместо потенциально испорченных версий, если вы знаете, что что-то не так до , когда вы начали отладку.
0 голосов
/ 29 июля 2018

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...