MySQL y las IPv6

29 Dic 2010

A raíz de la entrada MySQL: mejor tipo de campo para guardar IP publicada hace unos días, un usuario me pregunta qué hacer cuando trabajamos con IPv6 en lugar de las IPv4.

La pregunta resulta interesante tras la aparición en Internet de algunos debates (aquí, aquí o aquí) sobre el agotamiento próximo de las direcciones IP disponibles y la necesidad de actualizarse a un nuevo protocolo.

Así que como el tema lo requiere, vayamos por partes.

Diferencias entre IPv4 e IPv6

El protocolo TCP/IP es el protocolo usado para la gestión de tráfico de datos a través de Internet y que, básicamente, se encarga de enlazar computadoras entre sí independientemente del sistema operativo que utilicen. Para saber más sobre este protocolo, podemos recurrir a su entrada en la Wikipedia aquí.

Actualmente, la versión de este protocolo más utilizada es la v4 que data de 1981.

TCP/IPv4 es una versión de 32 bits compuesta por cuatro grupos de 8 bits cada uno destinados a representar un valor decimal de tres dígitos. Su especificación está definida en el RFC791.

Visto en forma binaria, cada uno de esos cuatro grupos está compuesto por 8 dígitos (ceros y unos) que, representados en formato decimal, permiten un rango que va desde el 0 al 255.

Ejemplo: 192.168.0.1

NOTA: Ocho dígitos que pueden corresponder a ceros y unos da lugar a dos elevado a ocho (2 8 = 256). Tomando el cero como elemento contable, obtenemos ese rango de 0-255.

TCP/IPv6 es la versión diseñada para reemplazar a la actual v4 y trabaja sobre 128 bits en lugar de 32. Su estructura queda compuesta por 8 grupos de 16 bits separados por el caracter ‘:’ y donde el cero, puede ser directamente suprimido.

Generalmente se representa en sistema hexadecimal en lugar de decimal, por lo que una IPv6 tiene el siguiente aspecto:

2005:205:169:0:175:b4fd:aacdd:bbcaa

O lo que es lo mismo:

2005:205:169::175:b4fd:aacdd:bbcaa

Con este sistema, el número de IPs disponible se incrementa de forma factorial hasta los casi 340 trillones direcciones.

Para más información sobre IPv6, podemos acudir de nuevo a la wikipedia o directamente a su especificación RFC2460.

IPv6 en MySQL

MySQL no soporta IPv6 de forma nativa.

Pese a que se habían definido funciones basadas en este protocolo del tipo INET6_ para la versión 6.0, todo lo relativo al futuro desarrollo de MySQL está en entre dicho tras su adquisición por parte de Oracle.

Así que, mientras esperamos pacientemente a ver qué pasa, debemos recurrir a las MySQL UDF (User Defined Functions).

Qué son las UDFs ?

UDF, o Funciones Definidas por los Usuarios, son pequeños programas escritos en C o en C++ que expanden las posibilidades nativas de MySQL añadiendo nuevas funciones definidas por el usuario.

Las UDFs están disponibles desde la versión 5.0 de MySQL y puede encontrarse toda la información al respecto aquí.

De acuerdo, me lo miraré. Y ahora ?

Pues que existe un UDF para el trabajo con direcciones IPv6 que nos puede facilitar mucho el trabajo con este formato.

Antes de ver ejemplos, podemos descargar el código directamente desde aquí o puede seguirse el track del proyecto completo en BitBucket en la siguiente dirección:

http://bitbucket.org/watchmouse/mysql-udf-ipv6/

Ha sido probado con éxito en Debian, Ubuntu y FreeBSD, aunque debería correr sin problemas en otras plataformas.

Ejemplos

Actualmente encontramos dos funciones implementadas para convertir tanto direcciones IPv6 como IPv4 en un valor numérico directamente desde comandos SQL. Las funciones son: inet6_pton() y inet6_ntop().

La primera de ellas, inet6_pton() convierte una cadena con dirección IP válida en una representación binaria tanto de 4 bytes (IPv4) como de 16 bytes (IPv6) de longitud. La segunda, inet6_ntop() hace lo contrario.

mysql> SELECT inet6_ntop(inet6_pton('2001:4860:a005::68'));

+———————————————-+
| inet6_ntop(inet6_pton(‘2001:4860:a005::68’)) |
+———————————————-+
| 2001:4860:a005::68                           |
+———————————————-+
1 row in set (0.00 sec)

mysql> SELECT inet6_ntop(inet6_pton('1.2.3.4'));

+———————————–+
| inet6_ntop(inet6_pton(‘1.2.3.4’)) |
+———————————–+
| 1.2.3.4                           |
+———————————–+
1 row in set (0.00 sec)

mysql> SELECT
LENGTH(inet6_pton('1.2.3.4')) AS ipv4len,
LENGTH(inet6_pton('2001:4860:a005::68')) AS ipv6len;

+———+———+
| ipv4len | ipv6len |
+———+———+
|       4 |      16 |
+———+———+
1 row in set (0.00 sec)

Ventajas

De este modo, se puede almacenar una IPv6 en base de datos con un valor de campo VARBINARY(16). Si usamos en su lugar un VARCHAR(16) podríamos tener problemas de conversión por lo que no lo recomiendo.

Pese a que hay otras muchas posibilidades para almacenar direcciones IPv6, con este método podríamos efectuar operaciones sobre nuestras IPs utilizando por ejemplo rangos:

SELECT ip FROM myTable WHERE ip BETWEEN a AND b;

Más información:

http://forums.mysql.com/read.php?20,178272,179710#msg-179710
http://labs.watchmouse.com/2009/10/extending-mysql-5-with-ipv6-functions/

Más:

Aún no tenemos debug!
Ningún marciano se ha comunicado.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *