Mantén la atención porque en este post hallarás la respuesta que buscas.
Solución:
Qué tal si:
BINARY(16)
Eso debería ser lo suficientemente efectivo.
Actualmente no hay ninguna función para convertir direcciones IPv6 textuales de/a binarias en el servidor MySQL, como se indica en ese informe de errores. Debe hacerlo en su aplicación o posiblemente crear una UDF (función definida por el usuario) en el servidor MySQL para hacerlo.
ACTUALIZAR:
MySQL 5.6.3 tiene soporte para direcciones IPv6, vea lo siguiente: “INET6_ATON(expr)”.
El tipo de datos es VARBINARY(16)
en lugar de BINARY(16)
como sugerí anteriormente. La única razón de esto es que las funciones de MySQL funcionan tanto para direcciones IPv6 como IPv4. BINARY(16)
está bien para almacenar solo direcciones IPv6 y ahorra un byte. VARBINARY(16)
debe usarse cuando se manejan direcciones IPv6 e IPv4.
Una implementación para versiones anteriores de MySQL y MariaDB, consulte lo siguiente: “EXTENDIENDO MYSQL 5 CON FUNCIONES IPV6”.
Nadie ha publicado una respuesta funcional completa (y muchos ejemplos usan Windows ::1
que puede ser muy engañoso para entornos en vivo (o “producción”)) en cualquier lugar (al menos que pueda encontrar), así que aquí está:
- El formato con el que almacenar.
- Ejemplo
INSERT
consulta utilizando una dirección IP IPv6 razonablemente compleja. - Ejemplo
SELECT
consulta que vas a poderecho
la dirección IP IPv6 de vuelta al cliente. - Solución de problemas para asegurarse de que no se ha perdido ningún código heredado.
Cambié todos los nombres de las columnas a ipv6
para reflejar que ellos adecuadamente admite IPv6 (y eso le permite mantener la columna anterior ip
intacto). Es posible almacenar el ip
columna en el ipv6
columna y luego solo DROP
los ip
columna una vez que esté seguro de que la conversión ha funcionado; cuando tenga tiempo lo agregaré a este post.
Tipo de datos IPv6
Como se ha mencionado VARBINARY 16
es el camino deseable a seguir hasta que AMD nos bendiga con CPU de 128 bits y las bases de datos se actualicen para admitir números enteros de 128 bits (¿lo dije correctamente?). IPv6 es de 128 bits, no de 64 bits.
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;
Consulta de inserción de IPv6
Obviamente necesitamos almacenar una dirección IP IPv6 antes de que podamos SELECT
eso; aquí está el PHP/SQL código:
$ipv6 = mysqli_real_escape_string($db,'FE80:0000:0000:0000:0202:B3FF:FE1E:8329');
$query1 = "INSERT INTO example (ipv6) VALUES (INET6_ATON('$ipv6'));";
Consulta SELECCIONAR IPv6
los PHP/SQL código:
$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');";
esto regresará fe80::202:b3ff:fe1e:8329
; no, no el IPv6 completo (que es FE80:0000:0000:0000:0202:B3FF:FE1E:8329
), es una versión abreviada / abreviada. Hay un código para convertirlo en la versión formal completa, pero esto es para ahorrarme tiempo a mí y a los demás porque esta Q/A es el que sigue apareciendo.
Importante: simplemente porque algunos direcciones IPv6 Mira como si encajaran bigint
lo hace no implica que dos minutos después, alguien con una dirección IPv6 más grande no se detendrá y causará estragos.
Con suerte, esto salvará a algunas personas de la locura de abrir otras dos docenas de pestañas. Cuando tenga tiempo en el futuro, agregaré el código PHP adicional que extiende el IPv6 condensado al formato formal completo.
Solución de problemas
Si por alguna razón almacenar y/o recuperar direcciones IPv6 no funciona para usted, obtenga una copia de Búsqueda y reemplazo avanzados (funciona más rápido en Wine que el nativo de Linux). grep
); utilizar esta predominantemente para encontrar, no para reemplazar. Asegúrese de que su código sea consistente en todas partes de su software.
- Todos
$ip
Variables deber convertirse en$ipv6
para que sepas que tienes esa parte cubierta. - No olvides quitar el final.
)
para los siguientes cuatro pasos: - Buscar todas las instancias de PHP
inet_pton(
funciones y elimínelas. - Buscar todas las instancias de PHP
inet_ntop(
funciones y elimínelas. - Buscar todas las instancias de sql
INET_ATON(
funciones y elimínelas. - Buscar todas las instancias de sql
INET_NTOA(
funciones y elimínelas. - Buscar todas las instancias de
$ipv6
y asegúrese de que todas las instancias de IP-IN-TO-SQL utilicenINET6_ATON('$ipv6')
y que todas las instancias donde se usa IP-FROM-SQLINET6_NTOA(ipv6) AS ipv6
. - Buscar todas las instancias de
$row1['ip']
y reemplazarlos con$row1['ipv6']
. - Asegúrese de que todas las instancias de
$ipv6 =
use el siguiente código (con su referencia de objeto de base de datos cambiada):$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'));
. - Asegúrese de que sus pruebas utilicen recién direcciones IP probadas en lugar de versiones potencialmente fallidas si sabe que algo andaba mal antes de empezaste a depurar.