Configuración y desarrollo del Protocolo IP versión 6

Transcripción

Configuración y desarrollo del Protocolo IP versión 6
Protocolo de Internet versión 6
Configuración y Desarrollo
Pablo Carmona Amigo – Renato Ulloa Sepúlveda
Ingenierı́a Civil Electrónica
Universidad de La Frontera
24 de julio de 2002
Resumen
Este informe pretende mostrar a grandes rasgos el trabajo de investigación, configuración
y programación en el nuevo protocolo que regirá Internet en un futuro cercano, esto es IPv6
(Protocolo Internet versión 6). A través del presente trabajo se pretenden mostrar básicamente
dos cosas. Por un lado, ver todo lo referente a configuración de equipos GNU/Linux, (como
router y cliente) y la configuración de un cliente Windows 2000 para formar parte de una red
LAN. En tanto por otro lado se aborda el tema de la programación de redes usando los llamados Sockets. Este último es un medio para conectar los programas a la red, pudiendo de esta
forma enviar y recibir los mensajes. Esta no pretende ser una guı́a completa referente al tema,
más bien es dar un vistazo a algunos aspectos del trabajo necesario para poder hacer uso de
redes basadas en IPv6.
Índice
1. Introducción a IPv6
2
2. Caracterı́sticas de IPv6
2
2.1. Aumento del espacio de direcciones . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
2.2. Autoconfiguración . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
2.3. Seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
2.4. Calidad de Servicio (QoS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
2.5. Enrutamiento Jerárquico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
3. Configuración general
5
3.1. Habilitación de IPv6 en los equipos . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
3.1.1. Computador con GNU/Linux . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1
3.1.2. Computador con Windows 2000 . . . . . . . . . . . . . . . . . . . . . . . . .
8
3.2. Configuración del router . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
3.2.1. Túneles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
3.2.2. Zebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
3.3. Configuración de los clientes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
3.3.1. Configuración en Debian GNU/Linux . . . . . . . . . . . . . . . . . . . . . .
13
3.3.2. Configuración en Windows 2000 . . . . . . . . . . . . . . . . . . . . . . . . .
14
3.4. Pruebas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
4. Programación de aplicaciones para IPv6
16
4.1. Sockets IPv6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
4.2. Ejemplos de cliente y servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
4.2.1. Cliente TCP6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
4.2.2. Servidor TCP6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
4.2.3. Pruebas del cliente y el servidor . . . . . . . . . . . . . . . . . . . . . . . . .
23
1. Introducción a IPv6
El Protocolo de Internet versión 6, conocido por sus siglas IPv6, es el nuevo protocolo que se
utilizará en Internet dentro de los próximos años. Su aplicación se debe a que el reducido espacio
de direcciones que ofrece la versión 4 del Protocolo de Internet (IPv4) ya
está alcanzando su lı́mite.
IPv6 ofrece un número muy superior de direcciones (del orden de 10 ) dado que la dirección se
representa con 128 bits. Se recomienda revisar [3] y [5] para mayores detalles.
2. Caracterı́sticas de IPv6
Antes de comenzar con la caracterización del nuevo protocolo se debe mencionar por qué fue
necesario el replanteamiento del ya acostumbrado IPv4, tratando de solventar todas las falencias,
debilidades y además agregar caracterı́sticas propias que harán que con esta versión por fin se de
solución a todas las necesidades de las redes, ya sea desde una simple LAN hasta la red de redes,
la Internet.
De las caracterı́sticas que vienen a dar solución se puede mencionar al aumento del espacio
de direcciones, autoconfiguración, seguridad y calidad de servicio (QoS).
2.1. Aumento del espacio de direcciones
En IPv4 se tiene una estructura
de direcciones de 32 bits, agrupado en 4 octetos separados
por un punto (.); lo que da 4,29x10 direcciones posibles. Dado el agotamiento de las direcciones
2
ruteables en Internet1 , fue necesario recurrir a la denominada NAT2 , para de esta forma dar acceso
a la red pública a hosts que utilizan direcciones privadas. Con este método bastaba sólo una
dirección válida y tras ella el resto de hosts con direcciones reservadas. Esto ya no será necesario
porque se produce el cambio de 32 bits a 128 bits trayendo consigo el gigantesco aumento de
direcciones posibles.
Si se toman estos 128 bits de la longitud de la dirección, se hacen 8 grupos de 16 bits separados por dos puntos(:), y si se agrupa cada bloque de 16 bits en 4 bloques de 4 bits se podrá pasar
3
de notación binaria a hexadecimal
para hacerlas más comprensibles y recordables. De esta es
tructura se obtendrán 3,4x10 direcciones.
La mencionada escritura en hexadecimal se hace necesaria porque serı́a imposible manejar
una dirección como:
0011111111111110:1000000001110000:0001000000001100:0000101100000110:
0000000000000000:0000000000000000:0000000000000001:0000000000000001
Resulta más práctico escribirlo como:
3ffe:8070:100c:0b06:0000:0000:0001:0001
Sin embargo, esto es aún muy largo y engorroso, es por esto que se utiliza la llamada compresión de ceros, que dice lo siguiente:
Se pueden reemplazar secuencias contiguas de ceros con “::”. Esto es posible solamente una
vez en toda la dirección y teniendo siempre cuidado de tomar bloques completos de 16 bits.
Los ceros a la izquierda de cada bloque de 16 bits se pueden quitar.
Es decir, si se aplican estas reglas a la dirección anterior, quedarı́a de la forma:
3ffe:8070:100c:b06::1:1
Ésta es por cierto la dirección que tiene asignado el Router.
Como se ve, dada la complejidad de las direcciones respecto de las IPv4 se hace necesario
(más bien crı́tico) el uso del servicio DNS4 más que en la versión anterior del protocolo. Para
mayor información acerca de DNS en IPv6 se recomienda [13].
1
Es decir, excluyendo las direcciones de uso privado, por ejemplo: 10.0.0.0/8, 192.168.0.0./16
Del inglés Network Address Translation
3
En base 16, es decir, los números van de 0. . . 9, A, B, C, D, E, F (0 a 15 decimal)
4
Del inglés Domain Name Service, permite asociar un nombre con una dirección IP y viceversa.
2
3
2.2. Autoconfiguración
Esto se refiere básicamente al concepto de conectar y comenzar a usar. Es decir, cuando algún
nodo o host se conecte a una red, éste recibe datos del router para comenzar a comunicarse: una
dirección IPv6, máscara de red y rutas a utilizar. Lo que se trata de lograr es similar al DHCP 5
usado comúnmente en IPv4. En este punto existen básicamente dos métodos:
Un proceso de asignación de direcciones en base a la direccion MAC de la tarjeta de red o
bien mediante DHCPv6, que es un servicio que asigna una dirección al equipo, controlando de
este modo el rango de direcciones con que se trabaja. Este último en realidad es algo controlado
por el administrador de red, lo que quizás no podrı́a ser considerado como autoconfiguración.
Existen variantes para la asignación de direcciones, que serán vistas más adelante en el capı́tulo 3
en la página 5. Se pueden obtener detalles en [14].
2.3. Seguridad
Éste es quizás uno de los principales requerimientos a la hora de plantear esta versión del
protocolo, beneficiando a las aplicaciones en cuanto a autenticación y encriptación de datos en
forma transparente. Cabe señalar que IPv4 no poseı́a seguridad ni menos encriptación de datos,
para ello era necesario usar software de encriptación basados en varios estándares, uno de los más
utilizados fue IPSec. Es precisamente en éste que se basa la encriptación incluı́da en IPv6.
2.4. Calidad de Servicio (QoS)
Si bien es cierto que en IPv4 existı́an algunos bits en la cabecera para el control del Tipo de
Servicio (ToS6 ), en IPv6 se disponen de campos más amplios para definir prioridad y flujo de
cada paquete a ser transportado. Estos campos son leı́dos por los routers y de acuerdo a ellos se
les debe dar un trato especial. Por ejemplo, si un paquete va marcado como flujo de video, resulta
evidente que debe ser enviado con prioridad sobre paquetes que podrı́an estar marcados como
correo electrónico. Si un e-mail se demora 2 ó 10 segundos es casi imperceptible, en cambio en una
videoconferencia esto es inaceptable. A esto se le denominda QoS7 . Más información en [7].
2.5. Enrutamiento Jerárquico
El ruteo en IPv6 es jerárquico y sin las clases que existı́an en IPv4. De esta forma se logra
que las tablas de ruta no crezcan más allá de lo necesario8 . Junto con disminuir los tamaños de las
tablas de rutas se simplifica el ruteo en sı́, haciendo que los routers sean más eficientes.
5
Del inglés Dynamic Host Configuration Protocol
Del inglés Type of Service
7
Del inglés Quality of Service
8
En IPv4 las tablas de ruta han crecido de tal forma que se han convertido en inmensos archivos que sólo son
manejables con poderosos servidores dedicados
6
4
3. Configuración general
Se realizó la configuración en un servidor corriendo Red Hat Linux 7.3 que trabaja principalmente como router, y otro corriendo Debian GNU/Linux Sid y que se configuró como un cliente.
También se configuraron otros dos clientes usando Windows 2000 Professional.
El objetivo a conseguir en cuanto a la creación, configuración y mantención de túneles se
puede sintetizar en la figura 1 en la página 6.
Como se ve, se cuenta con un túnel hacia la Universidad Austral de Chile (UACH) desde el
Departamento Ingenierı́a Eléctrica (DIE) de la Universidad de La Frontera y otro hacia el Instituto
de Informática Educativa (IIE), que también se encuentra en esta universidad. Este último posee
una subred de la división del rango de direcciones dadas por la UACH.
Obviamente se tiene salida a través de la UACH hacia el 6 BONE 9 .
Las direcciones asignadas a la UFRO, tanto para red como para el túnel son las siguientes:
Red disponible para la UFRO: 3ffe:8070:100c:b06::/64
Túnel dado por la UACH:
Extremo UACH: 3ffe:8070:100c:2b02::a/64
Extremo UFRO: 3ffe:8070:100c:2b02::b/64
Número autónomo ASN:
UACH: 45333
UFRO: 45348
Es con estos valores (o derivados de ellos) que se realiza la configuración de los túneles,
router y equipos clientes.
En particular se subdividió la red 3ffe:8070:100c:b06::/64 de la siguiente forma:
Red DIE: 3ffe:8070:100c:b06::1:0/112
Red IIE: 3ffe:8070:100c:b06::2:0/112
Red para túnel con IIE: 3ffe:8070:100c:b06::ffff:0/112
3.1. Habilitación de IPv6 en los equipos
Antes de comenzar la configuración particular de los equipos es necesario hacer alcances
de la configuración básica y necesaria para poder trabajar con el protocolo en máquinas Linux y
Windows. Las configuraciones que vienen a continuación pueden ser revisadas en [1], [2], [4], [8] y
[9]. Si bien no todos ellos son especı́ficos de IPv6 también esclarecen situaciones y configuraciones
que se realizan de forma similar en IPv4.
9
Mayores consultas en www.6bone.net
5
Figura 1: Esquema de túneles de la Universidad de La Frontera
6
3.1.1. Computador con GNU/Linux
Antes de cualquier uso del protocolo en el S.O. GNU/Linux se necesita cargar el módulo
ipv6, para esto existen varias formas de hacerlo:
En forma manual: esto quiere decir que una vez que se inició Linux, se abre una consola y como
root se escribe:
[root@ipv6 root]# modprobe ipv6
Con esto se carga el módulo y ya es posible comenzar a utilizar el protocolo, ya sea asignar
direcciones, configuraciones, etc.
Usando un archivo de inicio: esto se consigue mediante la creación de un archivo que contenga
la lı́nea:
modprobe ipv6
luego se agrega el nombre de este archivo en /etc/rc.d/rc.local10. Incluso se puede escribir
esto directamente en /etc/rc.d/rc.local.
Con este método es necesario reiniciar para que la configuración se haga efectiva.
Modificando archivos del Network (Red Hat 7.x): este es el método recomendado, ya que es el
que viene con la distribución. Para esto debemos editar varios archivos, comenzando con
/etc/sysconfig/network, cuyo contenido es similar a esto:
NETWORKING=yes
HOSTNAME=ipv6
GATEWAY=146.83.206.254
Tras esta última lı́nea debemos agregar lo siguiente:
NETWORKING_IPV6=yes
Ahora tenemos que editar el archivo de configuración /etc/sysconfig/network-scripts/
ifcfg-ethx11 y agregar la lı́nea:
IPV6INIT=yes
Una vez hecho esto guardamos los cambios y ahora es necesario reiniciar el network mediante el comando /etc/init.d/network restart, una vez hecho esto ya tenemos habilitado
el protocolo. Esto se hace en forma automática cada vez que se inicia el equipo, por lo que
esto sólo se hace cuando recién hemos modificado el archivo.
Una vez echo esto ya se está en condiciones de continuar con la configuración de cualquier tipo.
Podrı́amos por ejemplo hacer un /sbin/ifconfig y se deberı́a obtener algo como:
10
11
La ubicación puede variar dependiendo de la distribución. Esto es válido para Red Hat 7.x
Puede ser eth0, eth1 según corresponda.
7
eth0
Link encap:Ethernet HWaddr 00:04:75:81:26:45
inet addr:146.83.206.114 Bcast:146.83.206.255 Mask:255.255.255.0
inet6 addr: fe80::204:75ff:fe81:2645/10 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3019997 errors:0 dropped:0 overruns:30 frame:0
TX packets:1570211 errors:0 dropped:0 overruns:0 carrier:0
collisions:157201 txqueuelen:100
RX bytes:439717982 (419.3 Mb) TX bytes:885637606 (844.6 Mb)
Interrupt:10 Base address:0xbc00
lo
Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:19604 errors:0 dropped:0 overruns:0 frame:0
TX packets:19604 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2998019 (2.8 Mb) TX bytes:2998019 (2.8 Mb)
En este ejemplo podemos apreciar la existencia de una dirección IPv6 del tipo
fe80::204:75ff:fe81:2645/10
Que es del tipo de autoconfiguración, esto quiere decir que de forma automática se ha asignado esta dirección. También se ven las direcciones de loopback:
127.0.0.1 en IPv4.
::1/128 en IPv6.
3.1.2. Computador con Windows 2000
Se debe decir que la configuración de los clientes Windows 2000 es bastante simple, pero
poco clara. Se debe bajar desde el sitio de Microsoft en Internet el archivo tpipv6-version.exe 12 , éste
se descomprime al ejecutarlo y posteriormente hay que buscar el archivo setup.exe en el directorio
donde se descomprimió para ejecutarlo y terminar con la instalación del protocolo.
3.2. Configuración del router
Una vez pasada la etapa de inicialización del protocolo, se puede asignar una dirección IPv6
del rango dado a este equipo13 . Para esto se abre una consola como root y se escribe:
# ip -f inet6 address add 3ffe:8070:100c:b06::1:1/112 dev eth0
En donde:
ip -f inet6 le dice al comando ip que lo que viene a continuación es de la familia IPv6.
12
13
Se puede encontrar en http://msdn.microsoft.com/downloads/sdks/platform/tpipv6.asp
Esto es válido también para los clientes Linux.
8
address add indica que se tiene que manejar una dirección, añadir una especı́ficamente.
dirección/prefijo dev eth0 aquı́ se le da la dirección que se ha elegido y la interfaz a la que se le
quiere asignar dicha dirección. En este caso es eth0.
Esta es sólo una de las formas de realizar esta configuración, la otra es editando el archivo
se ve como éste:
/etc/sysconfig/network-scripts/ifcfg-eth0 que
DEVICE=eth0
BOOTPROTO=static
BROADCAST=146.83.206.255
IPADDR=146.83.206.114
NETMASK=255.255.255.0
NETWORK=146.83.206.0
ONBOOT=yes
IPV6INIT=yes
y se agrega la lı́nea:
IPV6ADDR="3ffe:8070:100c:b06::1:1/112"
Una vez guardado este cambio se reinicia el network ejecutando /etc/init.d/network restart,
luego de esto ya se cuenta con la dirección en la interfaz eth0. Cabe señalar que se pueden tener
múltiples direcciones en una misma interfaz de red, añadiendo en el mismo archivo una lı́nea
similar a esta:
IPV6ADDR_SECONDARIES="3ffe:8070:100c:b06::1:2/112 3ffe:8070:100c:b06::1:3/112"
Con esto ya se tienen 3 direcciones en la interfaz eth0. No olvidar reiniciar el network. Se
recomienda [1], [2] y [4].
3.2.1. Túneles
Para poder manejar tráfico IPv6 en redes separadas por routers IPv4 se debe recurrir a los
llamados T ÚNELES. A través de ellos se envı́an los paquetes IPv6 encapsulados en paquetes IPv4
hacia otra red que maneje también el protocolo. Con esto se logra unir nubes IPv6, pero inmersos
en redes del tipo IPv4. Antes de la creación de los túneles se necesitan varios datos:
Dirección IPv4 de nuestro Router: 146.83.206.114
Dirección IPv4 del router remoto14 : 146.83.248.2
Dirección IPv6 para el túnel:
3ffe:8070:100c:2b02::a/64 para el equipo remoto.
3ffe:8070:100c:2b02::b/64 para el equipo local.
Para la creación de ellos existen variadas formas:
14
Con quien se quiere establecer el túnel.
9
A través de la consola:
ip
ip
ip
ip
tunnel add UACH mode sit remote 146.83.248.2 local 146.83.206.114 ttl 64
link set UACH up
address add 3ffe:8070:100c:2b02::b/64 dev UACH
route add 3ffe:8070:100c:2b02::a/64 dev UACH
Con esto se ha creado la interfaz de túnel UACH, en modo sit, es decir, IPv6 en IPv4. Luego
se activa la interfaz, se asigna el extremo local del túnel y se añade el extremo remoto. Hecho
esto ya se puede comenzar a probar la conexión, por ejemplo con un ping6 al otro extremo:
root@ipv6 root# ping6 -c4 3ffe:8070:100c:2b02::a
PING 3ffe:8070:100c:2b02::a(3ffe:8070:100c:2b02::a) from 3ffe:8070:100c:2b02::b
: 56 data bytes
64 bytes from 3ffe:8070:100c:2b02::a: icmp_seq=1 ttl=64 time=31.3 ms
64 bytes from 3ffe:8070:100c:2b02::a: icmp_seq=2 ttl=64 time=10.4 ms
64 bytes from 3ffe:8070:100c:2b02::a: icmp_seq=3 ttl=64 time=12.5 ms
64 bytes from 3ffe:8070:100c:2b02::a: icmp_seq=4 ttl=64 time=20.1 ms
--- 3ffe:8070:100c:2b02::b ping statistics --4 packets transmitted, 4 received, 0% loss, time 3000ms
rtt min/avg/max/mdev = 0.009/0.029/0.071/0.025 ms
Está funcionando.
Mediante un archivo de inicio:
Al igual que se hizo para cargar el módulo ipv6, ahora se pueden escribir estos mismos
comandos en un archivo y luego incluir el nombre de ese archivo (con su ruta por cierto) en
/etc/rc.d/rc.local.
Utilizando la herramienta de Red Hat:
Este método es el que finalmente se utilizó. Consiste en la creación del archivo ifcfg-uach
en el directorio /etc/sysconfig/network-scripts/ y cuyo contenido es el siguiente:
DEVICE=uach
BOOTPROTO=none
ONBOOT=yes
IPV6INIT=yes
IPV6TUNNELIPV4=146.83.248.2
IPV6ADDR=3ffe:8070:100c:2b02::b/64
IPV6_DEFAULTGW=3ffe:8070:100c:2b02::a
IPV6_DEFAULTDEV=uach
En él se especifican la dirección IPv4 remota, el extremo local del túnel, el gateway por
defecto y el dispositivo por defecto15 . Una vez guardado esto, se ingresan los siguientes
comandos en la consola:
root@ipv6 root# ln -s ifup-sit ifup-uach
root@ipv6 root# ln -s ifdown-sit ifdown-uach
15
Estas dos últimas variables sólo son leı́das en la versión 7.3 de Red Hat.
10
Con esto se crea un enlace simbólico hacia los archivos donde están las funciones necesarias
para subir y bajar el túnel. Luego de hecho esto, se reinicia el network con el correspondiente /etc/init.d/network restart. Con esto, ya se tiene un túnel cuyo nombre será uach.
Podemos hacer un ifconfig y se verá el dispositivo del túnel:
uach
Link encap:IPv6-in-IPv4
inet6 addr: 3ffe:8070:100c:2b02::b/64 Scope:Global
inet6 addr: fe80::9253:ce72/10 Scope:Link
inet6 addr: fe80::a00:1/10 Scope:Link
UP POINTOPOINT RUNNING NOARP MTU:1480 Metric:1
RX packets:692080 errors:0 dropped:0 overruns:0 frame:0
TX packets:692944 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:113649875 (108.3 Mb) TX bytes:60870452 (58.0 Mb)
En forma opcional se puede subir el túnel ejecutando simplemente:
root@ipv6 root# ifup uach
o bien para bajar:
root@ipv6 root# ifdown uach
3.2.2. Zebra
Para que una red de redes funcione hace falta que los routers tengan mapas (totales o parciales) de la red. Estos mapas pueden generarse manualmente mediante rutas estáticas o automáticamente mediante protocolos de ruteo. En la isla que se trabajó, bastó con rutas estáticas, sin
embargo, dado que se está experimentando es conveniente hacerlo también con los nuevos protocolos de ruteo y generar estos mapas automáticamente de ser posible. Se llama sistema autónomo
a “alguna red”, esto es, a una red o conjunto de redes controladas por una única entidad administrativa. Cada sistema autónomo decide cómo manejar sus redes internas independientemente
de cualquier otro, y se conecta a otros sistemas autónomos por medio de protocolos de ruteo externos. El protocolo de ruteo externo más común es el BGP16 . Este protocolo se maneja en base a
números de sistema autónomo (ASN). Básicamente, lo que hace BGP es establecer una relación de
pares entre dos routers que pertenecen a distintos sistemas autónomos y esos routers se informan
entre sı́ acerca de a qué redes conocen como hacer llegar paquetes, con lo que pueden formarse
los mapas de los que hablabamos antes.
Para el ruteo del tráfico de la red se usó el administrador de protocolos de ruteo Zebra17
versión 0.91a y el protocolo BGP-418 . Para usar este software se puede conseguir en el CD de
la distribución o bien bajarlo de Internet, de www.zebra.org por ejemplo. Una vez instalado se
necesitan básicamente dos archivos de configuración: zebra.conf y bgpd.conf; ambos ubicados
en /etc/zebra/. El contenido de zebra.conf es:
!
! Zebra configuration saved from vty
16
Se recomienda [6] y [11]
Más información en www.zebra.org
18
Border Gateway Protocol
17
11
!
2002/06/26 16:15:57
!
hostname zebra
password clave1
enable password clave2
!
interface lo
!
interface sit0
!
interface eth0
ipv6 nd send-ra
ipv6 nd prefix-advertisement 3ffe:8070:100c:b06::1:0/112
!
interface tunl0
!
Interesan el hostname, las claves y las lı́neas que comienzan con ipv6. Mediante la lı́nea
ipv6 nd send-ra se le está diciendo a Zebra que haga anuncio de router19 y con ipv6 nd prefix
advertisement 3ffe:8070:100c:b06::1:0/112 se especifica la red y el prefijo a anunciar. En cuanto a las claves, éstas son necesarias para la intervención en la consola del bgpd. Esta configuración
se logra creando este archivo en forma manual y luego iniciando Zebra de la forma service zebra
start. Una vez hecho esto se debe configurar el bgpd.conf. También se edita el archivo y se incluye
algo como:
!
! Zebra configuration saved from vty
!
2002/06/26 16:25:20
!
hostname bgpd
password ******
enable password ******
log file /var/log/zebra/bgpd.log
!
router bgp 45348
ipv6 bgp network 3ffe:8070:100c:b06::/64
ipv6 bgp neighbor 3ffe:8070:100c:2b02::a remote-as 45333
ipv6 bgp neighbor 3ffe:8070:100c:2b02::a interface uach
ipv6 bgp neighbor 3ffe:8070:100c:2b02::a description TunelUACH
ipv6 bgp neighbor 3ffe:8070:100c:2b02::a next-hop-self
ipv6 bgp neighbor 3ffe:8070:100c:b06::ffff:2 remote-as 64512
ipv6 bgp neighbor 3ffe:8070:100c:b06::ffff:2 interface iie
ipv6 bgp neighbor 3ffe:8070:100c:b06::ffff:2 description TunelIIE
ipv6 bgp neighbor 3ffe:8070:100c:b06::ffff:2 next-hop-self
!
line vty
!
En él se aprecian las configuraciones de las redes involucradas en el ruteo, primero se define
la red local, luego se da el extremo remoto del túnel asociado a ciertos parámetos: ASN remoto, interfaz, una descripción y el next-hop-self. Aquı́ se muestra la configuración del túnel con
la UACH y con el Instituto Informática Educativa. Esta última isla está usando un ASN privado. Creado este archivo se debe iniciar el bgpd mediante service bgpd start y deberı́a tomar la
19
Es decir que anuncia la red correspondiente.
12
configuración que se indica en el archivo modificado. Para asegurarse se podrı́a reiniciar el Zebra
mediante service zebra restart y luego iniciar el bgpd. Una forma de confirmar la configuración
es haciendo un telnet al puerto 2605 (bgpd) de la forma:
root@ipv6 root# telnet 127.0.0.1 2605
Debiendo realizar la siguiente secuencia:
Hello, this is zebra (version 0.91a).
Copyright 1996-2001 Kunihiro Ishiguro.
User Access Verification
Password:
bgpd> ena
Password:
bgpd# show ipv6 bgp summary
BGP router identifier 146.83.206.114, local AS number 45348
275 BGP AS-PATH entries
0 BGP community entries
Neighbor
AS
MsgRcvd MsgSent Up/Down State/PfxRcd
3ffe:8070:100c:b06::ffff:2 64512
508
38738
00:00:49 Connect
Description: TunelIIE
3ffe:8070:100c:2b02::a
45333
934898 12682 5d09h32m
344
Description: TunelUACH
Total number of neighbors 2
Aquı́ se muestra la configuración correcta de acuerdo a lo ingresado en el archivo bgpd.conf.
Con esto ya basta para que se realice el trabajo de ruteo, ahora sólo se necesita agregar clientes
a esta red que ya cuenta con un router BGP-4. Una vez hecho esto y después de innumerables
pruebas del sistema, se ha observado que el anuncio de router es válido solamente si el prefijo
es de 64 bits, ya que la MAC de la tarjeta es usada siempre para configurar la dirección IPv6.
Esto quiere decir, que se podrı́a usar este método siempre y cuando se cuente con un prefijo
menor o igual a 64, de otro modo se debe configurar a mano cada equipo (que es precisamente lo
que finalmente se hizo). Por lo investigado, la forma de hacer una real configuración automática
apegándose a la red designada serı́a usando DHCPv6, que actualmente se encuentra en desarrollo
y sólo hay paquetes de prueba, los que no se quisieron probar por ahora. Para mayores detalles
respecto de la creación de túneles y configuración de routers se recomienda [1] y [8].
3.3. Configuración de los clientes
A continuación se presenta la forma de configurar dos equipos que corren sistemas operativos diferentes. Primero se configura un equipo con Debian GNU/Linux para posteriormente
hacerlo con uno corriendo Windows 2000.
3.3.1. Configuración en Debian GNU/Linux
En esta distribución la carga del módulo ipv6 se puede hacer usando /etc/modules. Solamente hay que agregar el nombre ipv6 al final de este archivo para que Debian lo cargue en la
partida.
13
Las direcciones, prefijos y gateways de las diferentes interfaces de red del equipo se configuran en el archivo /etc/network/interfaces, que son utilizados por los programas ifup e ifdown
para levantar y bajar las interfaces de red.
# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)
# The loopback interface
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 146.83.206.112
netmask 255.255.255.0
broadcast 146.83.206.255
network 146.83.206.0
gateway 146.83.206.254
iface eth0 inet6 static
address 3ffe:8070:100c:b06::1:2
netmask 112
gateway 3ffe:8070:100c:b06::1:1
En este archivo conviven todas las configuraciones, ya sean de IPv4 o IPv6. Para asignar una
dirección estática de IPv6 a la tarjeta ethernet se usa una declaración del tipo
iface eth0 inet6 static
Después de esta lı́nea se puede agregar la dirección asignada al equipo. Usando address,
netmask y gateway se designa la dirección, prefijo de red y puerta de enlace. Hay que tener en
cuenta que en netmask se pone el número de bits de red, no una máscara de red.
address 3ffe:8070:100c:b06::1:2
netmask 112
gateway 3ffe:8070:100c:b06::1:1
En este ejemplo, el equipo con Debian tiene asignada la dirección 3ffe:8070:100c:b06::1:2/112
y el router de salida es 3ffe:8070:100c:b06::1:1.
Las lı́neas del archivo que comienzan con auto indican que la interfaz que se nombra a continuación será configurada al iniciarse el sistema.
Para mayor información se puede recurrir a la página de manual de interfaces, sección 5, con
el comando man interfaces. También se puede consultar la página de manual de los programas
ifup e ifdown con man ifup o man ifdown respectivamente.
3.3.2. Configuración en Windows 2000
La instalación del protocolo se hace como se explicó en la sección 3.1.2 en la página 8. Para
agregar direcciones, prefijo y router por defecto se deben ejecutar los siguientes comandos en una
ventana de DOS.
14
ipv6 adu 4/3ffe:8070:100c:b06::1:2
ipv6 rtu 3ffe:8070:100c:b06::1:0/112 4
ipv6 rtu ::/0 4/3ffe:8070:100c:b06::1:1
En la primera lı́nea se agrega la dirección, en la segunda se le da la red a la que pertenece
la dirección junto con el prefijo y la interfaz. Finalmente se establece el router por defecto a través
de la interfaz correspondiente, en este caso 4. Al hacerlo de esta forma se pierde la configuración
cuando se reinicie el equipo.
La manera de hacer permanente esta configuración es crear un archivo con extensión .cmd
que contenga estas instrucciones y posteriormente añadirlo en el Programador de Tareas para que
sea ejecutado cada vez que se inicia el equipo. Una vez hecho esto ya está configurado el equipo
correctamente para comenzar a usar el protocolo. Están disponibles por ejemplo las herramientas
comunes como ping6, tracert6, etc.
3.4. Pruebas
En esta sección se muestra una prueba del funcionamiento de la red. A continuación se presenta el resultado de ping6, tracert6 desde el cliente Windows 2000. Se opta por esto dado que la
prueba desde el mismo router puede no necesariamente provenir de una correcta configuración y
funcionamiento de Zebra.
Primero el ping6:
C:\>ping6 www.6bone.net
Pinging 6bone.net [3ffe:b00:c18:1::10] with 32 bytes of data:
Reply
Reply
Reply
Reply
from
from
from
from
3ffe:b00:c18:1::10:
3ffe:b00:c18:1::10:
3ffe:b00:c18:1::10:
3ffe:b00:c18:1::10:
bytes=32
bytes=32
bytes=32
bytes=32
time=739ms
time=737ms
time=736ms
time=736ms
C:\>
En este ping6 se pone el nombre del sitio dado que en la UACH están resolviendo nombres.
No es necesario escribir la dirección en hexadecimal.
Ahora se presenta un tracert6 para mostrar la ruta seguida por los paquetes hacia el 6 BONE.
C:\>tracert6 www.6bone.net
Tracing route to 6bone.net [3ffe:b00:c18:1::10]
over a maximum of 30 hops:
1
2
3
4
5
6
<1
5
469
603
737
738
ms
ms
ms
ms
ms
ms
<1
5
468
601
737
737
ms
ms
ms
ms
ms
ms
<1
5
468
603
737
737
ms
ms
ms
ms
ms
ms
3ffe:8070:100c:b06::1:1
3ffe:8070:100c:2b02::a
3ffe:8240:800d::1
3ffe:8280:0:2000::8
rap.ipv6.viagenie.qc.ca[3ffe:b00:c18:1:290:27ff:fe17:fc0f]
www.6bone.net [3ffe:b00:c18:1::10]
Trace complete.
15
C:\>
Viendo la salida del comando anterior, se aprecia que primero se envı́a el tráfico hasta el
router local (3ffe:8070:100c:b06::1:1), posteriormente se va al extremo del túnel en la UACH y
ası́ continúa por otros nodos hasta llegar al destino, que es el 6 BONE [3ffe:b00:c18:1::10].
Con esto se da por entendido que ahora sólo resta comenzar a levantar servicios que soporten
el protocolo, por ejemplo DNS, SMTP y WWW para comenzar. Todas estas implementaciones se
podrı́an realizar más tarde, de tal forma de probar el funcionamiento de los servicios habituales
con el nuevo protocolo.
4. Programación de aplicaciones para IPv6
La programación de redes se hace con Sockets, que es un medio que permite a los programas
conectarse a la red y poder enviar y recibir mensajes. La API (interfaz de programa de aplicación)
de Sockets ofrece estructuras de datos y funciones que permiten abstraerse de la red, puesto que
en el envı́o y recepción de la información no hay que preocuparse de cabeceras del paquete ni de
otras cosas relacionadas con la comunicación. Esto permite al programador preocuparse más del
tratamiento de los datos que de la comunicación en sı́.
El importante cambio introducido por IPv6 en el tamaño de las direcciones, hace que los
programas hechos para operar con la versión actual del protocolo IP no puedan funcionar con
la versión 6. Sin embargo, la conversión de los programas a IPv6 no es muy complicada, por
lo ya descrito anteriormente. Los cambios radican principalmente en las entructuras de datos
utilizadas, las que se tuvieron que adaptar a las nuevas exigencias del protocolo.
No se tratará con profundidad la programación de sockets para no extenderse demasiado. Las
explicaciones centrarán su atención en los sockets IPv6 principalmente.
En todo el desarrollo que se hará de programas de red basados en IPv6, se utilizarán los
Sockets de Linux, un sistema operativo libre y que provee todas las herramientas necesarias para
un desarrollo completo. Si se desea aprender más acerca de la programación de sockets en Linux,
puede consultar [15].
4.1. Sockets IPv6
Se utilizan las mismas funciones para la programación de sockets IPv4 utilizando C, con la
diferencia de que cambia la familia de protocolos por PF INET6 y la familia de direcciones por
AF INET6, las que se usan en la llamada socket y en la estructura socket. La declaración de la
función socket deberı́a ser de la forma:
sd = socket (PF_INET6, SOCK_STREAM, 0);
sd = socket (PF_INET6, SOCK_DGRAM, 0);
sd = socket (PF_INET6, SOCK_RAW, 0);
/* si se usa TCP */
/* si se usa UDP */
/* si se usa ICMP o Raw */
Todas devuelven un descriptor de socket para ser utilizado por otras funciones relacionadas
con la comunicación.
16
También cambia la estructura socket de sockaddr in a sockaddr in6, y ésta es la que se utiliza
en las llamadas a las funciones accept, bind y connect.
La estructura socket, que está ampliamente explicada en [10], contiene las siguientes variables:
struct sockaddr_in6
uint8_t
sa_family_t
in_port_t
uint32_t
struct in6_addr
uint32_t
};
{
sin6_len;
sin6_family;
sin6_port;
sin6_flowinfo;
sin6_addr;
sin6_scope_id;
/*
/*
/*
/*
/*
/*
length of this struct */
AF_INET6 */
transport layer port # */
IPv6 flow information */
IPv6 address */
set of interfaces for a scope */
Los miembros sin6 family, sin6 port y sin6 addr deben ser definidos antes de pasar la estructura a la funciones accept, bind o connect.
Por ejemplo, si se crea una variable con la estructura socket llamado destino con la declaración
struct sockaddr_in6 destino;
se podrı́an llenar los datos de la siguiente forma:
bzero (&destino, sizeof (destino));
destino.sin6_family = AF_INET6;
destino.sin6_port = htons (PORT);
La primera lı́nea usa la función bzero para poner a cero la estructura con el fin de agregar
datos. Luego se asigna la familia de direcciones con AF INET6 y finalmente se incluye el puerto.
Aquı́ se utiliza la función htons para convertir el valor del puerto a un número en bytes de red,
utilizado por el sistema operativo para la comunicación. Se puede encontrar más información en
[15].
Para agregar la información de la dirección se utiliza la función inet pton que transforma la
dirección alfanumérica a binario ordenado en bytes de red. Su utilización puede ser la siguiente:
if ( inet_pton (AF_INET6, "3ffe:8070:100c:b06::1:1",
&destino.sin6_addr) == -1 )
perror ("Error en inet_pton");
El resto de la programación es igual que siempre, salvo que para obtener la dirección de una
cierta estructura socket se debe utilizar la función inet ntop, que realiza lo inverso a lo que hace
inet pton. Se podrı́a utilizar la siguiente forma para almacenar el valor devuelto en una variable
de cadena y utilizarla para enviarla a la salida estándar.
char direccion_destino[INET6_ADDRSTRLEN];
inet_ntop (AF_INET6, &destino.sin6_addr,
direccion_destino, INET6_ADDRSTRLEN);
printf ("Intentando conectar a [%s]:%d...\n", direccion_destino,
ntohs (destino.sin6_port));
Se usa INET6 ADDRSTRLEN para asignar espacio suficiente para almacenar una dirección
IPv6 en una variable de cadena.
17
4.2. Ejemplos de cliente y servidor
Se presenta a continuación los dos programas sencillos de cliente y servidor TCP para IPv6.
La forma de programar protocolos UDP e ICMP no son tratados aquı́. Puede consultar [15] para
obtener información acerca de eso.
4.2.1. Cliente TCP6
Todo cliente funciona de la siguiente manera:
Crear un socket.
Crear una dirección destino para el servidor.
Conectar con el servidor.
Leer y visualizar cualquier mensaje.
Cerrar la conexión.
Para conectar con el servidor se utiliza la función connect, a la cual se le pasa el descriptor
del socket creado (sd), la estructura socket (destino) y su tamaño.
connect (sd, (struct sockaddr *) &destino, sizeof (destino));
Devuelve cero si no hay errores en la conexión y distinto de cero cuando los hay. Se puede
diagnosticar el error usando, por ejemplo, la función perror para obtener un mensaje descriptivo
del error producido.
Para enviar un mensaje al servidor remoto se puede utilizar la función send, que necesita
como parámetros el descriptor de socket, el búfer (o mensaje) a enviar, el tamaño de éste y unas
opciones del tipo de envı́o, que normalmente se dejan a 0. Para mayor información consulte [15].
send (sd, peticion, sizeof (peticion), 0);
Devuelve un valor menor que cero si se produce algún error.
Luego de enviar datos al servidor se puede recibir la respuesta de éste. Esto se hacer con la
función recv. Tiene como parámetros al descriptor del socket, un búfer donde almacenar los datos
recibidos, el tamaño máximo de ese búfer y finalmente opciones para la recepción. Tiene la misma
salida que la función send.
if ( send (sd, peticion, sizeof (peticion), 0) < 0 )
perror ("No se pudo enviar petición");
Finalmente queda cerrar la conexión, lo que se realiza con la llamada a close usando como
parámetro al descriptor de socket.
close (sd);
18
De esta forma, se puede formular el siguiente programa para el cliente.
#include
#include
#include
#include
#include
#include
#include
<sys/socket.h>
<sys/types.h>
<resolv.h>
<arpa/inet.h>
<unistd.h>
<stdlib.h>
<string.h>
#define MSG_MAX 32768
int main ( int argc, char **argv )
{
int sd;
struct sockaddr_in6 destino;
char peticion[] = "Aqui cliente IPv6 :-)";
char respuesta[MSG_MAX];
char direccion_destino[INET6_ADDRSTRLEN];
printf ("Prueba sencilla de un cliente IPv6\n");
if ( argc < 3 ) {
printf ("Uso: cliente6 <direccion IPv6> <puerto>\n");
exit (EXIT_FAILURE);
}
printf ("Intentado abrir un socket...\n");
if ( (sd = socket (PF_INET6, SOCK_STREAM, 0)) < 0 ) {
perror ("No se pudo crear el socket");
exit (EXIT_FAILURE);
}
else
printf ("Socket %d creado\n", sd);
bzero (&destino, sizeof (destino));
destino.sin6_family = AF_INET6;
destino.sin6_port = htons (atoi (argv[2]));
if ( inet_pton (AF_INET6, argv[1], &destino.sin6_addr) == -1 ) {
perror ("Error en inet_pton");
exit (EXIT_FAILURE);
}
inet_ntop (AF_INET6, &destino.sin6_addr,
direccion_destino, INET6_ADDRSTRLEN);
printf ("Intentando conectar a [%s]:%d...\n", direccion_destino,
ntohs (destino.sin6_port));
if ( connect (sd, (struct sockaddr *) &destino,
sizeof (destino)) != 0 ) {
perror ("No se pudo conectar al host");
exit (EXIT_FAILURE);
}
else {
inet_ntop (AF_INET6, &destino.sin6_addr,
direccion_destino, INET6_ADDRSTRLEN);
printf ("Conectado al host [%s]:%d\n", direccion_destino,
ntohs (destino.sin6_port));
19
}
printf ("Enviando peticion...\n");
if ( send (sd, peticion, sizeof (peticion), 0) < 0 ) {
perror ("No se pudo enviar peticion");
exit (EXIT_FAILURE);
}
else
printf ("Peticion enviada\n");
printf ("Esperando respuesta...\n");
if ( recv (sd, respuesta, MSG_MAX, 0) < 0 ) {
perror ("No se obtuvo respuesta");
exit (EXIT_FAILURE);
}
else
printf ("Respuesta recibida:\n%s\n", respuesta);
printf ("Cerrando la conexion...\n");
if ( close (sd) ) {
perror ("Problemas al cerrar el socket");
exit (EXIT_FAILURE);
}
else
printf ("Socket cerrado\n");
printf ("Saliendo\n");
return EXIT_SUCCESS;
}
4.2.2. Servidor TCP6
El servidor tiene una forma distinta de conectarse a la red respecto del cliente. Necesita asociar un puerto al socket y escuchar por él las conexiones que llegarán.
Para asociar un puerto con el socket ya iniciado se utiliza la función bind. Ésta recibe el descriptor del socket, la estructura y su tamaño. La estructura se forma con:
servidor.sin6_family = AF_INET6;
servidor.sin6_addr = in6addr_any;
servidor.sin6_port = htons (PUERTO);
Aquı́ el valor in6addr any se usa para asociar el socket con cualquier dirección, es decir, escuchar por todas las interfaces. La llamada para asociar el puerto serı́a ası́:
if ( bind (sd, (struct sockaddr *) &servidor,
sizeof (servidor)) != 0 )
perror ("No se puede asociar puerto");
Las lı́neas anteriores generarı́an un mensaje en caso de error.
Luego de asociar el socket con el puerto hay que crear una cola de espera para sockets con el
fin de atender varias solicitudes remotas. Esto se consigue con la función listen que necesita el
descriptor de socket y el número de espacios para espera.
20
if ( listen (sd, 10) != 0 )
perror ("No se puede escuchar por el puerto");
En el ejemplo anterior se genera una cola de 10 conexiones en caso de éxito, si no, se presenta
un mensaje de error.
Luego de esto, se está en condiciones de aceptar conexiones remotas. Para hacerlo, se llama
a la función accept. Es necesario pasar como parámetros el descriptor de socket, una estructura de
socket vacı́a y su tamaño. Esta estructura es llenada con los datos de la conexión entrante y puede
ser usada más adelante.
sd_tmp = accept (sd, (struct sockaddr *) &destino, &tamano);
Si la llamada es exitosa, devuelve un descriptor de socket para usarlo temporalmente y rellena los datos de la estructura. El socket devuelto se usa para comunicarse con el cliente usando las
llamadas anteriormente descritas send y recv. Esta interacción puede hacerse en un bucle condicional hasta que el usuario envı́e algún comando tipo QUIT.
Finalmente, el código fuente del servidor es el siguiente:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<sys/socket.h>
<sys/types.h>
<resolv.h>
<netinet/in.h>
<arpa/inet.h>
<unistd.h>
<stdio.h>
<stdlib.h>
<string.h>
<time.h>
#define MSG_MAX 32768
#define PUERTO 7777
int main ( int argc, char **argv )
{
int sd, sd_tmp, tamano;
struct sockaddr_in6 servidor, destino;
char recibido[MSG_MAX];
char direccion_destino[INET6_ADDRSTRLEN];
char *respuesta;
time_t tiempo;
respuesta = calloc (MSG_MAX + 10, sizeof (char));
printf ("Prueba sencilla de un servidor IPv6\n");
printf ("Intentado abrir un socket...\n");
if ( (sd = socket (PF_INET6, SOCK_STREAM, 0)) < 0 ) {
perror ("No se pudo crear el socket");
exit (EXIT_FAILURE);
}
else
printf ("Socket %d creado\n", sd);
21
bzero (&servidor, sizeof (servidor));
bzero (&destino, sizeof (destino));
servidor.sin6_family = AF_INET6;
servidor.sin6_addr = in6addr_any;
servidor.sin6_port = htons (PUERTO);
if ( bind (sd, (struct sockaddr *) &servidor,
sizeof (servidor)) != 0 ) {
perror ("No se puede asociar puerto");
exit (EXIT_FAILURE);
}
else
printf ("Socket asociado al puerto %d\n", PUERTO);
if ( listen (sd, 10) != 0 ) {
perror ("No se puede escuchar por el puerto");
exit (EXIT_FAILURE);
}
else
printf ("Aceptando conexiones en el puerto %d\n", PUERTO);
while ( 1 ) {
tamano = sizeof (destino);
sd_tmp = accept (sd, (struct sockaddr *) &destino, &tamano);
if ( sd_tmp < 0 ) {
perror ("Problemas al aceptar conexion\n");
exit (EXIT_FAILURE);
}
else {
inet_ntop (AF_INET6, &destino.sin6_addr, direccion_destino,
INET6_ADDRSTRLEN);
time (&tiempo);
printf ("\n%sConexion desde [%s]:%d\n", ctime (&tiempo),
direccion_destino, ntohs (destino.sin6_port));
}
bzero (&recibido, sizeof (recibido));
if ( recv (sd_tmp, recibido, MSG_MAX, 0) < 0 ) {
perror ("Error al recibir datos del cliente");
exit (EXIT_FAILURE);
}
snprintf (respuesta, MSG_MAX + 10, "Ud. dijo: %s", recibido);
printf ("Mensaje recibido:\n%s\nEnviando respuesta\n", recibido);
if ( send (sd_tmp, respuesta, strlen (respuesta), 0) < 0 ) {
perror ("No se pudo enviar respuesta");
exit (EXIT_FAILURE);
}
else
printf ("Respuesta enviada\n");
printf ("Cerrando la conexion...\n");
if ( close (sd_tmp) ) {
perror ("Problemas al cerrar el socket");
exit (EXIT_FAILURE);
22
}
else
printf ("Socket cerrado\n");
}
free (respuesta);
close (sd);
return EXIT_SUCCESS;
}
4.2.3. Pruebas del cliente y el servidor
Si se dispone de dos consolas gráficas, se puede correr el servidor en una y el cliente en otra.
El servidor es el primer programa que se ejecuta. Como el servidor usa el puerto 7777 no es
necesario tener privilegios de root para ejecutarlo.
[pablo@ipv6 pruebas]$ ./servidor6
Prueba sencilla de un servidor IPv6
Intentado abrir un socket...
Socket 3 creado
Socket asociado al puerto 7777
Aceptando conexiones en el puerto 7777
Si se ejecuta el cliente en la otra consola, se obtiene una salida parecida a ésta:
[pablo@ipv6 pruebas]$ ./cliente6 ::1 7777
Prueba sencilla de un cliente IPv6
Intentado abrir un socket...
Socket 3 creado
Intentando conectar a [::1]:7777...
Conectado al host [::1]:7777
Enviando peticion...
Peticion enviada
Esperando respuesta...
Respuesta recibida:
Ud. dijo: Aqui cliente IPv6 :-)
Cerrando la conexion...
Socket cerrado
Saliendo
El cliente recibe como parámetros la dirección IPv6 y el puerto para realizar la conexión. En el
ejemplo anterior se probó con la dirección local ::1 aunque también se podrı́a haber probado con la
dirección global que tiene asignado el computador, que para este caso serı́a 3ffe:8070:100c:b06::1:1.
Si se observa la consola donde está corriendo el servidor, se verá que quedó registrada una
conexión, con una salida parecida a ésta:
Wed Jul 24 00:09:14 2002
Conexion desde [::1]:33651
Mensaje recibido:
Aqui cliente IPv6 :-)
Enviando respuesta
23
Respuesta enviada
Cerrando la conexion...
Socket cerrado
Lo que se ha intentado hasta aquı́ es mostrar un poco la programación de sockets orientada a
IPv6. Se espera que con estos dos ejemplos sencillos se halla demostrado que no es difı́cil portar a
IPv6 programas que ya están hechos para IPv4.
Para mayor información acerca de sockets IPv6 consulte las referencias [10] y [12].
Referencias
[1] Peter Bieringer. IPv6-HOWTO. http://www.bieringer.de/linux/IPv6/.
[2] Eric Van Buggenhaut. Routing Avanzado con el Núcleo Linux. http://congreso.hispalinux.es/
congreso2001/actividades/ponencias/eric/.
[3] S. Deering and R. Hinden. Request for Comments 2460: Internet Protocol, Version 6 (IPv6) Specification. The Internet Society, December 1998.
[4] Bert Hubert et al. Linux Advanced Routing and Traffic Control HOWTO. http://www.tldp.org/
HOWTO/Adv-Routing-HOWTO.html.
[5] R. Hinden and S. Deering. Request for Comments 2373: IP Version 6 Addressing Architecture.
The Internet Society, July 1998.
[6] P. Marques and F. Dupont. Request for Comments 2545: Use of BGP-4 Multiprotocol Extensions
for IPv6 Inter-Domain Routing. The Internet Society, March 1999.
[7] C. Partridge. Request for Comments 1809: Using the Flow Label Field in IPv6, June 1995.
[8] Horacio Peña. Creación de una isla IPv6 y conexión al 6bone. http://www.uninet.edu/6fevu/
text/isla6bone.html.
[9] Luis Peralta. IPv6 @ UJI, Febrero 2002. http://spisa.act.uji.es/ peralta/ipv6/.
[10] J. Bound R. Gilligan, S. Thomson and W. Stevens. Request for Comments 2553: Basic Socket
Interface Extensions for IPv6. The Internet Society, March 1999.
[11] Y. Rekhter and T. Li. Request for Comments 1771: A Border Gateway Protocol 4 (BGP-4), March
1995.
[12] W. Stevens and M. Thomas. Request for Comments 2292: Advanced Sockets API for IPv6. The
Internet Society, February 1998.
[13] S. Thomson and T. Narten. Request for Comments 1886: DNS Extensions to support IP version 6.
The Internet Society, December 1998.
[14] S. Thomson and T. Narten. Request for Comments 2462: IPv6 Stateless Address Autoconfiguration.
The Internet Society, December 1998.
[15] Sean Walton. Programación de Socket Linux. Pearson Educación, 2001.
24

Documentos relacionados