scieee AI-readable full text Open interactive document viewer

Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6

Caballero Martos, José Antonio

Abstract

Las redes inalámbricas de sensores (WSN) han tenido un creciente impacto en el mundo de las telecomunicaciones en los últimos años. Esto se debe en parte al auge del Internet de las cosas (IoT). Estas redes permiten que dispositivos de bajo consumo puedan comunicarse entre sí formando una malla, o con otros equipos en Internet a través de una pasarela. El pequeño tamaño y la autonomía de los dispositivos que las forman permiten su despliegue en lugares antes insospechados. Y su uso en aplicaciones antes impensables. En este tipo de redes, la seguridad muchas veces puede ser un punto crítico. Pues las aplicaciones que se nutren de la información recogida por los sensores podrían verse gravemente afectadas si éstos fallan o si los datos son interceptados o modificados. Además, el aumento de dispositivos conectados a Internet ha traído consigo un gran aumento en la demanda de direcciones en Internet. Y es aquí donde entra en escena el protocolo IPv6. Este protocolo nos proporciona un espacio de direcciones mucho mayor que el protocolo IPv4 que es el que se viene usando hasta ahora en Internet, además de otros cambios. Es por eso que este trabajo tiene como finalidad el estudio de distintos mecanismos de autenticación y seguridad en redes inalámbricas de sensores que funcionen con IPv6. Y así poder hacer pruebas para asegurar las que se presupone que serán las redes que predominarán en un futuro cercano en el mundo de las telecomunicaciones.

Full text

Equation Chapter 1 Section 1 Trabajo Fin de Grado Grado en Ingeniería de las Tecnologías de Telecomunicación Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Autor: José Antonio Caballero Martos Tutor: Juan Antonio Ternero Muñoz Dep. Ingeniería Telemática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2016 iii Trabajo Fin de Grado Grado en Ingenieria de las Tecnologias de Telecomunicacion Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Autor: José Antonio Caballero Martos Tutor: Juan Antonio Ternero Muñiz Profesor Colaborador Dep. Ingeniería Telemática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2016 v Trabajo Fin de Grado: Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Autor: José Antonio Caballero Martos Tutor: Juan Antonio Ternero Muñiz El tribunal nombrado para juzgar el Proyecto arriba indicado, compuesto por los siguientes miembros: Presidente: Vocales: Secretario: Acuerdan otorgarle la calificación de: Sevilla, 2016 El Secretario del Tribunal vii A mi abuelo Pepe, que no podrá ver cómo acabo mis estudios, como él hubiera querido. Pero estoy seguro de que estaría muy orgulloso. ix Agradecimientos Este trabajo supone el final de mi etapa como estudiante de Grado en Ingeniería de las Tecnologías de Telecomunicación. Han sido unos años muy duros, pero también muy buenos. Y siento una gran satisfacción ahora que estoy a punto de terminar. En primer lugar, quiero agradecerle a todo el profesorado de la escuela su dedicación. Pues me han ayudado a formarme en el ámbito de la ingeniería, y también como persona. Estoy orgulloso de haber tenido la oportunidad de aprender de ellos. Quisiera agradecer en especial a Juan Antonio Ternero Muñiz, tutor de este trabajo, por haberme ayudado y guiado en su realización. También me gustaría dar las gracias a todos los miembros de mi familia, los que están y los que una vez estuvieron. Sobre todo a mis padres, pues sin su sacrificio no habría podido nunca llegar a escribir estas líneas. Estoy orgulloso de tener a la madre más brillante y trabajadora de este mundo. Sin los valores de esfuerzo, constancia y buen hacer de las cosas que me ha inculcado no sería quien soy hoy. Y dudo que hubiera podido llegar hasta aquí. Y gracias también a mi padre, pues sin su pasión por las nuevas tecnologías, y ese Pentium II que me regaló en su día. No sé si habría llegado a despertar en mí el interés por estudiar esta carrera sin él. No quiero olvidarme tampoco de mi hermana, que aunque siempre sepa como darme la lata y no dejarme estudiar, me quiere y aprecia muchísimo, igual que yo a ella. Y a mi tata, que todos los días preguntó por el estado de este trabajo y tuvo que escuchar cada batallita librada durante el curso. Por último, quiero agradecer al destino por haberme cruzado con los “Telecolegas”, y a ellos por haber estado disponibles y dispuestos siempre que los he necesitado. Compañeros de clase que tras grandes trabajos en equipo, prácticas y tardes de estudio, pasaron a ser grandes y buenos amigos. Me han ayudado y enseñado mucho, y por eso les estaré eternamente agradecido. José Antonio Caballero Martos Sevilla, 2016 4.9 Pila de red 35 5 Desarrollo del entorno de pruebas 38 5.1 Pruebas 38 5.2 Entorno de pruebas 38 5.3 udp-sender.c 39 5.3.1 Configuración del dispositivo 39 5.3.2 Envío de la información 42 5.4 udp-sink.c 47 5.4.1 Configuración del dispositivo 47 5.4.2 Recepción de información 51 5.5 project-conf.h 52 5.6 Makefile 54 6 Pruebas y resultados 57 6.1 Cooja 57 6.2 Montaje del escenario 58 6.2.1 Parámetros de la simulación 59 6.3 Simulación 63 6.3.1 Consumo energético 63 6.3.2 Tamaño del programa 64 6.3.3 Retardo en las comunicaciones 65 6.4 Resultados 66 6.4.1 Consumo energético 66 6.4.2 Tamaño del programa 69 6.4.3 Retardo en las comunicaciones 73 6.5 Conclusiones 74 6.6 Líneas futuras 75 Anexo A: Código de las pruebas 78 Bibliografía 101 Glosario 105 xvii ÍNDICE DE TABLAS Tabla 3–1. Comparación entre las redes 802.15.4 y las redes típicas IPv6 23 Tabla 5–1. Mecanismos de autenticación y cifrado a usar en el escenario de pruebas 54 Tabla 6–1. Mecanismos de autenticación y cifrado a usar en el escenario de pruebas 59 Tabla 6–2. Potencia media consumida por los distintos mecanismos de autenticación y/o cifrado en el dispositivo emisor 66 Tabla 6–3. Diferencia de potencia media de los distintos mecanismos de autenticación y/o cifrado en el dispositivo emisor 68 Tabla 6–4. Diferencia de potencia media de los distintos mecanismos de autenticación y/o cifrado en el dispositivo emisor 69 Tabla 6–5. Tamaño del programa del sensor receptor 69 Tabla 6–6. Diferencia de tamaño del programa del sensor receptor con respecto a no usar ninguna medida de autenticación y seguridad 70 Tabla 6–7. Tamaño del programa del sensor receptor 72 Tabla 6–8. Tiempos de envío y recepción de los mensajes en cada una de las medidas 73 Tabla 6–9. Retardos medidos, retardo medio y diferencia de retardo en cada una de las medidas 73 xix ÍNDICE DE FIGURAS Figura 2-1. Estimacion del numero de dispositivos conectados a Internet desde el año 2003 al 2020. Fuente: Cisco IBSG, abril de 2011 7 Figura 2-2. Estructura por capas y sectores de las aplicaciones del IoT. Fuente: ITU-T 7 Figura 2-3. Ejemplo de red IoT. Fuente: Micrium 9 Figura 2-4. Tecnologías de comunicaciones. Fuente: Xataka 10 Figura 2-5. Agotamiento direcciones IPv4. Fuente: Google 11 Figura 2-6. Número de direcciones IPv4 frente a IPv6. Fuente: Google 12 Figura 2-7. Tráfico IPv6 global en el acceso a Google. Fuente: Google 13 Figura 2-8. Mapa del tráfico IPv6 global en el acceso a Google. Fuente: Google 13 Figura 2-9. Diferencias entre las cabeceras IPv4 e IPv6. Fuente: Cisco 14 Figura 2-10. Cabeceras de extensión en IPv6 15 Figura 2-11. Estructura direcciones IPv6. Fuente ciscolinux.co.uk 16 Figura 3-1. Ejemplo de topología en estrella y punto a punto en redes 802.15.4. Fuente: Wikipedia 21 Figura 3-2. Ejemplo de algoritmo MAC. Fuente: Wikipedia 22 Figura 3-3. Cabecera 802.15.4 con el uso de las distintas medidas de autenticación y seguridad 23 Figura 3-4. Cabecera 6LoWPAN sobre 802.15.4. Fuente: Atlassian 24 Figura 3-5. Modos IPsec 25 Figura 4-1. Ejemplo de proceso de envío y entrega de un evento de forma síncrona 28 Figura 4-2. Ejemplo de ejecución de procesos en contextos preferente y cooperativo en Contiki 30 Figura 4-3. Ejemplo de proceso de envío y entrega de un evento de forma asíncrona 31 Figura 4-4. Ejemplo de proceso de envío y entrega de un evento de forma síncrona 31 Figura 4-5. Máquina de estados de un hilo 32 Figura 4-6. Máquina de estados de un hilo 33 Figura 4-7. Ejemplo de transmisión de paquetes 35 Figura 5-1. Diagrama paso de mensajes del escenario de pruebas 39 Figura 5-2. Tamaño de un unsigned int en el TMote Sky 44 Figura 5-3. Límite de tamaño de un unsigned int en el TMote Sky 44 Figura 5-4. Información del paquete de anuncio de servicio multicast de la app servreg-hack 49 Figura 5-5. Contenido de un paquete multicast de la app servreg-hack que anuncia el servicio con SERVICE_ID 190 49 Figura 6-1. Diagrama del escenario de pruebas 58 Figura 6-2. Diagrama paso de mensajes del escenario de pruebas 58 Figura 6-3. Parámetros para la simulación en Cooja 59 Figura 6-4. Creación de un sensor en Cooja 60 Figura 6-5. Posición del sensor en Cooja 60 Figura 6-6. Vista del escenario a simular en Cooja 61 Figura 6-7. Editor de scripts para las simulaciones en Cooja 62 Figura 6-8. Parámetros de Collect View en Cooja 63 Figura 6-9. Consumo energético medio en en Cooja 64 Figura 6-10. Tamaño de los programas para el sensor TMote Sky 65 Figura 6-11. Salida estándar de ambos dispositivos 65 Figura 6-12. Gráfico de la potencia media usada en la CPU del sensor emisor 67 Figura 6-13. Gráfico de la potencia media usada en la transmisión por radio del sensor emisor 67 Figura 6-14. Gráfica del tamaño que ocupa en ROM y en RAM el programa del sensor receptor 70 Figura 6-15. Gráfica de la diferencia de tamaños en ROM de cada medida de autenticación y/o cifrado con respecto a no usar ninguna medida 71 Figura 6-16. Gráfica del tamaño que ocupa en ROM el programa del sensor emisor 72 Figura 6-17. Gráfica de la diferencia de retardo medio entre las distintas medidas 74 Figura 6-18. Escenario de una WSN conectada a Internet a través de una pasarela 75 1 1 INTRODUCCIÓN ste Trabajo Fin de Grado consiste en el desarrollo de un escenario de pruebas de mecanismos de autenticación y seguridad para redes WSN con IPv6. A día de hoy, a pesar de que hay muchos estándares, casi todas las soluciones de WSN tienden a ser propietarias. Y cada una resuelve sus problemas de una forma diferente. Especialmente en el ámbito de la seguridad. Por eso este trabajo intenta desarrollar un escenario sobre el que probar los distintos mecanismos de autenticación y seguridad. De esta forma se pueden probar las ventajas e inconvenientes de las distintas soluciones de seguridad. Y así evaluar cuál es la mejor opción para una WSN que se piense desplegar. Teniendo en cuenta consumo energético, dificultad de la implementación y/o mantenimiento (distribución y renovación de claves, certificados, etc.). 1.1 Motivación El “Internet de las cosas” se ha convertido en un tema omnipresente en el ámbito tecnológico a día de hoy. Este fenómeno no tiene precedentes en lo que a temática y escala se refiere, y está transformando muchos sectores como el industrial. Los dispositivos llevan años conectándose a la red, pero ahora son más pequeños y móviles. El Internet de las cosas ofrece muchas ventajas, pero también supone un reto en el aspecto de la seguridad. Y es que resulta un riesgo tener toda nuestra información en la red si no se maneja de forma segura. Los dispositivos de este tipo de redes suelen disponer de pocos recursos. Ello hace que algunas medidas de seguridad, que requieren de alta carga computacional y un consecuente gasto de energía, deban ser usadas de manera eficiente. Por otro lado IPv6 es el futuro de Internet y parece ser que pronto será el protocolo que predomine. Con la idea de probar las distintas medidas de autenticación y seguridad en el ámbito de las redes de sensores con IPv6 nace este proyecto. 1.2 Objetivos Este trabajo tiene como objetivo el desarrollo de un entorno de pruebas de mecanismos de autenticación y seguridad en redes de sensores con IPv6. Se usará Cooja, que es un simulador de redes de equipos que usan Contiki OS, un sistema operativo para microcontroladores de bajo coste y consumo. Contiki permite a los dispositivos conectarse a Internet a través de protocolos de bajo consumo como 6LoWPAN (IPv6 over Low power Wireless Personal Area Networks). Se harán distintas pruebas en redes inalámbricas de sensores implementando medidas de autenticación y cifrado de los mensajes de la red. Comprobando que la comunicación es posible y examinando los mensajes intercambiados entre los nodos para el envío de los datos firmado o cifrado. Finalmente se evaluarán las distintas medidas probadas en base a aspectos como el consumo energético, retardo en las comunicaciones o aumento del tamaño de programa. E Introducción 2 1.3 Fases de realización Para llevar a cabo este trabajo se han seguido las siguientes fases en su desarrollo:  Documentación: En esta fase se realizó un estudio de todo lo relacionado con el IoT. El propósito del mismo y su situación actual. Así como sus protocolos y plataformas más usadas. También se llevó a cabo un estudio de IPv6, su implementación para redes de sensores inalámbricas, 6LoWPAN. Y los distintos problemas de seguridad que existían en IPv6 y las soluciones que se dan en las redes de sensores para mitigar estas amenazas.  Preparación del entorno de trabajo: En esta fase se barajaron las distintas alternativas para establecer el entorno de pruebas. Como no disponíamos de los recursos hardware necesarios, se optó por empezar a trabajar con el simulador Cooja de Contiki OS y así poder simular redes de sensores inalámbricas.  Selección y desarrollo de las medidas de seguridad: De las medidas de seguridad buscadas en la primera fase se llevó a cabo una selección. Se usó la capa llsec (link-layer security) que incluye Contiki.  Realización de las pruebas: Se probaron las distintas medidas de autenticación y cifrado en una WSN de dispositivos Contiki que se diseñó en el simulador Cooja.  Verificación de los resultados de las pruebas: En esta fase se comprobó el correcto funcionamiento de las medidas de autenticación y cifrado de paquetes utilizadas.  Redacción de la memoria: Por último, se llevó a cabo la redacción de este documento para transmitir la experiencia y conocimiento obtenido en el desarrollo de este Trabajo de Fin de Grado. 1.4 Estructura de la memoria La memoria consta de las siguientes partes:  En primer lugar, se hará un acercamiento al estado actual de Internet (Internet de las Cosas, IPv6 y seguridad TIC).  Se evaluarán todas las tecnologías implicadas en el trabajo, así como las diferentes alternativas. Se explicará por qué se eligieron aquellas seleccionadas para formar parte del entorno de trabajo frente a las posibles alternativas. Una vez escogida la tecnología, se explicacará más exhaustivamente. Tratando aspectos técnicos.  Después desarrollaremos las pruebas de autenticación y cifrado en la red de sensores. Para ello se usará el lenguaje de programación C.  Una vez desarrolladas las pruebas pasaremos a realizarlas en el simulador Cooja y a analizar los resultados. Prestaremos especial atención a los mensajes intercambiados en los distintos escenarios y verificaremos el correcto funcionamiento de los mecanismos.  Cuando se tenga un correcto funcionamiento de los escenarios, se estudiarán aspectos como el consumo energético, retardo en las comunicaciones y el incremento en el tamaño del programa que suponen las distintas medidas. 3 3 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 5 2 ESTADO DEL ARTE a evolución de las tecnologías de la información en los últimos tiempos ha provocado cambios significativos en nuestras vidas. Hoy en día es cada vez más frecuente que los objetos cotidianos estén conectados a Internet. Internet ha contribuido bastante al desarrollo de las tecnologías de la información. Ha supuesto el acceso universal a la información. Ahora cualquiera puede tener acceso al instante a un volumen de información enorme. Pero no sólo eso, gracias a él surgieron nuevas formas de generación y transmisión de información por parte de los usuarios. De esta forma cualquiera puede aportar información de una infinita variedad de temas en la red. Las mejoras en tecnología no sólo añaden cada vez más funcionalidades, sino que por lo general tienden a simplificar bastante lo que ya había. Y es que sin la capacidad de los usuarios para manejar de manera sencilla los dispositivos que se conectan a la red o la información que se encuentra en ésta, es imposible lograr un buen uso de los recursos. De esta forma hemos pasado de una red orientada a clientes a una red que interconecta todas las cosas. De esta forma los clientes pueden seguir conectándose entre sí a través de múltiples dispositivos. Pero además los dispositivos se pueden valer de datos que recogen otros dispositivos, comunicándose a través de Internet. Y es aquí donde entra en juego el concepto de Internet de las Cosas. Este trabajo está pensado para usarse en el ámbito del IoT, y es por eso que lo estudiaremos a continuación. Por otro lado el gran número de dispositivos a Internet ha sobrepasado con creces el límite que se pensó cuando se diseñó el protocolo que predomina en la red (IPv4). Y aunque existen varios factores atenuantes de este problema, el agotamiento de las direcciones IPv4 es un hecho. Por ello surgió un nuevo protocolo en Internet. IPv6 sería la solución a largo plazo para este problema. Y por eso lo estudiaremos también más adelante. Otro aspecto por el que no se preocuparon excesivamente en el diseño original de Internet fue la seguridad. Esto hizo que cuando llegó la revolución del uso de Internet fuera muy fácil desarrollar amenazas en la red. En este aspecto no se avanzó demasiado en IPv6, no habiendo diferencias significativas en cuanto a seguridad. Más adelante hablaremos del estado de la seguridad y en concreto en redes IPv6. L "Los productos del IoT no están solamente orientados a la vida cotidiana. Tendrán un gran impacto en el mundo empresarial. E igual que aquellas compañías que ignoraron Internet al principio del siglo, aquellos que pasen del IoT se arriesgarán a quedarse atrás" Jared Newman, en Fast Company Estado del arte 12 Figura 2-6. Número de direcciones IPv4 frente a IPv6. Fuente: Google La realidad es que el protocolo IPv6 está cada vez más extendido, y así lo demuestran por ejemplo las estadísticas de Google. Alrededor de un 10% del tráfico que accede a su portal lo hace a través de IPv6. Es decir, ya no es una cifra nada despreciable. Particularmente en países como EEUU la cifra aumenta a más de un 24% ó un 43% en países como Bélgica. 3 Este protocolo encaja muy bien con el IoT. Ya que si vamos a tener conectados a Internet la mayoría de objetos nos será imposible direccionarlos con el actual protocolo IPv4. Tiene también bastantes mejoras en el ámbito de la movilidad tanto de los nodos finales como de los nodos encaminadores. Resuelve la barrera del NAT y ahora sí, cada equipo podrá tener su propia IP pública. El uso de NAT suponía que no hubiera una conexión IP extremo a extremo. En lugar de eso había un equipo intermedio que cambiaría la IP origen/destino por la suya según si los paquetes salen/entran de la red. De esta forma, con el uso de IPv6, los equipos serán directamente accesibles desde la red. Existe una versión comprimida de IPv6 llamada 6LoWPAN. Esta versión está pensada para dispositivos con limitaciones en recursos como memoria, batería, capacidad de procesamiento, etc. 6LoWPAN reduce el espacio de direcciones de IPv6 y requiere de encaminadores que traduzcan esas direcciones comprimidas a direcciones IPv6 normales. Por eso lo escogimos para este Trabajo de Fin de Grado. Porque es esencial para evitar que se frene el crecimiento de Internet y permite que todos los dispositivos se comuniquen entre sí directamente. IPv6 abre un nuevo campo de posibilidades infinitas para el desarrollo de nuevos servicios. 3 Google IPv6 estadísticas 2016 (https://www.google.com/intl/es/ipv6/index.html) 13 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Figura 2-7. Tráfico IPv6 global en el acceso a Google. Fuente: Google Figura 2-8. Mapa del tráfico IPv6 global en el acceso a Google. Fuente: Google Estado del arte 14 2.2.2 Conceptos En este apartado se repasarán los conceptos mínimos de IPv6 para entender por qué es útil para el IoT. Veremos cómo está relacionado con el protocolo 6LoWPAN que veremos en el siguiente capítulo. Y su utlidad por tanto en el ámbito de las WSN. La cabecera de los paquetes IPv6 ha cambiado con respecto a la de IPv4:  Número de campos: Ha sido reducido de 12 a 8.  Tamaño de la cabecera: La cabecera IPv6 se ha fijado en 40 bytes y se ha alineado a 64 bits. Esto permite que se pueda llevar a cabo un reenvío de paquetes más rápido en los routers basados en hardware.  Tamaño de las direcciones: Se ha incrementado de 32 bits a 128 bits. Figura 2-9. Diferencias entre las cabeceras IPv4 e IPv6. Fuente: Cisco Los campos más importantes son la dirección destino y origen. Ya que son los que permiten identificar a cada uno de los dispositivos conectados a Internet. Como ya vimos en el apartado anterior, esto permite que haya 2128 = 3,4 × 1038. En vez de la cantidad que había en IPv4 (232 = 4.294.967.296), que se ha quedado pequeña para el aumento de direcciones que supone el IoT. Por otra parte tenemos las cabeceras de extensión. Que mantienen la cabecera con un tamaño fijo y permiten añadir funcionalidades a IPv6 después de la cabecera. Existen muchas cabeceras de extensión definidas, en la figura podemos ver el orden en el que deben aparecer. 15 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Figura 2-10. Cabeceras de extensión en IPv6 Las cabeceras de extensión por tanto proporcionan:  Flexibilidad: Permitiendo por ejemplo el uso de seguridad para cifrar los datos del paquete.  Optimización en el procesado del paquete: Con excepción de las cabeceras de extensión salto a salto (hop by hop), todas las demás se procesan solamente en los nodos extremos de la comunicación. Esto permite que cada router en el camino no tenga que procesar el paquete.  Cadena de cabeceras de extensión: Las cabeceras de extensión se van añadiendo una detrás de otra. Empezando por la cabecera básica se va apuntando a la siguiente cabecera con el campo de siguiente cabecera. En cuanto al direccionamiento ampliado de IPv6, sus beneficios son los siguientes:  Cantidad de direcciones: Ya se ha visto que se proporcionan muchas más direcciones. Que permitirán satisfacer la demanda actual y futura.  Autoconfiguración: Se simplifican los mecanismos de autoconfiguración para la asignación de direcciones.  Gestión: La gestión de las direcciones resulta más sencilla para los organismos que se encargan de repartir las direcciones. Pues ahora se tiene espacio suficiente para asignarlas jerárquicamente. Se simplificará la tarea de enrutamiento gracias a la agregación de rutas.  Seguridad: Al eliminar la NAT, se podrá usar IPsec de extremo a extremo. Los tipos de direcciones IPv6 son los siguientes:  Unicast: Se usan para enviar un paquete desde un origen a un solo destino. Éstas son las más habituales.  Multicast: Sirven para enviar un paquete desde un origen a varios destinos. Es posible gracias a los protocolos de enrutamiento multicast, que permiten a los routers saber dónde se encuentran los destinos que esperan recibir los paquetes. También se usan en el mismo enlace para establecimiento de vecindades y otras tareas.  Anycast: Permite el envío de un paquete desde un origen hasta el destino más cercano dentro de un conjunto de posibles destinos. Estado del arte 16  Reserved: Son grupos de direcciones que se encuentran reservados para usos especiales. Por ejemplo los que se usan para documentación o ejemplos. Las direcciones se componen de dos partes: el identificador de red (64 bits) y el identificador de interfaz (64 bits). El identificador de red viene a su vez a dividirse en dos partes: el prefijo de enrutamiento (48 bits o más) y el identificador de subred (16 bits o menos). Figura 2-11. Estructura direcciones IPv6. Fuente ciscolinux.co.uk Y dentro de las direcciones unicast encontramos también varios tipos  Link-local: Direcciones locales al enlace. Están siempre presentes en una interfaz IPv6 que esté conectada a una red. Y todas empiezan por el prefijo FE80::/10. Los dispositivos las usan para comunicarse con otros equipos en la misma red local. Pero no se pueden usar para mantener comunicaciones con otras redes.  Unique Local: Llamadas también ULA (Unique Local Address). Todas empiezan por FC00::/8 ó FD00::/8. Se usan para comunicaciones locales dentro de una misma organización. No son enrutables dentro de Internet.  Global Unicast: Son el equivalente a las direcciones públicas IPv4. Son únicas en todo Internet y se pueden usar para enviar paquetes desde un sitio a cualquier destino en Internet. Con lo visto podemos apreciar el potencial de IPv6 para el IoT. Podemos ponerle direcciones IPv6 unicast globales a todo dispositivo que queramos. De esta forma todos los dispositivos pueden colaborar entre sí de una forma antes impensable. Podemos imaginar lo que supone para las redes de sensores desplegadas por todo el mundo. Que gracias a esta tecnología podrán enviar todos los datos recolectados o ser accedidos desde cualquier parte del mundo para crear una red a escala global que tenga las mediciones de los valores físicos. Si todos esos valores se almacenan y se procesan, se pueden tener aplicaciones como las que vimos en el apartado anterior. Para obtener las direcciones ha surgido un nuevo mecanismo llamado SLAAC (Statless Addresss Autoconfiguration) que no existía en IPv4. De forma que ahora las formas de asignar una dirección a una interfaz son las siguientes:  Estáticamente: Se configura manualmente la dirección IPv6 que le quieres asignar a tu dispositivo. Normalmente también tendrán que configurarse manualmente otros parámetros. Como por ejemplo la pasarela para enviar los paquetes fuera de la red.  DHCPv6: Tiene la misma función que el DHCP en IPv4. Necesitas un servidor que asigne dinámicamente las direcciones a los equipos. El servidor mantiene un registro de las direcciones asignadas. Por eso se llama autoconfiguración de las direcciones con estado. 17 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6  SLAAC: Autoconfiguración de la dirección independiente del estado 4 . Es un nuevo mecanismo introducido en IPv6. Permite configurar automáticamente todos los parámetros de un dispositivo IP usando el router que da conectividad a la red. La ventaja de SLAAC es que simplifica la configuración de dispositivos con pocos recursos. La ventaja de usar SLAAC es que se simplifica mucho la configuración de dispositivos con menos recursos. Como por ejemplo los sensores que usaremos en este trabajo. 2.3 Seguridad Si hay una cosa en la que la gran mayoría de la comunidad de Internet está de acuerdo es en que la seguridad es una prioridad ahora mismo en Internet. Es necesario tenerla en cuenta a la hora de desarrollar nuevos sistemas y protocolos. Después de ver los grandes avances que ha supuesto y supondrá en el futuro para la sociedad el IoT, hay que tener en cuenta los grandes riesgos que conllevará su implantación si este tipo de equipos y redes son objeto de ciberataques. Al fin y al cabo, las organizaciones dependen para su funcionamiento de la información que manejan. Si no la tienen disponible, las organizaciones no podránn trabajar. O en el caso de que ésta se vea alterada por alguien que no debería tener acceso a ella, la organización estaría funcionando sobre datos inválidos. He aquí los distintos servicios que se deben conseguir para tener un nivel de seguridad razonable en un sistema:  Confidencialidad: Si la información que se transmite resulta importante y se pretende que sea secreta para dispositivos intrusos, habrá que hacerla confidencial. Normalmente ésto se consigue cifrando los datos con una clave que ambos dispositivos (origen y destino de la comunicación) conocen.  Autenticación: Permite que los dispositivos que participan en una transmisión puedan asegurarse de que el dispositivo que transmite es realmente quien dice ser. De esta forma se evita que dispositivos ilegítimos puedan enviar información falsa en la red. Así como tampoco podrían suplantar la identidad de dispositivos legítimos. Para conseguirlo normalmente se acompaña el mensaje de un código de autenticación de mensaje (MAC). Este código es un hash del mensaje cifrado con una clave conocida por ambos. La clave puede estar asignada para un dispositivo en concreto o usarse la misma en toda la red.  Integridad: Es importante que el mensaje se reciba exactamente de la misma forma en que fue enviado. De manera que nada lo altere por el camino a su destino o no haya pérdidas que alteren la información. Esto se consigue con un código redundante cíclico (CRC). Como este CRC podría ser alterado por un atacante, se suele usar el MAC, que además de autenticación proporciona integridad.  Disponibilidad: Se encarga de asegurar que los nodos de la red de sensores presten el servicio para el que están pensado. Incluso aunque sufran ataques de denegación de servicio (DoS). Conseguir esto en las redes de sensores inalámbricas resulta extremadamente difícil, pues los ataques DoS pueden tener como objetivo muchas capas. Por ejemplo, atacando con interferencias a la señal de radio para evitar las comunicaciones. También pueden tratar de agotar la batería de los sensores enviando mensajes falsos para hacer que los sensores los procesen.  Autorización: Se asegura de que sólo los nodos autorizados pueden acceder a los servicios y recursos de la red. Si pensamos en los usuarios particulares u organizaciones, los peligros que pueden ocasionar fallos de seguridad en el IoT también son cuanto menos preocupantes. Hacer que todos los objetos se conecten a Internet tiene sus ventajas, siempre y cuando éstos lo hagan de forma segura. Un atacante podría aprovecharse de la falta de seguridad en un dispositivo cuantificador de salud, obtener la localización de la víctima. O tener el control de dispositivos como marcapasos, bombas de insulina, etc. Poniendo en riesgo la salud de las personas. 4 RFC 4862 (http://tools.ietf.org/html/rfc4862) Estado del arte 18 En las viviendas por ejemplo podría controlar las cerraduras o luces. O enviar spam a través de malware instalado en una nevera inteligente. En el ámbito de la conducción podrían aprovechar fallos de seguridad para abrir las puertas de un coche remotamente. O desactivar remotamente el sistema de control de frenos. Siendo un peligro para la seguridad de las personas. Por tanto, vemos que la seguridad juega un papel crucial en el despliegue del IoT y en su éxito. Ya que si no se toman las medidas adecuadas se pueden llegar a dar lugar hechos totalmente catastróficos. Un 73% de los ejecutivos del sector esperan que el IoT produzca un aumento de las amenazas de seguridad en los próximos dos años. 5 Por otro lado un 78% de los profesionales de la seguridad de las tecnologías de la información piensan que no tienen los medios suficientes y les falta control y visibilidad para gestionar y asegurar nuevos tipos de dispositivos conectados a la red. 6 A esto hay que añadir que un 46% piensan que las actuals políticas de seguridad no son válidas para los dispositivos del IoT. 7 Con esto podemos hacernos una idea de lo importante que va a ser el tema de la seguridad en este tipo de redes para los negocios pronto. En cualquier caso, dependiendo de la naturaleza de la red y aplicación que tenga, necesitará estar más o menos asegurada. Normalmente, aplicar medidas de seguridad conlleva mayor dificultad para el despliegue y mantenimiento de la red, y también un mayor gasto de la batería de los equipos para, por ejemplo, llevar a cabo operaciones de cifrado y descifrado. Así que las medidas de seguridad se deben de usar en consonancia con el objetivo y las capacidades de la red y los equipos. Las políticas de seguridad intentan garantizar la autenticidad, confidencialidad, integridad y disponibilidad de los datos que se manejan. En el caso de las redes de sensores puede que no nos interese que los datos que generan los sensores sean leídos por otro, porque sean confidenciales. Tampoco que alguien los falsifique haciéndose pasar por otro sensor o modificando los datos que generan los sensores. Ni que se lleve a cabo una denegación de servicio de los sensores y no dispongamos de sus lecturas. Todo depende de la aplicación y por eso en este trabajo se intentará montar un escenario para probar los distintos tipos de políticas para elegir la que más se adecue a la aplicación que se quiera desarrollar. Existen varios tipos de mecanismos de seguridad: Preventivos, defectivos y correctivos.  Mecanismos preventivos: Detienen ataques y por tanto actúan antes de que ocurra ningún incidente de seguridad  Mecanismos detectores: Ayudan a detectar agentes no deseados. Normalmente emiten alertas y registrar incidencias. Actúan también antes de que ocurra algún incidente.  Mecanismos correctivos: Corrigen las consecuencias de una intrusión o ataque. Actúan después de que el hecho haya ocurrido.  Mecanismos disuasivos: Intentan desalentar a los agentes no deseados de que cometan un ataque. En este trabajo nos centraremos en los mecanismos preventivos para las redes de sensores que funcionen con IPv6. Hay que tener en cuenta que estas redes pueden estar ubicadas en sitios apartados como vías de tren, subestaciones eléctricas, etc. Estos sitios pueden no estar lo suficientemente vigilados. Es por eso que la seguridad física aunque se vaya fuera del alcance de este trabajo, es importante tenerla en cuenta también a la hora de desplegar una red de sensores. Pues si un atacante tiene acceso físico a los equipos finales el riesgo de intrusión y sabotaje es bastante alto. Por ello una buena solución de seguridad debe:  Permitir que los sistemas críticos para el desarrollo del negocio sigan funcionando incluso aunque se esté siendo víctima de un ataque 5 Global Market Insite (GMI), a division of Lightspeed Research, from a Cisco-sponsored study 2015. Cisco IoT System Security: Mitigate Risk, Simplify, Compliance, and Build Trust. Cisco White Paper (http://www.cisco.com/c/dam/en/us/products/collateral/se/internet-of-things/iotsystem-security-wp.pdf) 6 ibid 7 SANS Institute, Securing the Internet of Things. Cisco 2015 (http://www.cisco.com/c/dam/en/us/products/collateral/se/internet-of-things/iotsystem-security-wp.pdf) 19 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6  Proporcionar visibilidad en las aplicaciones, usuarios, protocolos y anomalías. De esta forma en caso de error o de ataque, éste pueda ser rápidamente detectado y arreglado.  Escalar de forma rentable. De manera que se pueda dar soporte a muchos dispositivos y mucha información. Si por cada dispositivo que añadamos a la red tenemos que gastar mucho dinero, esfuerzo o tiempo para mantenerlo seguro, no nos vamos a poder permitir añadir muchos dispositivos a la red. Como consecuencia dispondremos de menos información. Por eso para una solución de seguridad sería deseable que escalase bien al añadir más equipos a la red, ya que cada vez tendremos más dispositivos conectados.  Tener conocimiento de la situación. Para ello conviene tener identificados los dispositivos y usuarios de la red, disponer de registros, tener cámaras de vigilancia para detectar sabotaje de equipos, etc. Es importante para que en el caso de que un incidente ocurra se pueda acotar rápidamente el error y detectar las causas para poder arreglarlas con rapidez. Los sistemas del IoT suelen presentar muchos puntos de vulnerabilidades. Desde comunicaciones sin cifrar hasta el diseño de la aplicación que llevan a cabo, pasando por débiles sistemas de autenticación, almacenamiento de datos inseguro y la ausencia de registros de eventos. Muchas veces por ahorrar recursos, pero en otras ocasiones simplemente por desconocimiento o para acelerar el desarrollo. Solamente el 48% de las compañías tienen en cuenta la seguridad desde el principio del desarrollo de sus productos para el IoT. 8 Los dispositivos del IoT necesitan estar constantemente actualizándose para estar protegidos frente a las nuevas amenazas que van surgiendo. Aunque parezca una medida obvia para mitigar las amenazas solo un 49% de las organizaciones proporcionan actualizaciones remotas. 9 8 Securing the Internet of Things Opportunity: Putting Cybersecurity at the Heart of the IoT. Capgemini Consulting, Sogeti High Tech (https://www.capgemini.com/resource-file- access/resource/pdf/securing_the_internet_of_things_opportunity_putting_cyber_security_at_the_heart_of_the_iot.pdf) 9 ibid Estado del arte 20 19 3 6LOWPAN SOBRE 802.15.4 l protocolo 6LoWPAN permite el uso de IPv6 en redes que funcionen bajo el estándar IEEE 802.15.4. Es un acrónimo de IPv6 sobre redes de área personal de sensores de bajo consumo. Fue desarrollado por un grupo de trabajo del IETF en su división del área de Internet. El concepto de 6LoWPAN viene de la idea de que el protocolo de Internet debería poder usarse incluso en el más pequeño de los dispositivos. De esta forma podremos comunicarnos directamente a través de una red inalámbrica de sensores con otros equipos que funcionen con IP. Esto se consigue gracias a una serie de mecanismos de compresión de cabeceras que permiten a los paquetes IPv6 poder ser enviados y recibidos en redes 802.15.4. Esto resulta un reto, pues este tipo de redes tienen muy poco espacio para carga útil en sus paquetes. 3.1 Otras tecnologías Lo primero que hice fue investigar para ver cuáles eran las tecnologías más usadas en el ámbito de las redes de sensores. Pero uno de los requisitos fundamentales de este trabajo es que estuvieran basadas en IPv6. De forma que los sensores pudieran comunicarse directamente o bien a través de una pasarela con el resto de Internet. Después de llevar a cabo la búsqueda creí que la mejor opción para este trabajo era 6LoWPAN. Pero ahora veremos sus ventajas y desventajas frente al resto de tecnologías. 3.1.1 ZigBee Actualmente la tecnología de bajo coste para redes de bajo consumo que más popularidad tiene es ZigBee. Existen muchos productos comerciales que hacen uso de esta tecnología y existen cada día muchas más compañías que apuestan por él. ZigBee concretamente resulta ser un protocolo de capa de red como 6LoWPAN. Y se apoya en el estándar IEEE 802.15.4 de redes inalámbricas de área personal de bajo consumo. El mismo que usa 6LoWPAN. Por esto 6LoWPAN ha aparecido en el mercado como un competidor directo de ZigBee. 6LoWPAN aunque usa el estándar 802.15.4, puede funcionar en otras tecnologías de capas de nivel físico distintas a las que soportan el uso de ZigBee. Pero lo más importante es su integración con otros sistemas basados en IP. Y es que la interoperabilidad es un factor importante a la hora de escoger un protocolo de red inalámbrica. En el caso de ZigBee se definen las comunicaciones entre nodos 802.15.4 (capa de enlace en el mundo IP) y después se definen unas capas superiores hasta llegar a la capa de aplicación. De esta forma los dispositivos ZigBee pueden trabajar con otros dispositivos ZigBee, asumiendo que utilizan el mismo perfil en sus comunicaciones. En este aspecto 6LoWPAN ofrece interoperabilidad con otros dispositivos inalámbricos 802.15.4 al igual que ZigBee, pero también con otros dispositivos de distintas redes IP basadas en tecnologías como Ethernet o Wi-Fi. Y es que pasar de una red ZigBee a una red distinta requiere de una pasarela a nivel de aplicación para llevar a cabo el cambio de red. En el caso de 6LoWPAN esta pasarela no trabaja a nivel de aplicación, sino a nivel de red. Traduciendo las cabeceras comprimidas de 6LoWPAN a IPv6. Otro factor a comparar entre ZigBee y 6LoWPAN es el tamaño de los paquetes, sus cabeceras y el tamaño de la implementación de la pila para poder funcionar con la tecnología en cuestión. En el caso de 6LoWPAN no es E 6LoWPAN sobre 802.15.4 26 26 consumo. Además, su uso depende de TCP. Y la pila TCP también resulta pesada para este tipo de sensores, además de implicar el establecimiento y mantenimiento de conexiones. Para securizar aplicaciones que usan UDP existe el protocolo DTLS (Datagram Transport Layer Security). Este protocolo es el equivalente a TLS para UDP. Pero igualmente, su implementación resulta muy pesada para incluirla en la memoria de los dispositivos. En las pruebas del trabajo usaremos las medidas de seguridad a nivel de enlace vistas para redes 802.15.4. Por ser más simples. En cualquier caso el entorno de pruebas que desarrollemos servirá también para probar con algunas modificaciones IPsec. En el caso de SSL/TLS y DTLS sí se necesitarán más modificaciones a nivel de aplicación, pero igualmente se podría partir de lo desarrollado en este trabajo. 27 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Contiki OS 28 28 4 CONTIKI OS os sistemas operativos para dispositivos de redes de sensores inalámbricas han de ser más sencillos que los de propósito general para adaptarse y funcionar bajo las restricciones de capacidad de procesamiento, memoria, batería, etc. Contiki OS es un sistema operativo pequeño y de código abierto. Fue desarrollado por el Swedish Institute of Computer Science. Y está pensado para ser usado en dispositivos embebidos de redes de sensores inalámbricas con muy poca capacidad en memoria. Se puede portar a distintas plataformas de manera relativamente sencilla. Contiki OS está escrito en C y necesita desde unos pocos bytes a varios kilobytes de memoria RAM, dependiendo de la configuración escogida (por ejemplo se puede escoger no usar la pila TCP para ahorrar memoria). Una configuración típica de Contiki ocuparía unos 40kB de memoria ROM y 2kB de memoria RAM. Está disponible para su descarga de manera libre bajo licencia BSD 15 y funciona en una gran cantidad de plataformas. 4.1 Estructura del sistema El sistema operativo Contiki OS se compone de la siguiente estructura: Figura 4-1. Ejemplo de proceso de envío y entrega de un evento de forma síncrona 15 Contiki OS (http://www.contiki-os.org/) L 29 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Las carpetas más importantes son:  apps: Aplicaciones que trae el sistema operativo. Usaremos en este trabajo algunas como servreghack, powertracer ó collect-view.  core: Aquí se encuentra el núcleo del sistema operativo. Los módulos de radio, temporizadores, funciones de lectura/escritura, etc.  cpu: Este directorio contiene las las implementaciones para cada uno de los microcontroladores que soportan el sistema operativo.  dev: Incluye las librerías para el manejo de chips radiotransmisores externos.  doc: Se trata de la documentación generada por doxygen.  examples: En este directorio se tienen muchos ejemplos de aplicaciones para el sistema operativo. Resulta muy útil para aprender el funcionamiento del sistema y sus posibilidades. Nos hemos valido de algunos ejemplos para desarrollar el entorno de pruebas.  platform: Contiene las librerías específicas para cada plataforma. En nuestro caso para la plataforma del dispositivo TMote Sky. Y se encuentran en otro directorio dentro de platform que se llama sky.  tools: Aquí se encuentran las herramientas para cargar los programas a los dispositivos, depurar y simular. En nuestro caso usaremos el simulador Cooja y la herramienta Collect View para el entorno de pruebas. 4.2 Procesos Contiki OS es un sistema con un kernel basado en eventos. Por encima de ese kernel, las aplicaciones son cargadas dinámicamente en tiempo de ejecución. El sistema es multitarea. Cada programa debe empezar al menos un proceso y sólo un proceso puede ejecutarse al mismo tiempo en CPU. Es responsabilidad de cada proceso pausar o parar la ejecución y prevenir que el sistema quede en punto muerto. La comunicación entre procesos se hace a través de eventos. Cuando un proceso necesita avisar a otro de alguna novedad o suceso, añade un evento a la cola de eventos. El kernel va tomando eventos de la cola y se los hace llegar al proceso al que van dirigidos. También podría ir dirigido a todos los procesos en ejecución, en caso de que el evento vaya destinado a difusión. El código en Contiki puede ejecutarse en dos tipos de contextos: preferente o cooperativo. El código cooperativo se ejecuta secuencialmente con respecto al resto de código cooperativo. Por el contrario, el código con preferencia para temporalmente la ejecución del código cooperativo. Como antes se dijo, todos los programas de Contiki son procesos. Y los procesos son partes de código que el sistema operativo ejecuta cada cierto tiempo. Los procesos empiezan normalmente en el arranque del sistema. También puede ser que un módulo que contiene a un proceso lo cargue en el sistema. Los procesos siempre funcionan en el contexto cooperativo. El contexto preferente se reserva para las interrupciones en los drivers de los dispositivos y para tareas en tiempo real que tienen programadas un tiempo límite. Ya hablaremos de este tipo de tareas cuando hablemos de los temporizadores. Contiki OS 30 30 Figura 4-2. Ejemplo de ejecución de procesos en contextos preferente y cooperativo en Contiki 4.3 Protothreads En Contiki existen los protothreads. Son hilos de procesos ligeros y no necesitan llevar una pila asociada. De esta forma funcionan de manera parecida a los hilos, pero sin incurrir en el gasto que supone el uso de hilos. Su uso está pensado para dispositivos que dispongan de muy poca memoria, como los dispositivos que se usan en las WSN. Su propósito es permitir un control secuencial del flujo sin recurrir a complejas máquinas de estado o sistemas multihilos complejos. Un protothread permite estructurar el código de manera que el sistema pueda ejecutar otras actividades cuando el código está esperando que algo ocurra. De esta forma los protothreads permiten bloquear condicionalmente dentro de las funciones de la aplicación. Gracias a esto la estructura supera la limitación de la programación basada únicamente en eventos, en la que el bloqueo de las funciones hay que implementarlo dividiendo en dos partes la función de forma manual. Una parte que funciona antes de que se pause la ejecución y otra que se ejecuta tras el bloqueo. Esto hace muy difícil el uso de bucles while o sentencias condicionales if. Por eso los protothreads al no requerir una pila separada hacen el proceso de programación y funcionamiento más sencillos. Y es que almacenar múltiples pilas consume grandes cantidades de memoria. Pero en el caso de los protothreads sólo se necesitan entre 2 y 12 bytes. Además no es un código exclusivo de cada máquina. Los protothreads están escritos en C. Las macros que se usan en los procesos de Contiki para el manejo de protothreads son los siguientes: PROCESS_BEGIN(); // Declara el inicio del protothread asociado al proceso. PROCESS_END(); // Declara el final del protothread asociado al proceso. PROCESS_EXIT(); // Sale del proceso. PROCESS_WAIT_EVENT(); // Espera algún evento. PROCESS_WAIT_EVENT_UNTIL(); // Espera a un evento, pero con una condición. PROCESS_YIELD(); // Espera a algún evento. Es equivalente a PROCESS_WAIT_EVENT() PROCESS_WAIT_UNTIL(); // Espera dada alguna condición. Puede que no cese el proceso. PROCESS_PAUSE(); // Cesa temporalmente el proceso. 31 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 4.4 Eventos En Contiki un proceso se ejecuta cuando recibe un evento. Hay dos tipos de eventos: síncronos y asíncronos. Los eventos síncronos se apilan en la cola de eventos del kernel y se entregan al proceso que espera recibirlo, pasado un tiempo. En el caso de los eventos síncronos, el evento se entrega inmediatamente después de enviarse. Figura 4-3. Ejemplo de proceso de envío y entrega de un evento de forma asíncrona Figura 4-4. Ejemplo de proceso de envío y entrega de un evento de forma síncrona Vistos los procesos, protothreads y eventos, un ejemplo de proceso en Contiki sería el siguiente: #include "contiki.h" PROCESS(Proceso_ejemplo, "Proceso de ejemplo"); AUTOSTART_PROCESSES(&Proceso_ejemplo); PROCESS_THREAD(Proceso_ejemplo, ev, data) { Contiki OS 32 32 PROCESS_BEGIN(); while(1) { PROCESS_WAIT_EVENT(); printf("Se ha recibido el evento número %d\n", ev); } PROCESS_END(); } 4.5 Multithreading Existe otra forma de usar programación concurrente en Contiki. Pero al contrario que con los protothreads, es dependiente de la arquitectura del procesador que se use. El código de la librería que implementa esta tecnología (mt library) se divide en dos partes: una independiente de la arquitectura del procesador y otra que depende de su arquitectura. Ha de cambiarse de contexto entre los distintos hilos y para ello se tiene una pila privada por cada hilo y un contador de programa que se guarda al cambiar de contexto. La figura 4-5 muestra la máquina de estados de los hilos. Un hilo puede tener tres estados distintos durante su tiempo de uso:  Ready: En este estado el hilo está listo para ejecutarse. Que se hace a través de la función mt_exec() del hilo. Este estado se puede reestablecer una vez que el control se cede a otro hilo usando mt_yield().  Running: Este estado indica que el hilo se está ejecutando.  Exited: Es el estado final de un hilo. Significa que ya no se puede ejecutar más. Figura 4-5. Máquina de estados de un hilo Los hilos no pueden recibir eventos de Contiki y por lo general no se suelen usar. Pero Contiki los ofrece por si alguien los necesita en un programa o plataforma específica. 33 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 4.6 Temporizadores Contiki OS también propociona una serie de librerías para el uso de temporizadores, que pueden usar tanto las aplicaciones, como el propio sistema operativo. Estas librerías contienen funciones para comprobar si un período de tiempo ha pasado, despertando al sistema desde el modo de bajo consumo en los tiempos programados. También permite programar tareas en tiempo real. Los temporizadores también sirven para dejar que el sistema trabaje con otras tareas por un período de tiempo antes de reanudar la ejecución. 4.7 Entradas y salidas El tipo de dispositivos I/O que es usen depende altamente de la plataforma en cuestión. Contiki OS proporciona dos interfaces básicas que la mayoría de plataformas comparten: comunicación por puerto serie y LEDs. La salida por puerto serie está soportada con la librería estándar C para imprimir (printf o putchar). Aquí un ejemplo para sacar algo por la salida del puerto serie: int printf(const char *formato, ...); // Imprime una cadena conforme a un formato. int putchar(int c); // Imprime un único carácter. La entrada por puerto serie en cambio es a través de un mecanismo específico de Contiki. Será necesario primero llamar a la función serial_line_init() y así el proceso serial_line_process y el buffer puedan ser inicializados antes de empezar a recibir. Cuando hay un carácter para ser leído del puerto serie se genera una interrupción. Y se van almacenando los datos en el buffer hasta que llega el carácter de nueva línea. Cuando esto ocurre se manda un evento a difusión a todos los procesos. Figura 4-6. Máquina de estados de un hilo Los LEDs no los usaremos en nuestro caso, ya que podemos ver la salida del puerto serie por pantalla en el simulador. Pero en entornos reales se usan bastante para depurar el funcionamiento de los programas en los sensores. Para su uso es necesario inicializar la librería llamando a leds_init(). Luego podemos usar las funciones que Contiki OS 34 34 incluye la librería para modificar el estado del LED: void leds_init(void); // Inicializa el driver de los LEDs. unsigned char leds_get(void); // Obtiene el estado de un LED. void leds_on(unsigned char ledv); // Enciende un conjunto de LEDs. void leds_off(unsigned char ledv); // Apaga un conjunto de LEDs. void leds_toggle(unsigned char ledv); // Invierte un conjunto de LEDs. void leds_invert(unsigned char ledv); // Invierte un conjunto de LEDs. Cada LED tiene un identificador, aquí los distintos identificadores para los LEDs verde, amarillo, rojo y todos: #define LEDS_GREEN 1 #define LEDS_YELLOW 2 #define LEDS_RED 4 #define LEDS_ALL 7 4.8 Radio Duty Cycling El consumo energético es muy importante para los sensores inalámbricos, para lograr perdurar bastante tiempo antes de tener que cambiarles las pilas o baterías. Para conseguirlo no basta con contar con un transmisor de bajo consumo. El hardware no es suficiente para reducir el consumo de permanecer constantemente a la escucha de nuevo tráfico de red. En el caso del sensor que se va a usar en las pruebas, el gasto de estar siempre a la escucha es de 60 mW, y un poco mayor al transmitir. Esto hace que las pilas del sensor se agoten en cuestión de días. Para evitarlo el transmisor debe apagarse todo lo posible. El problema es que cuando está apagado no le es posible enviar o recibir nuevos mensajes. Así que el transmisor deberá buscar una forma de recivir los mensajes pero mantener la radio apagada entre recepción y transmisión de mensajes. El propósito de un protocolo de ahorro energético en el ciclo de trabajo es mantener la radio apagada entre los puntos donde las radios transmiten o reciben. De forma que si los nodos están sincronizados, el ciclo de trabajo puede programar los momentos en los que se debe transmitir y estar a la escucha. Si no existe sincronización, los nodos deben buscar otra manera de proporcionar momentos para comunicarse. En el ámbito de las redes de sensores, los protocolos de ciclo de trabajo se llaman también protocolos de control de acceso al medio (MAC). En Contiki OS se ha separado el ciclo de trabajo del control de acceso al medio. Y por ello se tiene la capa RDC antes de la capa MAC. Se tienen 3 métodos para gestionar el ciclo de trabajo de la radio de comunicaciones 802.15.4: ContikiMAC, X-MAC y LPP. El más usado es ContikiMAC. Para que ContikiMAC funcione se deben satisfacer las siguientes restricciones. La primera, que el intervalo entre paquetes de transmisión (𝑡𝑖) debe ser menor que el intervalo en el que se comprueba el uso del canal (𝑡𝑐). De esta forma nos aseguramos que si no es en la primera comprobación de canal, sea en la segunda cuando el nodo receptor reciba el comienzo de la transmisión. Si el intervalo de comprobación (𝑡𝑐) es menor que 𝑡𝑖, dos comprobaciones de canal no podrían asegurar que se haya transmitido un paquete. A la inversa, el tiempo de retardo (𝑡𝑟) dos veces y el tiempo de comprobación del canal deben ser menor que el tiempo de transmisión del paquete más corto posible (𝑡𝑠). 𝑡𝑟+ 𝑡𝑐+ 𝑡𝑟< 𝑡𝑠 (4–1) 35 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Figura 4-7. Ejemplo de transmisión de paquetes Cuando se detecta una transmisión entrante, ContikiMAC mantiene la radio encendida para recibir el paquete entero. Cuando se recibe el paquete entero, se transmite un asentimiento a nivel de la capa de enlace. El tiempo que tarda el asentimiento en transmitirse (𝑡𝑎) y el tiempo de retraso hasta que se detecta el asentimiento (𝑡𝑑) establecen la cota inferior para el intervalo de comprobación (𝑡𝑐). De forma que las restricciones de tiempo de ContikiMAC se pueden resumir así: 𝑡𝑎+ 𝑡𝑑< 𝑡𝑖 (4–2) 𝑡𝑖< 𝑡𝑐 (4–3) 𝑡𝑐+ 2𝑡𝑟< 𝑡𝑠 (4–4) El problema de implementar los protocolos de ciclo de trabajo y control de acceso al medio de Contiki es que aumentan el tamaño del programa. En mi caso al utilizarlos, el programa no entraba en la ROM del dispositivo. Por ello tuve que desactivar ContikiMAC y cualquier protocolo MAC ó RDC. De esta forma en nuestras pruebas siempre estará encendida la radio. De todas formas, esto no afectará a nuestras pruebas como ya se explicará posteriormente. 4.9 Pila de red Una de las características más importantes de Contiki OS es el soporte de los protocolos IP. Y eso lo hace ser uno de los primeros sistemas operativos para sistemas embebidos que proporcionan soporte para IPv6. Las pilas de comunicaciones IP que trae Contiki funcionan tanto con IPv4 como con IPv6. Desarrollo del entorno de pruebas 42 42 369 /* We set the timer to SEND_INTERVAL */ 370 etimer_set(&periodic_timer, SEND_INTERVAL); Este tiempo SEND_INTERVAL será en nuestro caso 10 segundos. Y además será el mismo tiempo que después emplearemos para decidir cuándo volvemos a enviar otro mensaje. Para definir los 10 segundos definí la variable SEND_INTERVAL de la siguiente forma: 71 /* 72 * Time interval to send another message 73 */ 74 #define SEND_INTERVAL (10 * CLOCK_SECOND) En el proceso collection_view_client_process la parte de configuración es breve, pues sólo estableceremos el socket UDP con el servidor “Collection View” del receptor: 296 /* new connection with remote host */ 297 client_conn = udp_new(NULL, UIP_HTONS(UDP_SERVER_PORT), NULL); 298 udp_bind(client_conn, UIP_HTONS(UDP_CLIENT_PORT)); Los puertos UDP usados para la comunicación serán el 5688 en el caso del servidor y el puerto 8775 en el caso del cliente. A partir de entonces la comunicación la gestionará la app de powertrace y collect-view. Hasta aquí la fase de configuración del programa del emisor udp-sender.c. 5.3.2 Envío de la información Una vez ya hemos configurado el dispositivo emisor, pasaremos a describir cómo funciona el envío de la información al receptor. En el proceso unicast_sender_process de envío de paquetes UDP unicast al receptor habrá un bucle que se encargue de ir enviando los paquetes cada cierto intervalo de tiempo: 372 while(1) { 373 374 /* 375 * Wait for the interval to start sending the message, but before 376 * reset it again so that in the next interval we cand send another 377 * message 378 */ 379 PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer)); 380 etimer_reset(&periodic_timer); 381 382 /* It looks for the server address */ 383 addr = servreg_hack_lookup(SERVICE_ID); 384 if(addr != NULL) { 385 static unsigned int message_number; 386 char buf[24]; 387 43 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 388 #if DEBUG_SENDER == 1 389 printf("Sending unicast to "); 390 uip_debug_ipaddr_print(addr); 391 printf("\n"); 392 #endif 393 394 /* The message to send with the sequence number */ 395 sprintf(buf, "TFG Jose Antonio %d", message_number); 396 397 /* If we reach the max sequence number we reset it */ 398 if (message_number == MAX_MESSAGE_NUMBER) { 399 message_number = 0; 400 } 401 else { 402 message_number++; 403 } 404 405 /* It sends it to the sink server */ 406 simple_udp_sendto(&unicast_connection, buf, strlen(buf) + 1, addr); 407 408 } else { 409 #if DEBUG_SENDER == 1 410 printf("Service %d not found\n", SERVICE_ID); 411 #endif 412 } 413 } 414 415 PROCESS_END(); 416 } Lo primero es esperar a que acabe el temporizador. Este temporizador ya lo establecimos a 10 segundos en la fase de configuración. Una vez acabado lo reseteamos para que cuando vuelvan a pasar 10 segundos volvamos a enviar: 374 /* 375 * Wait for the interval to start sending the message, but before 376 * reset it again so that in the next interval we cand send another 377 * message 378 */ 379 PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer)); 380 etimer_reset(&periodic_timer); Lo siguiente será averiguar la dirección del receptor a través de nuestro registro de servicios de la app servreghack. Buscamos por el SERVICE_ID que hemos asignado al servicio del sumidero de paquetes. En nuestro caso SERVICE_ID es 190. Y así obtenemos la dirección: 382 /* It looks for the server address */ 383 addr = servreg_hack_lookup(SERVICE_ID); Desarrollo del entorno de pruebas 44 44 Después se escribe en el buffer de salida la cadena que queremos enviar. En nuestro caso será “TFG Jose Antonio” más un número de secuencia : 394 /* The message to send with the sequence number */ 395 sprintf(buf, "TFG Jose Antonio %d", message_number); Para saber el número máximo de número de secuencia compilé un programa en un sensor TMote Sky que incluía una línea con: 405 printf("Size of unsigned int %d\n", sizeof(unsigned int)); La salida del sensor fue la de la figura 5-2. Figura 5-2. Tamaño de un unsigned int en el TMote Sky Por tanto al ser 2 bytes, el límite será 65535. Lo comprobamos con la siguiente línea: 404 unsigned int prueba = 0; 405 printf("unsigned int limit %u\n", prueba-1); Que dan por resultado la salida del sensor que vemos en la figura 5-3. Figura 5-3. Límite de tamaño de un unsigned int en el TMote Sky Es importante tener controlada esta situación para evitar casos de overflow. De esta forma el tamaño máximo de la cadena de texto que vamos a enviar tendrá 24 caractéres. 23 caracteres para el texto en el caso del máximo número de secuencia y 1 carácter para el final de la cadena \0. De esta forma cada vez que escribimos el mensaje comprobamos justo después que no se haya llegado al número máximo de mensajes. Si hemos llegado reseteamos el número de secuencia, si no pues aumentamos el número de secuencia. 397 /* If we reach the max sequence number we reset it */ 45 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 398 if (message_number == MAX_MESSAGE_NUMBER) { 399 message_number = 0; 400 } 401 else { 402 message_number++; 403 } Una vez hecho esto, se envía por UDP al dispositivo receptor a través de la función simple_udp_sendto() con el socket UDP que registramos en la fase de configuración. 405 /* It sends it to the sink server */ 406 simple_udp_sendto(&unicast_connection, buf, strlen(buf) + 1, addr); Y una vez enviado volveríamos al comienzo del bucle donde esperaríamos a que expirara el temporizador y volveríamos a realizar todo este proceso hasta enviar el siguiente paquete. Esto es todo lo que se hace en el proceso unicast_sender_process. En cambio en el proceso collection_view_client_process sólo esperaremos recibir paquetes entrantes, aunque en nuestro caso los ignoraremos. 307 while(1) { 308 PROCESS_YIELD(); 309 if(ev == tcpip_event) { 310 tcpip_handler(); 311 } 312 } La función tcpip_handler() no hace nada: 143 static void tcpip_handler(void) 144 { 145 if(uip_newdata()) { 146 /* The sender ignores incoming data */ 147 } 148 } Son las apps de Contiki powertrace y collect-view las que se encargan de recoger la información del consumo y enviarla al receptor. Nosotros hemos definido la función collect_common_send() que se requiere para el funcionamiento de la app collect-view. En esta función se recopila la información para enviar al sensor. 152 /* 153 * collect_common_send: Send the statistics to the Collect View server 154 */ 155 void collect_common_send(void) Desarrollo del entorno de pruebas 46 46 156 { 157 static uint8_t seqno; 158 struct { 159 uint8_t seqno; 160 uint8_t for_alignment; 161 struct collect_view_data_msg msg; 162 } msg; 163 164 uint16_t parent_etx; 165 uint16_t rtmetric; 166 uint16_t num_neighbors; 167 uint16_t beacon_interval; 168 rpl_parent_t *preferred_parent; 169 linkaddr_t parent; 170 rpl_dag_t *dag; 171 172 if(client_conn == NULL) { 173 /* Not setup yet */ 174 return; 175 } 176 memset(&msg, 0, sizeof(msg)); 177 seqno++; 178 if(seqno == 0) { 179 /* Wrap to 128 to identify restarts */ 180 seqno = 128; 181 } 182 msg.seqno = seqno; 183 184 linkaddr_copy(&parent, &linkaddr_null); 185 parent_etx = 0; 186 187 /* Let's suppose we have only one instance */ 188 dag = rpl_get_any_dag(); 189 if(dag != NULL) { 190 preferred_parent = dag->preferred_parent; 191 if(preferred_parent != NULL) { 192 uip_ds6_nbr_t *nbr; 193 nbr = uip_ds6_nbr_lookup(rpl_get_parent_ipaddr(preferred_parent)); 194 if(nbr != NULL) { 195 /* Use parts of the IPv6 address as the parent address, in reversed byte order. */ 196 parent.u8[LINKADDR_SIZE - 1] = nbr- >ipaddr.u8[sizeof(uip_ipaddr_t) - 2]; 197 parent.u8[LINKADDR_SIZE - 2] = nbr- >ipaddr.u8[sizeof(uip_ipaddr_t) - 1]; 198 parent_etx = rpl_get_parent_rank((uip_lladdr_t *) uip_ds6_nbr_get_ll(nbr)) / 2; 199 } 200 } 201 rtmetric = dag->rank; 202 beacon_interval = (uint16_t) ((2L << dag->instance- >dio_intcurrent) / 1000); 203 num_neighbors = uip_ds6_nbr_num(); 204 } else { 205 rtmetric = 0; 47 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 206 beacon_interval = 0; 207 num_neighbors = 0; 208 } 209 210 collect_view_construct_message(&msg.msg, &parent, 211 parent_etx, rtmetric, 212 num_neighbors, beacon_interval); 213 214 uip_udp_packet_sendto(client_conn, &msg, sizeof(msg), 215 &server_ipaddr, UIP_HTONS(UDP_SERVER_PORT)); 216 } Esta función la obtuve de uno de los ejemplos de funcionamiento de Contiki (rpl-collect). Hay que destacar la función collect_view_construct_message(). Con ella construimos el mensaje, y lo enviamos con uip_udp_packet_sendto() pasando el socket UDP (client_conn), la dirección del servidor (server_ipaddr) y el puerto en el que escucha como parámetro (UDP_SERVER_PORT) además del mensaje. 214 uip_udp_packet_sendto(client_conn, &msg, sizeof(msg), 215 &server_ipaddr, HTONS(UDP_SERVER_PORT)); En nuestro caso el puerto UDP del servidor será el 5688. Y esto es todo en la parte del programa del sensor emisor. 5.4 udp-sink.c Este fichero contendrá el programa que vamos a usar en el dispositivo receptor. 5.4.1 Configuración del dispositivo Lo primero será declarar los procesos y hacer que comiencen, además del proceso collect_common_process(), que es parte de la app Collect-View, y vale tanto para el sensor recolector como para el sensor emisor: 93 /* 94 * 95 * collection_view_server_process: will receive the statistics of the 96 * sender sensor 97 * 98 * unicast_receiver_process: will receive the unicast packets to the sink 99 * Desarrollo del entorno de pruebas 48 48 100 */ 101 PROCESS(unicast_receiver_process, "Unicast receiver example process"); 102 PROCESS(collection_view_server_process, "UDP server process"); 103 AUTOSTART_PROCESSES(&unicast_receiver_process, &collection_view_server_process, &collect_common_process); En el proceso receptor de mensajes, se ha de configurar el dispositivo para que esté en la misma red que el emisor. Después será necesario por un lado iniciar el servicio servreg-hack para anunciar que tenemos un servicio de recepción de mensajes UDP unicast. 293 servreg_hack_init(); 294 295 ipaddr = set_global_address(); 296 297 servreg_hack_register(SERVICE_ID, ipaddr); El identificador del servicio SERVICE_ID será el que vimos en la parte del emisor, 190. Y en la función set_global_address() asignamos la dirección IPv6 del dispositivo de la misma forma que ya hicimos en el caso del emisor, a partir de su dirección MAC. Aunque esta vez no asignaremos la dirección del servidor, pues somos nosotros: 196 /* 197 * set_global_address: sets the IPv6 addresses of the device 198 */ 199 static uip_ipaddr_t * set_global_address(void) 200 { 201 static uip_ipaddr_t ipaddr; 202 203 // Build the IPv6 Address 204 uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); 205 // Set the last 64 bits based on the MAC Address 206 uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); 207 // We add the unicast address to the list 208 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); 209 210 return &ipaddr; 211 } De esta forma se empezará a anunciar el servicio por multicast gracias a la app servreg-hack. En la figura 5-5 podemos ver el contenido de uno de los paquetes de anuncio. En él se puede ver el SERVICE_ID 190 que en hexadecimal es 0xBE. 49 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Figura 5-4. Información del paquete de anuncio de servicio multicast de la app servreg-hack Figura 5-5. Contenido de un paquete multicast de la app servreg-hack que anuncia el servicio con SERVICE_ID 190 Después registramos el socket de escucha para escuchar las peticiones que se hagan en el puerto UDP_PORT (1234). Le pasamos como parámetro la dirección de la estructura que tiene los datos de la comunicación UDP unicast. La dirección remota la registraremos como NULL para que se acepten paquetes de cualquier dirección. De esta forma si en vez de uno, tuviéramos varios dispositivos, el servidor receptor seguiría recibiendo los paquetes y registrándolos. Para registrar los paquetes que llegan, se pasa como parámetro la función callback que se llamará cada vez que llegue un paquete en el puerto 1234 paquete. 299 simple_udp_register(&unicast_connection, UDP_PORT, 300 NULL, UDP_PORT, receiver); Por otro lado, en el proceso de recolección de los datos del consumo energético por parte de la aplicación Collect-View tenemos que configurar la dirección y puerto en los que escucharemos. Además de configurar el dispositivo como root para el protocolo RPL. 231 PROCESS_THREAD(collection_view_server_process, ev, data) 232 { 233 uip_ipaddr_t ipaddr; 234 struct uip_ds6_addr *root_if; 235 236 PROCESS_BEGIN(); 237 238 PROCESS_PAUSE(); 239 240 #if DEBUG_SINK == 1 241 PRINTF("UDP server started\n"); 242 #endif 243 244 #if UIP_CONF_ROUTER Desarrollo del entorno de pruebas 50 50 245 uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); 246 /* uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); */ 247 uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL); 248 root_if = uip_ds6_addr_lookup(&ipaddr); 249 if(root_if != NULL) { 250 rpl_dag_t *dag; 251 dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); 252 uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); 253 rpl_set_prefix(dag, &ipaddr, 64); 254 PRINTF("created a new RPL dag\n"); 255 } else { 256 PRINTF("failed to create a new RPL DAG\n"); 257 } 258 #endif /* UIP_CONF_ROUTER */ 259 260 print_local_addresses(); 261 262 server_conn = udp_new(NULL, UIP_HTONS(UDP_COLLECT_CLIENT_PORT), NULL); 263 udp_bind(server_conn, UIP_HTONS(UDP_COLLECT_SERVER_PORT)); 264 265 #if DEBUG_SINK == 1 266 PRINTF("Created a server connection with remote address "); 267 PRINT6ADDR(&server_conn->ripaddr); 268 PRINTF(" local/remote port %u/%u\n", UIP_HTONS(server_conn- >lport), 269 UIP_HTONS(server_conn->rport)); 270 #endif El puerto UDP en el que el servidor Collect-View escuchará será el 5688. Y el puerto UDP remoto del que espera recibir los datos 8775. 76 #define UDP_COLLECT_CLIENT_PORT 8775 77 #define UDP_COLLECT_SERVER_PORT 5688 262 server_conn = udp_new(NULL, UIP_HTONS(UDP_COLLECT_CLIENT_PORT), NULL); 263 udp_bind(server_conn, UIP_HTONS(UDP_COLLECT_SERVER_PORT)); También habrá que conectar la app Collect-View a la salida del puerto serie para poder visualizar las estadísticas en la herramienta del mismo nombre Collect-View. Esta herramienta se ejecuta tanto en escenarios reales como en los nuestros de prueba en un PC. 128 /* 129 * collect_common_net_init: sets the serial line input for Collection View 130 */ 51 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 131 void collect_common_net_init(void) 132 { 133 #if CONTIKI_TARGET_Z1 134 uart0_set_input(serial_line_input_byte); 135 #else 136 uart1_set_input(serial_line_input_byte); 137 #endif 138 serial_line_init(); 139 } 5.4.2 Recepción de información En el proceso principal tenemos al proceso esperando eventos, pues ya establecimos antes la función callback que se ejecutará cuando se reciba un paquete entrante en el puerto 1234. 302 while(1) { 303 PROCESS_WAIT_EVENT(); 304 } 305 PROCESS_END(); 306 } La función callback receiver() registra los paquetes según van llegando. Va imprimiendo por la salida estándar, que en nuestro caso será el puerto serie, la dirección y el puerto desde los que se reciben los datos, además de la longitud de los datos del mensaje y el mensaje en sí. El formato es: "Data received from IP_ADDR on port 1234 from port 1234 with length MSG_LENGTH: 'TFG Jose Antonio SEQ_NUM" ". A continuación vemos el código que corresponde a esta función. 215 static void receiver(struct simple_udp_connection *c, 216 const uip_ipaddr_t *sender_addr, 217 uint16_t sender_port, 218 const uip_ipaddr_t *receiver_addr, 219 uint16_t receiver_port, 220 const uint8_t *data, 221 uint16_t datalen) 222 { 223 printf("Data received from "); 224 uip_debug_ipaddr_print(sender_addr); 225 printf(" on port %d from port %d with length %d: '%s'\n", 226 receiver_port, sender_port, datalen, data); 227 } En el caso del proceso de recepción de la información del consumo energético del sensor emisor tenemos la función callback tcpip_handler(), que se encargará de tratar los paquetes que lleguen al servidor Collect- View. El proceso estará constantemente a la espera de nuevos eventos y llamará a la función en caso de que llegue un paquete. La llamamos de la siguiente forma: 272 while(1) { Pruebas y resultados 58 58 6.2 Montaje del escenario Para probar el rendimiento de los distintos mecanismos de cifrado y autenticación montamos el siguiente escenario con dos sensores: Figura 6-1. Diagrama del escenario de pruebas En el caso del dispositivo receptor tendremos un sensor ejecutando el programa udp-sink.c que creamos en el anterior capítulo. Este programa consta principalmente de dos procesos que se ejecutan en paralelo. Uno de ellos será un servicio que escucha en un puerto UDP y espera recibir paquetes UDP unicast del receptor. El otro será un servicio que recibirá estadísticas del otro dispositivo como por ejemplo el consumo energético. De esta forma podremos evaluar el gasto que conllevan las distintas medidas adoptadas. El dispositivo emisor ejecutará el programa udp-sender.c que también creamos en el anterior capítulo. Este programa también ejecutará dos procesos simultáneos. Uno se encargará de enviar paquetes UDP con la cadena “TFG Jose Antonio número_de_secuencia” donde número de secuencia se irá incrementando con cada paquete. Por otra parte tendremos un proceso que se encargará de enviar al receptor, que en este caso hace de colector, la información acerca del consumo energético que ha registrado. Figura 6-2. Diagrama paso de mensajes del escenario de pruebas 59 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 6.2.1 Parámetros de la simulación Cada fichero de simulación se llamará “TFG-Nombre_del_mecanismo_utilizado" donde Nombre_del_mecanismo_utilizado será el nombre del mecanismo que vayamos a utilizar en el escenario. Tabla 6–1. Mecanismos de autenticación y cifrado a usar en el escenario de pruebas Nombre Descripción 0 - No-Security Sin cifrado de datos ni autenticación 1 - AES-CBC-MAC-32 Sin cifrado de datos. Autenticación con MAC de 32 bits 2 - AES-CBC-MAC-64 Sin cifrado de datos. Autenticación con MAC de 64 bits 3 - AES-CBC-MAC-128 Sin cifrado de datos. Autenticación con MAC de 128 bits 4 - AES-CTR Cifrado de datos. Sin autenticación 5 - AES-CCM-32 Cifrado de datos. Autenticación con MAC de 32 bits 6 - AES-CCM-64 Cifrado de datos. Autenticación con MAC de 64 bits 7 - AES-CCM-128 Cifrado de datos. Autenticación con MAC de 128 bits Una vez dentro del simulador seleccionaremos los siguientes parámetros:  Radio medium: nos permite seleccionar el medio a través del que los dispositivos transmitirán. Seleccioné Unit Disk Graph Medium (UDGM): Distance Loss. De modo que tendrá perdidas según la distancia a la que se encuentren los dispositivos transceptores 802.15.4.  Mote startup delay (ms): El tiempo que tardarán en arrancar los dispositivos sensores después del comienzo de la simulación. En mi caso escogí un segundo.  Random seed: Es el número inicializador de números aleatorios. Para todas nuestras simulaciones usaremos el mismo (123456), de manera que sean reproducibles. Figura 6-3. Parámetros para la simulación en Cooja Luego una vez dentro del simulador añadimos los sensores. En mi caso el Sky Mote. Y elegí el fichero udpsink.c para el sensor receptor. Acto seguido pasé a compilarlo. Luego seleccioné “Create” para añadirlo a la simulación. Pruebas y resultados 60 60 Figura 6-4. Creación de un sensor en Cooja Lo siguiente fue seleccionar el número de sensores a desplegar (uno en mi caso) y fijar su posición. En el escenario ambos sensores estarán separados 10m y por ello las posiciones serán las siguientes:  Emisor: X: 45 ; Y: 50 ; Z: 0  Receptor: X: 55 ; Y: 50 ; Z: 0 Figura 6-5. Posición del sensor en Cooja Después seguí los mismos pasos para crear el dispositivo emisor. Sólo que ahora cambié el fichero a compilar por udp-sender.c y la posición correspondiente al emisor. Y finalmente Nos quedará el escenario de la figura 6- 6. 61 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Figura 6-6. Vista del escenario a simular en Cooja Antes de comenzar la simulación usé la herramienta “Radio messages” de Cooja. Esta herramienta permite exportar los mensajes de las simulaciones a un fichero PCAP para luego poder analizar las comunicaciones. Por otra parte también usé un script que permitía fijar el tiempo límite a la simulación. En mi caso serían 600.000 ms, que corresponden a 10 minutos. De esta forma todas las medidas se evaluarían en el mismo tiempo. /* * Example Contiki test script (JavaScript). * A Contiki test script acts on mote output, such as via printf()'s. * The script may operate on the following variables: * Mote mote, int id, String msg */ TIMEOUT(600000); while (true) { log.log(time + ":" + id + ":" + msg + "\n"); YIELD(); } Además de fijar el tiempo límite de la simulación, el script también permite mostrar todos los mensajes generados por el programa a través de funciones como printf (). Lo siguiente fue activar el uso del script. Para ello hice uso de la herramienta “Simulation script editor” que se incluye en Cooja. Y en la pestaña “Run” seleccioné “Activate”. Pruebas y resultados 62 62 Figura 6-7. Editor de scripts para las simulaciones en Cooja Lo siguiente fue abrir la herramienta “Collect View” en el dispositivo receptor (1). Esta herramienta permite visualizar el consumo energético en el sensor emisor. De esta forma pude medir el consumo tanto en CPU como en la transmisión que conlleva cada mecanismo de autenticación y seguridad. La configuraremos con los siguientes parámetros:  Report interval: Este valor determina el intervalo de tiempo en el que el emisor emitirá sus informes. En mi caso será 10 segundos.  Report randomness: Sirve para introducir un factor aleatorio a la hora de decidir cuándo se envía el informe. En mi caso 0 segundos. Queremos que se envíe exactamente cada 10 segundos en todos los casos.  Hop-by-hop retransmissions: Permite decidir el número máximo de saltos que puede dar el informe en la red de sensores. Como en nuestro caso no habrá saltos en la red, ya que tenemos dos sensores solamente, lo dejamos a su valor por defecto. Será por tanto 31.  Number of reports: Establece el número de informes. Lo dejaremos a 0, de esta forma no habrá un límite de informes. Éstos se seguirán enviando hasta el final de la simulación. Después envié el comando a los nodos con el botón “Send command to nodes” y comencé a recolectar los datos pulsando el botón “Start Collect”. 63 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Figura 6-8. Parámetros de Collect View en Cooja 6.3 Simulación Una vez hecho lo anterior, ya tenía la simulación lista. Pulsé en el botón “Start” de la ventana “Simulation control” y ya se ejecutaría la simulación hasta llegar a los 10 minutos. Durante la simulación se pueden ver las salidas de ambos sensores en la ventana “Simulation script editor”. Para ir cambiando de mecanismo de autenticación y/o cifrado iba cambiando el parámetro ADAPTIVESEC_CONF_UNICAST_SEC_LVL y el ADAPTIVESEC_CONF_BROADCAST_SEC_LVL seleccionando los datos según la tabla 6-1. Ya no se muestran en la ventana “Mote output”, esto es debido al uso del script para fijar el tiempo límite. Para evaluar los distintos mecanismos de autenticación y seguridad seguí varios criterios: consumo energético, tamaño del programa y retardo añadido a las comunicaciones. 6.3.1 Consumo energético El resultado en el caso del algoritmo AES-CBC-MAC-32 fue el de la figura 6-10. Podemos acercar la imagen seleccionando la zona de la gráfica que queramos ver con más detalle o también pulsando el botón derecho del ratón y seleccionando “Zoom in”. Si dejamos el ratón encima de alguna de las distintas zonas podemos ver los valores exactos que corresponden al consumo de CPU, transmisión y recepción o del modo de bajo consumo (LPM). Veremos que el consumo del módulo de comunicaciones en escucha (“Radio listen”) es muy elevado en comparación al resto. Esto se debe a que, como ya vimos en el capítulo del sistema operativo Contiki, el ciclo de trabajo (“RDC: Radio duty cycle”) del receptor radio está fijado a 100%. De modo que siempre está a la escucha. Esto se hizo así para ahorrar memoria de programa (ROM), ya que al incluir otros drivers de Contiki para gestionar el RDC nuestro programa no entraba en la memoria del dispositivo. De esta forma Pruebas y resultados 64 64 conseguí el espacio necesario. Al fin y al cabo ese gasto es irrelevante para el estudio que se pretende realizar. Nos interesa por tanto comparar el consumo de CPU y transmisión radio. Figura 6-9. Consumo energético medio en en Cooja 6.3.2 Tamaño del programa Además podemos mirar el tamaño del programa que hemos cargado en el sensor. De esta forma podemos evaluar el uso que hace en memoria cada mecanismo. Al compilar mi programa con Cooja y crear los sensores se generó el programa que habría que cargar en el sensor real. Usaremos este fichero para averiguar el tamaño usado. La salida de la utilidad size da la siguiente información acerca del programa que vamos a cargar en el sensor TMote Sky:  Text: Es el tamaño del código que irá en la flash ROM.  Data: Se trata del tamaño usado para datos inicializados. Estas variables que se guardan en RAM y se inicializan con valores almacenados en la ROM.  BSS (Block Started by Symbol): Contiene todos los datos no inicializados o inicializados a cero que irán en la RAM.  Dec: Corresponde al número total de bytes de “Text”, “Data” y “BSS”.  Hex: Es exactamente lo mismo que “Dec” pero en valor hexadecimal. De modo que el tamaño en ROM del programa es: 𝑇𝑒𝑥𝑡 + 𝐷𝑎𝑡𝑎 = 𝑅𝑂𝑀 𝑢𝑠𝑎𝑑𝑎 65 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Figura 6-10. Tamaño de los programas para el sensor TMote Sky Para hacer la comparativa me fijé en las variaciones de estos tamaños según el mecanismo de seguridad y autenticación escogido. 6.3.3 Retardo en las comunicaciones Al acabar la simulación, gracias a la herramienta “Radio messages”, se guardan todas las comunicaciones hechas de modo que podemos analizarlas. Pero si queremos medir el retardo que existe al cifrar y añadir el código de autenticación del mensaje por parte del emisor, y descifrar y autenticar los mensajes por parte del receptor, no podemos hacerlo a través del fichero PCAP. Esto es debido a que cuando la herramienta “Radio messages” capta los mensajes, éstos ya van cifrados y/o autenticados. Por tanto se desconoce el tiempo que le ha llevado al dispositivo cifrar los datos y añadir el código de autenticación. Pero es que tampoco han sido descifrados ni autenticados por el dispositivo receptor. Por tanto tuve que buscar otra forma de medir este retardo. La manera finalmente empleada fue la que ya se vio en el anterior capítulo: Antes de enviar el mensaje usamos la función printf () para anunciar que se va a enviar. Así se mostrará en la ventana “Simulation script editor”. Y al haberlo recibido también se muestra por la salida del dispositivo receptor. De esta forma se tiene un intervalo de tiempo desde antes de proceder al envío hasta justo después de recibirlo. Será este el tiempo a comparar entre los distintos mecanismos de seguridad y autenticación. En la figura 6-11 se puede apreciar el tiempo en milisegundos a la izquierda, el identificador del dispositivo (1- receptor ; 2-emisor). Y los datos de la transmisión y recepción. Para hacer la comparativa restaremos el número de milisegundos del envío por parte del emisor al que corresponde a la recepción por parte del receptor. Figura 6-11. Salida estándar de ambos dispositivos Pruebas y resultados 66 66 6.4 Resultados A continuación se pasará a mostrar y comentar los resultados obtenidos durante las pruebas en los distintos escenarios. Como ya se ha dicho, las medidas que se han tomado pretenden medir tres aspectos de las distintas medidas: consumo energético, aumento de la memoria usada y retardo añadido en las comunicaciones entre sensores. 6.4.1 Consumo energético A través de la herramienta Collect-View que trae Contiki, se recogieron los resultados al usar los distintos tipos de medidas de seguridad. El método seguido para realizar las mediciones es el que se explicó en el apartado anterior. Los resultados corresponden al sensor emisor. Tabla 6–2. Potencia media consumida por los distintos mecanismos de autenticación y/o cifrado en el dispositivo emisor Mecanismo de autenticación y/o seguridad Radio transmit (mW) CPU (mW) LPM (mW) Radio Listen (mW) Total (mW) Sin seguridad 0,02 0,408 0,151 59,973 60,552 AES-CBC- MAC-32 0,021 0,493 0,149 59,975 60,638 AES-CBC- MAC-64 0,022 0,493 0,149 59,973 60,637 AES-CBC- MAC-128 0,024 0,487 0,149 59,972 60,632 AES-CTR 0,02 0,492 0,149 59,976 60,637 AES-CCM-32 0,021 0,495 0,149 59,975 60,64 AES-CCM-64 0,022 0,495 0,149 59,974 60,64 AES-CCM-128 0,024 0,489 0,149 59,972 60,634 67 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Figura 6-12. Gráfico de la potencia media usada en la CPU del sensor emisor Figura 6-13. Gráfico de la potencia media usada en la transmisión por radio del sensor emisor Al no implementar ningún protocolo de Radio Duty Cycling, ni de control de acceso al medio (MAC), la radio permanece siempre encendida. Conviene usarlo para conseguir una mayor vida de la pila o batería en 0,018 0,019 0,02 0,021 0,022 0,023 0,024 0,025 Sinseguridad AES-CBC-MAC-32 AES-CBC-MAC-64 AES-CBC-MAC-128 AES-CTR AES-CCM-32 AES-CCM-64 AES-CCM-128 Consumo(mW) 0 0,05 0,1 0,15 0,2 0,25 0,3 0,35 0,4 0,45 0,5 Sinseguridad AES-CBC-MAC-32 AES-CBC-MAC-64 AES-CBC-MAC-128 AES-CTR AES-CCM-32 AES-CCM-64 AES-CCM-128 Consumo(mW) Pruebas y resultados 74 74 Figura 6-17. Gráfica de la diferencia de retardo medio entre las distintas medidas El retardo medio añadido a las comunicaciones a causa de las medidas de autenticación y/o cifrado es un 32,10%. Las medidas que implican cifrado de los datos del mensaje suponen un mayor retardo. 6.5 Conclusiones Después de haber llevado a cabo las pruebas de los distintos mecanismos de autenticación y/o cifrado en el entorno de pruebas, vamos a extraer una serie de conclusiones. En cuanto al consumo energético, parece bastante asumible el uso de alguna medida de autenticación y/o seguridad. En las pruebas realizadas, el uso de la medida de seguridad más robusta AES-CCM-128, sólo restaba unos 7 minutos y 30 segundos a la duración de la batería, de un total de más de 3 días y 20 horas. Con respecto al tamaño de programa, habría que evaluar la situación para cada aplicación. Pues la memoria de programa es muy limitada. En el caso del TMote-Sky sólo 48k de memoria Flash. Así que habrá que ver si hay hueco para aproximadamente 4k de memoria de programa y unos 600 bytes de memoria RAM. En cuanto al retardo añadido a las comunicaciones, habría que entrar a valorar si es aceptable en la aplicación que vayan a desempeñar los sensores. Pero por lo general un retardo añadido de unos 6 a 11 ms suele ser admisible a cambio de la seguridad que se obtiene. Por tanto, es necesario ver la naturaleza de la aplicación y valorar todos los aspectos como los evaluados en apartados anteriores. 0 5 10 15 20 25 30 Retardo (ms) 75 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 6.6 Líneas futuras Este trabajo de fin de grado se ha limitado a probar medidas de seguridad en la capa de enlace (802.15.4). Esto no nos proporciona ningún grado de seguridad en las comunicaciones IPv6 a través de Internet. Por ello, un posible trabajo futuro sería implementar sobre este mismo entorno de pruebas otras medidas de seguridad que sí proporcionen seguridad a los sensores en Internet. Existen implementaciones de IPsec para 6LoWPAN en Contiki. Con ello se conseguiría asegurar las comunicaciones extremo a extremo a través de Internet. El nodo receptor de nuestro entorno de pruebas pasaría a hacer de pasarela a Internet. Y habrá otro equipo en una red externa IPv6 que recibirá los paquetes IPv6 y los registrará. Figura 6-18. Escenario de una WSN conectada a Internet a través de una pasarela Otra posible prueba de seguridad sobre el entorno sería añadir soporte para TLS/DTLS en la aplicación del emisor y el receptor. De esta forma conseguiríamos seguridad a nivel de aplicación. Se presupone que serán unas medidas de seguridad poco ligeras para lo que viene siendo el software de estas plataformas. Pero por eso habría que realizar las pruebas y ver si es viable su implantación. Existen implementaciones de TLS/DTLS para Contiki. Y dejando de lado la seguridad en Internet e intentando mejorar la seguridad dentro de la WSN, se podría mejorar el escenario planteado. En este trabajo se ha usado una clave precompartida por los nodos (PSK) para el cifrado de los mensajes y los códigos MAC. Si en vez de ello se plantease un escenario con una infraestructura de clave Pruebas y resultados 76 76 pública, los nodos se podrían autenticar con identidad propia. De esta forma si la clave de un nodo es vulnerada, no se vería vulnerada toda la red, sólo el nodo en particular. A la hora de escribir estas líneas, existe un desarrollador de la comunidad Contiki trabajando en una solución de este tipo. Podría probarse qué tal funciona el sistema de intercambio de claves en el entorno que se ha desarrollado en este trabajo. 77 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Pruebas y resultados 78 78 Anexo A: Código de las pruebas udp-sender.c: 1 /* 2 * Copyright (c) 2016, Jose Antonio Caballero Martos. 3 * Universidad de Sevilla 4 * 5 * Copyright (c) 2010, Swedish Institute of Computer Science. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the Institute nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 79 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * This file is part of the Contiki operating system. 33 * 34 */ 35 36 #include "contiki.h" 37 #include "sys/ctimer.h" 38 #include "sys/etimer.h" 39 #include "net/ip/uip.h" 40 #include "net/ipv6/uip-ds6.h" 41 #include "net/ip/uip-udp-packet.h" 42 #include "simple-udp.h" 43 #include "net/rpl/rpl.h" 44 #include "dev/serial-line.h" 45 #include "lib/random.h" 46 47 #if CONTIKI_TARGET_Z1 48 #include "dev/uart0.h" 49 #else 50 #include "dev/uart1.h" 51 #endif 52 #include "collect-common.h" 53 #include "collect-view.h" 54 55 #include <stdio.h> 56 #include <string.h> 57 58 #define UDP_CLIENT_PORT 8775 59 #define UDP_SERVER_PORT 5688 60 61 #define DEBUG DEBUG_PRINT 62 #include "net/ip/uip-debug.h" 63 64 #include "reboot-app.h" 65 #include "servreg-hack.h" 66 67 68 #define UDP_PORT 1234 69 #define SERVICE_ID 190 70 71 /* 72 * Time interval to send another message 73 */ 74 #define SEND_INTERVAL (10 * CLOCK_SECOND) 75 76 /* 77 * Set this to 1 in order to show the printf() output 78 * Set to another value to save ROM Pruebas y resultados 80 80 79 */ 80 #define DEBUG_SENDER 1 81 82 /* 83 * Last sequence number for the messages 84 */ 85 #define MAX_MESSAGE_NUMBER 65535 86 87 /* Unicast sender connections*/ 88 static struct simple_udp_connection unicast_connection; 89 static uip_ipaddr_t *addr; 90 91 /* Collect View client connections */ 92 static struct uip_udp_conn *client_conn; 93 static uip_ipaddr_t server_ipaddr; 94 95 /*-------------------------------------------------------------- -------------*/ 96 97 /* 98 * 99 * collection_view_client_process: will send the statistics to the 100 * Collection View server 101 * 102 * unicast_sender_process: will send the unicast packets to the sink 103 * 104 */ 105 PROCESS(collection_view_client_process, "Collection View client process"); 106 PROCESS(unicast_sender_process, "Unicast sender example process"); 107 AUTOSTART_PROCESSES(&unicast_sender_process, &collection_view_client_process, &collect_common_process); 108 109 /*-------------------------------------------------------------- -------------*/ 110 111 void collect_common_set_sink (void) 112 { 113 /* A udp client can never become sink */ 114 } 115 116 /*-------------------------------------------------------------- -------------*/ 117 118 /* 119 * collect_common_net_print: Prints the routing information 120 */ 121 void collect_common_net_print (void) 122 { 123 rpl_dag_t *dag; 124 uip_ds6_route_t *r; 125 126 /* Let's suppose we have only one instance */ 81 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 127 dag = rpl_get_any_dag(); 128 if(dag->preferred_parent != NULL) { 129 PRINTF("Preferred parent: "); 130 PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent)); 131 PRINTF("\n"); 132 } 133 for(r = uip_ds6_route_head(); 134 r != NULL; 135 r = uip_ds6_route_next(r)) { 136 PRINT6ADDR(&r->ipaddr); 137 } 138 PRINTF("---\n"); 139 } 140 141 /*-------------------------------------------------------------- -------------*/ 142 143 static void tcpip_handler(void) 144 { 145 if(uip_newdata()) { 146 /* The sender ignores incoming data */ 147 } 148 } 149 150 /*-------------------------------------------------------------- -------------*/ 151 152 /* 153 * collect_common_send: Send the statistics to the Collect View server 154 */ 155 void collect_common_send(void) 156 { 157 static uint8_t seqno; 158 struct { 159 uint8_t seqno; 160 uint8_t for_alignment; 161 struct collect_view_data_msg msg; 162 } msg; 163 164 uint16_t parent_etx; 165 uint16_t rtmetric; 166 uint16_t num_neighbors; 167 uint16_t beacon_interval; 168 rpl_parent_t *preferred_parent; 169 linkaddr_t parent; 170 rpl_dag_t *dag; 171 172 if(client_conn == NULL) { 173 /* Not setup yet */ 174 return; 175 } 176 memset(&msg, 0, sizeof(msg)); 177 seqno++; 178 if(seqno == 0) { 179 /* Wrap to 128 to identify restarts */ 180 seqno = 128; Pruebas y resultados 82 82 181 } 182 msg.seqno = seqno; 183 184 linkaddr_copy(&parent, &linkaddr_null); 185 parent_etx = 0; 186 187 /* Let's suppose we have only one instance */ 188 dag = rpl_get_any_dag(); 189 if(dag != NULL) { 190 preferred_parent = dag->preferred_parent; 191 if(preferred_parent != NULL) { 192 uip_ds6_nbr_t *nbr; 193 nbr = uip_ds6_nbr_lookup(rpl_get_parent_ipaddr(preferred_parent)); 194 if(nbr != NULL) { 195 /* Use parts of the IPv6 address as the parent address, in reversed byte order. */ 196 parent.u8[LINKADDR_SIZE - 1] = nbr- >ipaddr.u8[sizeof(uip_ipaddr_t) - 2]; 197 parent.u8[LINKADDR_SIZE - 2] = nbr- >ipaddr.u8[sizeof(uip_ipaddr_t) - 1]; 198 parent_etx = rpl_get_parent_rank((uip_lladdr_t *) uip_ds6_nbr_get_ll(nbr)) / 2; 199 } 200 } 201 rtmetric = dag->rank; 202 beacon_interval = (uint16_t) ((2L << dag->instance- >dio_intcurrent) / 1000); 203 num_neighbors = uip_ds6_nbr_num(); 204 } else { 205 rtmetric = 0; 206 beacon_interval = 0; 207 num_neighbors = 0; 208 } 209 210 collect_view_construct_message(&msg.msg, &parent, 211 parent_etx, rtmetric, 212 num_neighbors, beacon_interval); 213 214 uip_udp_packet_sendto(client_conn, &msg, sizeof(msg), 215 &server_ipaddr, UIP_HTONS(UDP_SERVER_PORT)); 216 } 217 218 /*-------------------------------------------------------------- -------------*/ 219 220 /* 221 * collect_common_net_init: sets the serial line input for Collection View 222 */ 223 void collect_common_net_init(void) 224 { 225 #if CONTIKI_TARGET_Z1 226 uart0_set_input(serial_line_input_byte); 83 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 227 #else 228 uart1_set_input(serial_line_input_byte); 229 #endif 230 serial_line_init(); 231 } 232 233 /*-------------------------------------------------------------- -------------*/ 234 235 /* 236 * print_local_addresses: prints the current IPv6 addresses of the device 237 */ 238 static void print_local_addresses(void) 239 { 240 int i; 241 uint8_t state; 242 243 PRINTF("Client IPv6 addresses: "); 244 for(i = 0; i < UIP_DS6_ADDR_NB; i++) { 245 state = uip_ds6_if.addr_list[i].state; 246 if(uip_ds6_if.addr_list[i].isused && 247 (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { 248 PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); 249 PRINTF("\n"); 250 /* hack to make address "final" */ 251 if (state == ADDR_TENTATIVE) { 252 uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; 253 } 254 } 255 } 256 } 257 258 /*-------------------------------------------------------------- -------------*/ 259 260 /* 261 * set_global_address: sets the IPv6 addresses of the device 262 * and the Collection View server 263 */ 264 static void set_global_address(void) 265 { 266 uip_ipaddr_t ipaddr; 267 268 269 /* Build the IPv6 Address */ 270 uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); 271 /* Set the last 64 bits based on the MAC Address */ 272 uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); 273 /* Add the unicast address to the list */ 274 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); 275 276 /* Set the Collection View server address */ 277 uip_ip6addr(&server_ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); 278 Pruebas y resultados 90 90 udp-sink: 1 /* 2 * Copyright (c) 2016, Jose Antonio Caballero Martos. 3 * Universidad de Sevilla 4 * 5 * Copyright (c) 2010, Swedish Institute of Computer Science. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the Institute nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * This file is part of the Contiki operating system. 33 * 91 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 34 */ 35 36 #include "contiki.h" 37 #include "contiki-lib.h" 38 #include "contiki-net.h" 39 #include "net/ip/uip.h" 40 #include "net/rpl/rpl.h" 41 #include "net/linkaddr.h" 42 43 #include "net/netstack.h" 44 #include "dev/button-sensor.h" 45 #include "dev/serial-line.h" 46 #if CONTIKI_TARGET_Z1 47 #include "dev/uart0.h" 48 #else 49 #include "dev/uart1.h" 50 #endif 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <ctype.h> 55 #include "collect-common.h" 56 #include "collect-view.h" 57 58 #define DEBUG DEBUG_PRINT 59 #include "net/ip/uip-debug.h" 60 61 /* Contiki apps */ 62 #include "reboot-app.h" 63 #include "servreg-hack.h" 64 65 /* Sink server UDP Port and Service ID */ 66 #define UDP_PORT 1234 67 #define SERVICE_ID 190 68 69 #if 0 70 #define SEND_INTERVAL (10 * CLOCK_SECOND) 71 #define SEND_TIME SEND_INTERVAL 72 #endif 73 74 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) 75 76 #define UDP_COLLECT_CLIENT_PORT 8775 77 #define UDP_COLLECT_SERVER_PORT 5688 78 79 /* 80 * Set this to 1 in order to show the printf() output 81 * Set to another value to save ROM 82 */ 83 #define DEBUG_SINK 1 84 85 /* Unicast connections*/ 86 static struct simple_udp_connection unicast_connection; 87 88 /* Collect View */ 89 static struct uip_udp_conn *server_conn; Pruebas y resultados 92 92 90 91 /*-------------------------------------------------------------- -------------*/ 92 93 /* 94 * 95 * collection_view_server_process: will receive the statistics of the 96 * sender sensor 97 * 98 * unicast_receiver_process: will receive the unicast packets to the sink 99 * 100 */ 101 PROCESS(unicast_receiver_process, "Unicast receiver example process"); 102 PROCESS(collection_view_server_process, "UDP server process"); 103 AUTOSTART_PROCESSES(&unicast_receiver_process, &collection_view_server_process, &collect_common_process); 104 105 /*-------------------------------------------------------------- -------------*/ 106 107 /* 108 * These functions are common between the client and the server, but 109 * there is no real need to implement them in the sink server 110 */ 111 void collect_common_set_sink(void) 112 { 113 } 114 115 void collect_common_net_print(void) 116 { 117 printf("Sink\n"); 118 } 119 120 121 void collect_common_send(void) 122 { 123 /* Server never sends */ 124 } 125 126 /*-------------------------------------------------------------- -------------*/ 127 128 /* 129 * collect_common_net_init: sets the serial line input for Collection View 130 */ 131 void collect_common_net_init(void) 132 { 133 #if CONTIKI_TARGET_Z1 134 uart0_set_input(serial_line_input_byte); 135 #else 136 uart1_set_input(serial_line_input_byte); 93 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 137 #endif 138 serial_line_init(); 139 } 140 141 /*-------------------------------------------------------------- -------------*/ 142 143 /* 144 * tcpip_handler: handles the incoming packet from the sender sensor 145 * and gathers the information for the Collection View app 146 */ 147 static void tcpip_handler(void) 148 { 149 uint8_t *appdata; 150 linkaddr_t sender; 151 uint8_t seqno; 152 uint8_t hops; 153 154 if(uip_newdata()) { 155 appdata = (uint8_t *)uip_appdata; 156 sender.u8[0] = UIP_IP_BUF->srcipaddr.u8[15]; 157 sender.u8[1] = UIP_IP_BUF->srcipaddr.u8[14]; 158 seqno = *appdata; 159 hops = uip_ds6_if.cur_hop_limit - UIP_IP_BUF->ttl + 1; 160 collect_common_recv(&sender, seqno, hops, 161 appdata + 2, uip_datalen() - 2); 162 } 163 } 164 165 166 /*-------------------------------------------------------------- -------------*/ 167 168 /* 169 * print_local_addresses: prints the current IPv6 addresses of the device 170 */ 171 static void print_local_addresses(void) 172 { 173 #if DEBUG_SINK == 1 174 175 int i; 176 uint8_t state; 177 178 PRINTF("Server IPv6 addresses: "); 179 for(i = 0; i < UIP_DS6_ADDR_NB; i++) { 180 state = uip_ds6_if.addr_list[i].state; 181 if(state == ADDR_TENTATIVE || state == ADDR_PREFERRED) { 182 PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); 183 PRINTF("\n"); 184 /* hack to make address "final" */ 185 if (state == ADDR_TENTATIVE) { 186 uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; 187 } 188 } 189 } Pruebas y resultados 94 94 190 191 #endif 192 } 193 194 /*-------------------------------------------------------------- -------------*/ 195 196 /* 197 * set_global_address: sets the IPv6 addresses of the device 198 */ 199 static uip_ipaddr_t * set_global_address(void) 200 { 201 static uip_ipaddr_t ipaddr; 202 203 // Build the IPv6 Address 204 uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); 205 // Set the last 64 bits based on the MAC Address 206 uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); 207 // We add the unicast address to the list 208 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); 209 210 return &ipaddr; 211 } 212 213 /*-------------------------------------------------------------- -------------*/ 214 215 static void receiver(struct simple_udp_connection *c, 216 const uip_ipaddr_t *sender_addr, 217 uint16_t sender_port, 218 const uip_ipaddr_t *receiver_addr, 219 uint16_t receiver_port, 220 const uint8_t *data, 221 uint16_t datalen) 222 { 223 printf("Data received from "); 224 uip_debug_ipaddr_print(sender_addr); 225 printf(" on port %d from port %d with length %d: '%s'\n", 226 receiver_port, sender_port, datalen, data); 227 } 228 229 /*-------------------------------------------------------------- -------------*/ 230 231 PROCESS_THREAD(collection_view_server_process, ev, data) 232 { 233 uip_ipaddr_t ipaddr; 234 struct uip_ds6_addr *root_if; 235 236 PROCESS_BEGIN(); 237 238 PROCESS_PAUSE(); 239 240 #if DEBUG_SINK == 1 241 PRINTF("UDP server started\n"); 95 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 242 #endif 243 244 #if UIP_CONF_ROUTER 245 uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); 246 /* uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); */ 247 uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL); 248 root_if = uip_ds6_addr_lookup(&ipaddr); 249 if(root_if != NULL) { 250 rpl_dag_t *dag; 251 dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); 252 uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); 253 rpl_set_prefix(dag, &ipaddr, 64); 254 PRINTF("created a new RPL dag\n"); 255 } else { 256 PRINTF("failed to create a new RPL DAG\n"); 257 } 258 #endif /* UIP_CONF_ROUTER */ 259 260 print_local_addresses(); 261 262 server_conn = udp_new(NULL, UIP_HTONS(UDP_COLLECT_CLIENT_PORT), NULL); 263 udp_bind(server_conn, UIP_HTONS(UDP_COLLECT_SERVER_PORT)); 264 265 #if DEBUG_SINK == 1 266 PRINTF("Created a server connection with remote address "); 267 PRINT6ADDR(&server_conn->ripaddr); 268 PRINTF(" local/remote port %u/%u\n", UIP_HTONS(server_conn- >lport), 269 UIP_HTONS(server_conn->rport)); 270 #endif 271 272 while(1) { 273 PROCESS_YIELD(); 274 if(ev == tcpip_event) { 275 tcpip_handler(); 276 } else if (ev == sensors_event && data == &button_sensor) { 277 PRINTF("Initiaing global repair\n"); 278 rpl_repair_root(RPL_DEFAULT_INSTANCE); 279 } 280 } 281 282 PROCESS_END(); 283 } 284 285 /*-------------------------------------------------------------- -------------*/ 286 287 PROCESS_THREAD(unicast_receiver_process, ev, data) 288 { 289 uip_ipaddr_t *ipaddr; 290 291 PROCESS_BEGIN(); 292 Pruebas y resultados 96 96 293 servreg_hack_init(); 294 295 ipaddr = set_global_address(); 296 297 servreg_hack_register(SERVICE_ID, ipaddr); 298 299 simple_udp_register(&unicast_connection, UDP_PORT, 300 NULL, UDP_PORT, receiver); 301 302 while(1) { 303 PROCESS_WAIT_EVENT(); 304 } 305 PROCESS_END(); 306 } 307 308 /*-------------------------------------------------------------- -------------*/ 309 310 311 97 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 collect-common.c: 1 /* 2 * Copyright (c) 2010, Swedish Institute of Computer Science. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the Institute nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 */ 30 31 /** 32 * \file Pruebas y resultados 98 98 33 * Example of how the collect primitive works. 34 * \author 35 * Adam Dunkels <[email protected]> 36 */ 37 38 #include "contiki.h" 39 #include "lib/random.h" 40 #include "net/netstack.h" 41 #include "dev/serial-line.h" 42 #include "dev/leds.h" 43 #include "collect-common.h" 44 45 #include <stdio.h> 46 #include <string.h> 47 #include <ctype.h> 48 49 static unsigned long time_offset; 50 static int send_active = 1; 51 52 #ifndef PERIOD 53 #define PERIOD 60 54 #endif 55 #define RANDWAIT (PERIOD) 56 57 /*-------------------------------------------------------------- -------------*/ 58 PROCESS(collect_common_process, "collect common process"); 59 AUTOSTART_PROCESSES(&collect_common_process); 60 /*-------------------------------------------------------------- -------------*/ 61 static unsigned long 62 get_time(void) 63 { 64 return clock_seconds() + time_offset; 65 } 66 /*-------------------------------------------------------------- -------------*/ 67 static unsigned long 68 strtolong(const char *data) { 69 unsigned long value = 0; 70 int i; 71 for(i = 0; i < 10 && isdigit(data[i]); i++) { 72 value = value * 10 + data[i] - '0'; 73 } 74 return value; 75 } 76 /*-------------------------------------------------------------- -------------*/ 77 void 78 collect_common_set_send_active(int active) 79 { 80 send_active = active; 81 } 82 /*-------------------------------------------------------------- -------------*/ 83 void 99 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 84 collect_common_recv(const linkaddr_t *originator, uint8_t seqno, uint8_t hops, 85 uint8_t *payload, uint16_t payload_len) 86 { 87 unsigned long time; 88 uint16_t data; 89 int i; 90 91 printf("%u", 8 + payload_len / 2); 92 /* Timestamp. Ignore time synch for now. */ 93 time = get_time(); 94 printf(" %lu %lu 0", ((time >> 16) & 0xffff), time & 0xffff); 95 /* Ignore latency for now */ 96 printf(" %u %u %u %u", 97 originator->u8[0] + (originator->u8[1] << 8), seqno, hops, 0); 98 for(i = 0; i < payload_len / 2; i++) { 99 memcpy(&data, payload, sizeof(data)); 100 payload += sizeof(data); 101 printf(" %u", data); 102 } 103 printf("\n"); 104 leds_blink(); 105 } 106 /*-------------------------------------------------------------- -------------*/ 107 PROCESS_THREAD(collect_common_process, ev, data) 108 { 109 static struct etimer period_timer, wait_timer; 110 PROCESS_BEGIN(); 111 112 collect_common_net_init(); 113 114 /* Send a packet every 60-62 seconds. */ 115 etimer_set(&period_timer, CLOCK_SECOND * PERIOD); 116 while(1) { 117 PROCESS_WAIT_EVENT(); 118 if(ev == serial_line_event_message) { 119 char *line; 120 line = (char *)data; 121 if(strncmp(line, "collect", 7) == 0 || 122 strncmp(line, "gw", 2) == 0) { 123 collect_common_set_sink(); 124 } else if(strncmp(line, "net", 3) == 0) { 125 collect_common_net_print(); 126 } else if(strncmp(line, "time ", 5) == 0) { 127 unsigned long tmp; 128 line += 6; 129 while(*line == ' ') { 130 line++; 131 } 132 tmp = strtolong(line); 133 time_offset = clock_seconds() - tmp; 134 printf("Time offset set to %lu\n", time_offset); 135 } else if(strncmp(line, "mac ", 4) == 0) { 136 line +=4; 137 while(*line == ' ') { Glosario 106 106 RPL: IPv6 Routing Protocol for Low-Power and Lossy Networks. 107 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6 Glosario 108 108 109 Desarrollo de un entorno de pruebas de autenticación y seguridad de redes de sensores con IPv6