Memoria del proyecto - Departamento de Teoría de la Señal

Transcripción

Memoria del proyecto - Departamento de Teoría de la Señal
Caracterización de anomalías en
tráco P2P mediante autómatas de
estados nitos
Departamento de Teoría de la Señal, Telemática y
Comunicaciones
Proyecto Fin de Carrera
Jesús Javier Nuño García
Directores:
Jesús Esteban Díaz Verdejo
Gabriel Maciá Fernández
D. Jesús Esteban Díaz Verdejo y D. Gabriel Maciá Fernández, profesores de la Escuela
Técnica Superior de Ingenierías Informática y Telecomunicación del Departamento de
Teoría de la Señal, Telemática y Comunicaciones, como Directores del Proyecto Fin de
Carrera de D. Jesús Javier Nuño García
DECLARAN
que este trabajo, con título Caracterización de anomalías en tráco P2P con autómatas de estados nitos , ha sido elaborado por el alumno mencionado bajo nuestra
supervisión y autorizamos su defensa ante el tribunal que corresponda.
Y para que conste, rmamos el presente documento, en Granada, a 1 de septiembre
de 2009.
D. Jesús Esteban Díaz Verdejo
D. Gabriel Maciá Fernández
i
ii
Jesús Javier Nuño García, con DNI n
º
75.144.433-Y, alumno de Ingeniería Informá-
tica de la Escuela Técnica Superior de Ingenierías Informática y Telecomunicación de
la Universidad de Granada, autoriza que se expida una copia del presente documento
de Proyecto Fin de Carrera a la biblioteca del Centro, a n de poder ser consultada o
referenciada por aquellas personas que lo deseen.
Granada, a 1 de septiembre de 2009
Jesús Javier Nuño García
iii
iv
Caracterización de anomalías en tráco P2P
mediante autómatas de estados nitos
Jesús Javier Nuño García
Palabras clave:
Protocolo eDonkey, anomalía, autómata de estados nitos, IDS, P2P.
Resumen:
El popular protocolo para redes
peer-to-peer
`eDonkey', dene un modo de intercambio
de mensajes entre ciertas entidades involucradas en una comunicación. En particular,
establece la secuencia y tipo de tramas intercambiadas entre dos nodos (peers ) de la
red P2P. Para cada situación, este protocolo tiene denido una serie de intercambios de
mensajes consecutivos. Para cada uno de estos escenarios se puede denir un autómata
de estados nitos que modele el comportamiento del protocolo.
Mediante el desarrollo de una aplicación con conocimiento acerca de estos autómatas,
se puede analizar el comportamiento de las entidades en el uso del protocolo. A partir de
los resultados obtenidos, estos comportamientos se podrán clasicar como permitidos o
no, dependiendo de si han seguido la especicación del protocolo instanciada en los autómatas. Los comportamientos no acordes a dichos autómatas podrán, consecuentemente,
clasicarse como anómalos desde el punto de vista de la seguridad de los sistemas.
En este proyecto se modela e implementa un entorno de análisis que permite evaluar las
posibles anomalías existentes en el protocolo `eDonkey' mediante autómatas de estados
nitos. Adicionalmente, se diseñan y realizan una serie de pruebas de evaluación para
comprobar el correcto funcionamiento de la aplicación, así como su rendimiento.
v
vi
Anomaly characterization in P2P trac with
nite-state machines
Jesús Javier Nuño García
Keywords:
eDonkey protocol, anomaly, nite-state machine, IDS, P2P.
Abstract:
The popular peer-to-peer protocol `eDonkey', denes message exchange between certain entities involved in a communication. In particular, it establishes the sequence and
type of frames exchanged between two P2P network nodes (peers). For every possible
situation, this protocol denes a series of consecutive message exchange. For each of these
scenarios, a nite-state machine can be dened to model the protocol's behavior.
By developing an application with information about these nite-state machines, the
behavior of the communication entities, related to the use of the protocol, can be analyzed. From the results obtained, these behaviors may be classied as allowed or not,
depending on whether they have followed the protocol specication as instantiated in
nite-state machines. Those behaviors not coherent with these nite-state machines can
be consequently classied as abnormal from a system security point of view.
In this project, an environment is modeled and implemented. It makes it possible to
evaluate possible anomalies in `eDonkey' protocol by nite-state machines. In order to
check the correct implementation of the application, as well as its performance, a series
of tests are designed, being their result clearly discussed.
vii
viii
Agradecimientos
Estoy especialmente agradecido a mis padres y mi hermana, por el apoyo incondicional
que me han dado durante toda mi carrera.
Especial agradecimiento a mis compañeros, por su ayuda, dedicación, buen hacer y
compañerismo, dado que gracias a ellos he conseguido aprender mucho más de lo imaginable.
Y por último, dar innitas gracias a mis directores D. Jesús Esteban Díaz Verdejo y
D. Gabriel Maciá Fernández por el interés, la motivación y el apoyo que me han prestado
durante tanto tiempo.
Gracias a todos.
ix
x
Licencia
©
<Caracterización de anomalías en tráco P2P mediante autómatas de estados nitos>
Copyright
<2009> <Jesús Javier Nuño García>
Este Programa es Software Libre: usted puede redistribuirlo y/o modicarlo bajo los
ª
términos de la Licencia Publica General GNU como es publicada por la Fundacion de
Software Libre; en la 3
versión de la licencia, o (a su opción) cualquier versión posterior.
Este programa es distribuido con la esperanza de que sea útil, pero SIN GARANTÍA
ALGUNA; sin siquiera la garantía implícita de VALOR COMERCIAL o FORMADO
PARA UN PROPÓSITO EN PARTICULAR. Vea la Licencia Publica General GNU
para más detalles.
Usted debe haber recibido una copia de la Licencia Publica General GNU junto con
este programa. Si no, vaya a <http://www.gnu.org/licenses/>.
xi
xii
Índice general
0. Descripción del problema y especicaciones
1
1. Introducción
3
1.1.
Las redes en la actualidad . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
1.2.
¾Qué son las redes P2P y por qué son importantes? . . . . . . . . . . . . .
5
1.3.
El protocolo `eDonkey' . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.4.
Justicación del proyecto
. . . . . . . . . . . . . . . . . . . . . . . . . . .
2. Fundamentos tecnológicos
8
16
19
2.1.
Teoría de autómatas de estados nitos
. . . . . . . . . . . . . . . . . . . .
2.2.
Paradigma cliente-servidor . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
2.3.
Modelado de protocolos con autómatas de estados nitos . . . . . . . . . .
25
2.4.
Herramientas y utilidades
27
. . . . . . . . . . . . . . . . . . . . . . . . . . .
3. Análisis
19
37
3.1.
Procedimientos en el protocolo `eDonkey'
. . . . . . . . . . . . . . . . . .
3.2.
Análisis de requisitos y funcionalidades de la aplicación . . . . . . . . . . .
59
3.3.
Discusión del análisis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
63
4. Diseño e implementación
37
65
4.1.
Estructura modular de la aplicación
. . . . . . . . . . . . . . . . . . . . .
65
4.2.
Descripción de las estructuras de datos utilizadas . . . . . . . . . . . . . .
74
5. Evaluación
81
5.1.
Diseño de las pruebas de evaluación . . . . . . . . . . . . . . . . . . . . . .
81
5.2.
Evaluación de la funcionalidad de la aplicación
. . . . . . . . . . . . . . .
88
5.3.
Evaluación del rendimiento de la aplicación
. . . . . . . . . . . . . . . . .
94
6. Planicación y estimación de recursos
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
97
6.1.
Planicación
6.2.
Recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
xv
97
Índice general
6.3.
Estudio económico
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
7. Logros y conclusiones
103
7.1.
Logros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
7.2.
Conclusiones
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Bibliografía
105
Apéndice
107
A. Descripción de los métodos utilizados
107
xvi
Índice de guras
1.1.
1.2.
Millones de usuarios conectados a Internet (enero de 2009).
. . . . . . . .
3
Porcentaje de población que se conecta a Internet en los quince países más
poblados (enero 2009). . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
1.3.
Distribución porcentual del tráco de Internet en Alemania en 2007.
. . .
4
1.4.
Interfaz del cliente `eMule'.
. . . . . . . . . . . . . . . . . . . . . . . . . .
8
1.5.
Porcentaje de uso de protocolos P2P en Alemania en 2007 (véase [2]).
. .
9
1.6.
Estructura de la red `eMule' (protocolo `eDonkey'). . . . . . . . . . . . . .
11
1.7.
Estructura de una trama del protocolo `eDonkey'. . . . . . . . . . . . . . .
16
2.1.
Autómata de ejemplo.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
2.2.
Autómata de ejemplo.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
2.3.
Ejemplo de AFD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
2.4.
Ejemplo de AFND. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
2.5.
Ejemplo de conexión entre dos computadores cualesquiera. . . . . . . . . .
24
2.6.
Ejemplo de intercambio de paquetes entre dos nodos de una red P2P. . . .
26
2.7.
Ejemplo de información extraída en el intercambio de tramas entre dos
nodos en la red. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
2.8.
Información extraída de tres tramas.
. . . . . . . . . . . . . . . . . . . . .
27
2.9.
Ejemplo de modelado de protocolo con un autómata. . . . . . . . . . . . .
27
2.10. Conexión entre los tres elementos principales de la STL.
2.11. Costes en tiempo (aproximados) para
fork()
. . . . . . . . . .
pthread_create().
28
. . . . . .
33
. . . . . . . . . . . . . . . . . . . .
34
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
2.12. Grupos funcionales de rutinas
Pthread.
y
3.1.
Conexión con ID alto.
3.2.
Conexión con ID bajo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
3.3.
Conexión rechazada.
40
3.4.
Establecimiento de conexión modelado con autómata de estados nitos.
3.5.
Secuencia de mensajes al inicio de la conexión.
3.6.
Secuencia de mensajes al inicio de la conexión modelada con autómata de
estados nitos.
3.7.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
41
. . . . . . . . . . . . . . .
42
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
42
Secuencia de mensajes de búsqueda de archivos. . . . . . . . . . . . . . . .
43
xvii
Índice de guras
3.8.
Autómata de estados nitos para la búsqueda de archivos. . . . . . . . . .
3.9.
Secuencia de mensajes para el mecanismo de
3.10. Secuencia de mensajes para el mecanismo de
callback. . . . . . . . . . . .
callback modelada con auto-
mata de estados nitos (Cliente A). . . . . . . . . . . . . . . . . . . . . . .
3.11. Secuencia de mensajes para el mecanismo de
mata de estados nitos (Servidor).
callback
callback
44
45
modelada con auto-
. . . . . . . . . . . . . . . . . . . . . .
3.12. Secuencia de mensajes para el mecanismo de
44
45
modelada con auto-
mata de estados nitos (Cliente B). . . . . . . . . . . . . . . . . . . . . . .
keep-alive UDP. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
keep-alive UDP. . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.15. Secuencia keep-alive UDP modelada con autómata de estados nitos. . . .
3.16. Handshake inicial de los clientes `eMule'. . . . . . . . . . . . . . . . . . . .
3.17. Handshake inicial de los clientes `eMule' modelado con autómata de esta-
45
3.13. Ciclo de
46
3.14. Secuencia
46
dos nitos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
47
48
48
3.18. Identicación segura. `A' no tiene la clave pública de `B'. . . . . . . . . . .
49
3.19. Identicación segura. `A' tiene la clave pública de `B'.
. . . . . . . . . . .
49
3.20. Identicación segura modelada con autómata de estados nitos. . . . . . .
50
3.21. Solicitud de chero. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
3.22. Solicitud de archivo fallida. Archivo no encontrado. . . . . . . . . . . . . .
51
3.23. Solicitud de chero modelada con autómata de estados nitos. . . . . . . .
51
3.24. Cola de espera para una solicitud de un archivo. . . . . . . . . . . . . . . .
52
3.25. Cola de espera para una solicitud de un archivo modelada con autómata
de estados nitos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.26. Descarga de un archivo.
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.27. Descarga de un archivo modelada con autómata de estados nitos.
3.28. Detalles del mensaje de la parte de un archivo.
53
53
. . . .
54
. . . . . . . . . . . . . . .
54
3.29. Detalles del mensaje de la parte de un archivo modelado con autómata de
estados nitos.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.30. Intercambio de fragmentos de archivo.
. . . . . . . . . . . . . . . . . . . .
55
55
3.31. Intercambio de fragmentos de archivo modelado con autómata de estados
nitos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
3.32. Solicitud de vista de archivos compartidos. . . . . . . . . . . . . . . . . . .
56
3.33. Consulta de archivos y carpetas compartidos.
. . . . . . . . . . . . . . . .
3.34. Solicitudes de vista de archivos y carpetas denegadas.
. . . . . . . . . . .
57
57
3.35. Vista de archivos y carpetas compartidos modelada con autómata de estados nitos.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
hash de fragmento de archivo. .
de hash de fragmento de archivo
3.36. Solicitud de
3.37. Solicitud
estados nitos.
. . . . . . . . . . . . . . . . .
58
58
modelada con autómata de
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.38. Obtención de la previsualización de un archivo.
. . . . . . . . . . . . . . .
58
59
3.39. Obtención de la previsualización de un archivo modelada con autómata
de estados nitos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.40. Mensaje de re-solicitud de archivo.
. . . . . . . . . . . . . . . . . . . . . .
59
60
3.41. Mensaje de re-solicitud de archivo modelado con autómata de estados nitos. 60
xviii
Índice de guras
3.42. Estructura principal del programa.
. . . . . . . . . . . . . . . . . . . . . .
4.1.
Estructura en módulos del programa principal.
4.2.
4.3.
61
. . . . . . . . . . . . . . .
66
Autómata de ejemplo.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72
Autómata de ejemplo.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
4.4.
Esquema de un objeto de la clase `estado'. . . . . . . . . . . . . . . . . . .
75
4.5.
Autómata con un estado.
. . . . . . . . . . . . . . . . . . . . . . . . . . .
75
4.6.
Objeto `estado' para el estado de la Figura 4.5.. . . . . . . . . . . . . . . .
76
4.7.
Autómata con un estado.
76
4.8.
Objeto `estado' para el estado de la Figura 4.7.
4.9.
Autómata con tres estados.
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
76
. . . . . . . . . . . . . . . . . . . . . . . . . .
76
4.10. Objeto `estado' para el estado de la Figura 4.9.
. . . . . . . . . . . . . . .
77
. . . . . . . . . . . . . .
79
4.12. Relaciones entre las clases diseñadas. . . . . . . . . . . . . . . . . . . . . .
79
4.13. Diagrama de clases de diseño para la aplicación desarrollada.
. . . . . . .
80
5.1.
Estadísticas generales de los cheros de prueba. . . . . . . . . . . . . . . .
82
5.2.
Estadísticas del uso de protocolos para el chero de pruebas n 1.
. . . . .
82
5.3.
Estadísticas del uso de protocolos para el chero de pruebas n 2.
. . . . .
83
5.4.
Estadísticas del uso de protocolos para el chero de pruebas n 3.
. . . . .
83
5.5.
Estadísticas del uso de protocolos para el chero de pruebas n 4.
. . . . .
84
5.6.
Autómata correspondiente a Búsqueda de archivos. . . . . . . . . . . . .
84
5.7.
Autómata correspondiente a Establecimiento de conexión.
. . . . . . . .
84
5.8.
Autómata correspondiente a Secuencia de inicio de conexión. . . . . . . .
85
5.9.
Autómata correspondiente a Búsqueda de archivos. . . . . . . . . . . . .
4.11. Estructura de un objeto de la clase `datosFlujo'.
º
º
º
º
5.10. Autómata correspondiente a Establecimiento de conexión.
85
. . . . . . . .
86
5.11. Autómata correspondiente a Secuencia de inicio de conexión. . . . . . . .
86
5.12. Autómata correspondiente a Búsqueda de archivos. . . . . . . . . . . . .
86
5.13. Autómata correspondiente a Handshake inicial.
86
. . . . . . . . . . . . . .
5.14. Autómata correspondiente a Nueva secuencia de inicio de conexión. . . .
87
5.15. Autómata correspondiente a Ofrecer cheros.
. . . . . . . . . . . . . . .
87
5.16. Muestra de una trama `eDonkey' con Wireshark.
. . . . . . . . . . . . . .
90
5.17. Salida observada para la Prueba 5.
. . . . . . . . . . . . . . . . . . . . . .
92
5.18. Salida observada para la Prueba 6.
. . . . . . . . . . . . . . . . . . . . . .
93
5.19. Salida observada para la Prueba 7.
. . . . . . . . . . . . . . . . . . . . . .
93
5.20. Tiempos de ejecución de las pruebas realizadas. . . . . . . . . . . . . . . .
95
5.21. Actividad del grafo de llamadas.
. . . . . . . . . . . . . . . . . . . . . . .
95
5.22. Mediciones de tiempos para algunos métodos de la aplicación. . . . . . . .
95
6.1.
Esquema de las tareas inicialmente planicadas. . . . . . . . . . . . . . . .
98
6.2.
Diagrama de Gantt.
99
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.1. Ejemplo de estado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
A.2. Ejemplo de estado tras la llamada a `setMensaje'. . . . . . . . . . . . . . . 109
A.3. Ejemplo de estado con un mensaje. . . . . . . . . . . . . . . . . . . . . . . 109
xix
Índice de guras
A.4. Ejemplo de estado con un mensaje tras la llamada a `setMensaje'. . . . . . 109
xx
Capı́tulo
0
Descripción del problema y
especicaciones
Descripción del problema
En la actual sociedad de la información, existe un gran número de usuarios con acceso
a Internet. Gran parte del uso que se hace de Internet, está asociado debido a las redes
peer-to-peer,
las que, de manera supercial, se pueden denir como redes formadas por
una serie de nodos interconectados entre sí, en los que cada uno de ellos puede actuar
como cliente y como servidor al mismo tiempo.
Actualmente existen un gran número de aplicaciones compatibles con este tipo de
redes. Dichas aplicaciones funcionan gracias a un protocolo subyacente, el cual controla
el funcionamiento de estas redes. Existen múltiples protocolos P2P a día de hoy; uno de
los más conocidos y extendidos es el protocolo `eDonkey'.
Dentro del comportamiento habitual de este protocolo, existen una serie de acciones
básicas que se pueden clasicar según la naturaleza de la conexión: cliente-cliente o
cliente-servidor. Se pretende detectar el mal uso del protocolo con la nalidad de intentar
detectar potenciales problemas de seguridad (ataques, vulnerabilidades, etc.).
Por ello, se propone el desarrollo de una aplicación capaz de analizar los ujos producidos por este protocolo y clasicarlos en acordes a la especicación o no. En este
último caso se dirá que son ujos anómalos y, en consecuencia, requieren un análisis de
seguridad.
Especicaciones de la aplicación
Debe detectar ujos anómalos en el protocolo P2P `eDonkey'.
Debe ser exible, es decir, debe tener la capacidad de ser modicada por terceros
sin excesiva dicultad.
Debe ser extensible respecto a otros protocolos.
1
0. Descripción del problema y especicaciones
Debe estar desarrollada en el lenguaje ANSI C++.
Debe aceptar, para su análisis, cheros con tramas o bien analizar un protocolo en
vivo a través de una interfaz de red.
La especicación/denición de los autómatas debe ser sencilla e independiente del
programa principal.
2
Capı́tulo
1
Introducción
1.1. Las redes en la actualidad
Las redes de comunicaciones constituyen una parte importante de la comunicación
en la actual sociedad de la información. Años atrás, estas sólo estaban al alcance de
algunos pocos, como organismos ociales y al ámbito militar. Pero la losofía de compartir
información, tan de moda en la actualidad, ha hecho que las redes de comunicaciones se
expandan (y sigan haciéndolo) a gran velocidad, de modo que permiten estar comunicado
con el resto del mundo.
Una prueba de ello es la gran cantidad de usuarios con acceso a Internet. En la Figura
1.1 se muestra la cantidad de usuarios con acceso a Internet de los quince países más
poblados, como se puede consultar en [2].
La imagen no ofrece demasiada precisión, ya que muestra las cantidades en millones
de usuarios pero no indica cuántos habitantes tiene cada uno de los países mostrados ya
que, por ejemplo, China está más poblada que Italia. Por ello se muestra en la Figura
1.2 la relación habitantes/usuarios con acceso a Internet.
Figura 1.1: Millones de usuarios conectados a Internet (enero de 2009).
3
1. Introducción
Figura 1.2: Porcentaje de población que se conecta a Internet en los quince países más
poblados (enero 2009).
En la Figura 1.2 se puede apreciar mejor la proporción de usuarios con acceso a Internet, en especial en los países más desarrollados, como Reino Unido o Corea del Sur,
en los que la mayor parte de la población dispone de dicho acceso. Sin embargo, India es
justamente el punto opuesto, incluso siendo el segundo país más poblado del planeta.
Internet ofrece a día de hoy una ingente cantidad de usos y servicios, como por ejemplo:
FTP, mensajería instantánea, streaming, redes P2P, correo electrónico, tráco HTTP, etc.
Esto hace que existan millones de usuarios con acceso a la Red y que los servicios sean
cada vez más demandados. El tráco existente en Internet corresponde mayoritariamente
a redes P2P, como se explica en [2], como evidencia el estudio realizado por la compañía
`iPoque' en 2007 en Alemania (véase la Figura 1.3).
Como se puede apreciar, las redes P2P tienen una gran aceptación entre la comunidad
de usuarios que conforma Internet, ya que el tráco producido por este tipo de redes es
muy superior al resto de tráco en Internet. Ni siquiera el tráco HTTP o de Streaming
puede compararse en la actualidad con el generado por las redes P2P.
Figura 1.3: Distribución porcentual del tráco de Internet en Alemania en 2007.
4
1. Introducción
1.2. ¾Qué son las redes P2P y por qué son importantes?
Existen múltiples deniciones que de las redes P2P. Una de ellas, de acuerdo a [3], es:
Las redes
peer-to-peer
(P2P) son unas redes en las que existe como prin-
cipio básico la compartición de recursos entre computadoras. Tales recursos
incluyen procesamiento, conocimiento, almacenamiento de datos e información de bases de datos distribuidas.
En los últimos años, se ha invertido aproximadamente medio billón de dólares en
compañías dedicadas al desarrollo de sistemas P2P.
Este interés es debido al éxito de muchas aplicaciones, como, por ejemplo, `Napster'
(hoy en día ya desaparecida) o `eMule'. El concepto de compartición de recursos no es
totalmente nuevo, ya que los sistemas P2P son una evolución natural en la arquitectura
de sistemas.
Lo que caracteriza a una red P2P es que la relación es directa entre los equipos que
actúan como iguales, ya que los computadores pueden actuar como clientes y servidores al
mismo tiempo. El comportamiento de dichas computadoras se determinará dependiendo
de los requerimientos del sistema en cada momento. Por ejemplo, un computador `A'
envía una solicitud de un chero a un computador `B'. En este momento, el computador
`B' estaría actuando de servidor y el `A' sería el cliente. Poco después, es el computador
`B' el que envía una solicitud de archivo al computador `A', por lo que, en este caso el
comportamiento es justo el contrario, ya que `A' sería el servidor y `B' el cliente.
Las redes
peer-to-peer
permiten a los usuarios hacer uso de toda la información dispo-
nible en la red, ayudan a realizar grandes trabajos computacionales que antes no eran
posibles y, además, su implementación no tiene un gran coste para pequeñas compañías
e incluso, para uso particular. Estas redes cuentan con la ventaja de tener acceso distribuido a determinados recursos. En denitiva, una red P2P tiene grandes benecios en
costes y un procesamiento veloz.
Existen una serie de características comunes ampliamente aceptadas en relación a los
sistemas P2P:
Un
peer
es cada uno de los nodos que forma parte de una red P2P, siendo habi-
tualmente un computador que puede actuar tanto de cliente como de servidor. Este
comportamiento se determinará por los requerimientos del sistema en un momento concreto. En algunos sistemas P2P, un
peer
puede actuar como cliente y como
servidor al mismo tiempo.
Una red P2P consiste en, al menos, dos o más
Los
peers
peers.
son capaces de intercambiar recursos directamente entre ellos, como ar-
chivos, información, procesamiento, etc.
Los servidores dedicados puede que estén o no presentes en un sistema P2P, dependiendo de la naturaleza de las aplicaciones. Sin embargo, el comportamiento de
la mayoría de estos servidores se limita a permitir a los
peers
descubrirse los unos
a los otros. Dicho de otra manera, asumen el papel de agentes.
5
1. Introducción
Los
peers
pueden entrar o abandonar un sistema con total libertad.
Los
peers
pueden pertenecer a diferentes usuarios. Lo normal en un sistema P2P
es tener millones de usuarios.
1.2.1.
Ventajas de un sistema P2P
La mayoría de los sistemas P2P tienen las siguientes ventajas:
La carga de trabajo se reparte entre todos los
peers. Es posible que existan millones
de computadores en una red P2P que proporcionen grandes cantidades de datos y
procesamiento.
Muchos computadores tienen recursos que no se usan. Por ejemplo, en una ocina,
los computadores no se usan durante un determinado horario (normalmente por
la noche). Un sistema P2P puede utilizar estos computadores con sus recursos
correspondientes, para así maximizar el uso.
Ciertas empresas podrían ahorrar mucho dinero mediante una buena utilización de
las instalaciones que existen, en lo que a sistemas P2P se reere.
No se necesita un control centralizado ni un riguroso manejo de una red P2P.
La escalabilidad en una red P2P se hace evidente debido a que, si existen nuevos
peers,
pueden unirse al sistema P2P de una manera muy sencilla.
Una red P2P funcionará incluso si algunos de sus
peers
no funcionan correctamente.
De esta manera, se hace más tolerante a fallos que otros sistemas.
Los usuarios de una red P2P pueden entrar y salir cuando quieran. Así, dichos
usuarios pueden mantener el control de sus recursos.
1.2.2.
Inconvenientes de un sistema P2P
Aunque los sistemas P2P proporcionan grandes benecios, no son sistemas infalibles.
Una red P2P puede no ser la herramienta apropiada para determinadas tareas. A continuación se muestra una serie de desventajas de estos sistemas:
Las redes P2P pueden ser utilizadas con nes maliciosos, como pueden ser ataques
de denegación de servicio contra un sitio web concreto.
Establecer estándares en un sistema P2P es una tarea compleja.
Para algunas tareas especícas, la carga de trabajo no se puede compartir entre los
peers.
Resulta una tarea complicada que los usuarios de un sistema lleguen a obtener
benecios económicos de una red P2P.
6
1. Introducción
Un
peer
abandona el sistema de acuerdo a lo que haga su propietario con él. Por
eso, no se puede garantizar que un recurso en particular esté disponible siempre,
exceptuando algunas redes P2P diseñadas a tal n. Por ejemplo, el propietario
puede apagar su computador o borrar un archivo. Por tanto, es difícil predecir el
rendimiento total del sistema.
También es una tarea complicada prevenir el intercambio ilegal de material con
copyright.
Los sistemas P2P más populares pueden generar una gran cantidad de tráco en
la red. Por eso, por ejemplo, no se suele permitir el uso de este tipo de programas
en algunas facultades, ya que el rendimiento de la red descendería en gran medida.
1.2.3.
Clientes de redes P2P
De acuerdo a [4, 5], uno de los clientes P2P más populares en la actualidad es `eMule'.
Ya que las diversas redes P2P de compartición de archivos existentes no son capaces de
comunicarse entre sí, es necesario ser cuidadoso con el cliente que se elige. Se puede optar
por escoger un cliente el cual disponga de acceso a una red muy grande, o algún cliente
que sea capaz de conectarse a varias redes al mismo tiempo.
Algunos de los clientes P2P más populares en la actualidad son `Gnutella', `Bittorrent',
o `eMule', aunque existen otros muchos clientes más. Es necesario destacar que es el cliente
el que se conecta a la red P2P, pero esto no signica que sea el único que pueda hacerlo.
En otras palabras y, poniendo de base un ejemplo, existen varios programas cliente que
son capaces de conectarse a la red `Gnutella'; estos pueden ser, por ejemplo, `Morpheus',
`BearShare', `LimeWire', etc.
Aquí es donde juega un papel fundamental el cliente `eMule'. Dicho cliente no es más
que una interfaz que hace uso de la red P2P `eDonkey'. Al igual que otros clientes, es
capaz de buscar archivos, descargárselos y poder compartirlos con los demás miembros
de dicha red. Asimismo, permite al usuario ser un miembro más de la extensa red P2P
de la cual `eMule' hace uso.
Como se puede ver en la Figura 1.4, `eMule' proporciona una interfaz en la que sus
funciones principales se aprecian con facilidad. Es por ello que, en la actualidad, sea uno
de los clientes más aceptados y utilizados por los usuarios de la red `eDonkey'.
Aunque otros protocolos han ido ganando terreno con el paso de los años, es innegable
que el protocolo `eDonkey' sigue siendo ampliamente utilizado.
Por tanto, dada su gran extensión, sería interesante disponer de un detector de anomalías que fuera capaz de mostrar cualquier comportamiento extraño que pudiera producirse
en el uso de protocolos P2P. De esta manera, se podrían evaluar dichos comportamientos y tomar decisiones acerca de la vulnerabilidad de un determinado computador ante
dichos comportamientos.
7
1. Introducción
Figura 1.4: Interfaz del cliente `eMule'.
Aquí es donde juega un importante papel la aplicación a desarrollar. Esta aplicación
se centra en el protocolo `eDonkey' que, como se ha detallado, es uno de los más utilizados en la actualidad. Dicho programa debe ser capaz de tomar como entrada ujos de
información en Internet, evaluar si pertenecen al protocolo `eDonkey' o no, y juzgar su
buen funcionamiento, tomando decisiones de si está funcionando con normalidad o no.
El objetivo es prevenir a las redes
peer-to-peer
de usos no autorizados.
1.3. El protocolo `eDonkey'
De acuerdo a [6, 7], el protocolo de compartición de cheros `eDonkey' es uno de los
protocolos para redes P2P más conocidos. En un principio se usó para el cliente llamado
`eDonkey2000' y, además, por algunos otros clientes de código abierto (open
source ) como,
por ejemplo, `mldonkey'. En algunos países, el protocolo `eDonkey' es el protocolo P2P
de compartición de archivos más popular entre todos los usuarios.
Muestra de ello son los resultados del estudio realizado en Alemania en 2007 por la
compañía `iPoque', que se puede consultar en [2], la cual obtuvo los resultados mostrados
en la Figura 1.5 acerca del porcentaje de uso de protocolos
peer-to-peer.
Básicamente, la red `eDonkey' es una red de compartición de archivos
peer-to-peer
que
usa aplicaciones cliente ejecutándose en los sistemas nales que están conectados a una
red distribuida o a servidores dedicados.
El protocolo `eDonkey' no está completamente descentralizado, ya que usa servidores
que ofrecen mecanismos para la comunicación.
8
1. Introducción
Figura 1.5: Porcentaje de uso de protocolos P2P en Alemania en 2007 (véase [2]).
A diferencia de otros protocolos P2P, la red `eDonkey' tiene una estructura basada en
el paradigma cliente/servidor (véase Capítulo 2). Los servidores no comparten ningún
archivo. El papel que juegan es manejar la distribución de la ubicación de la información
y operar con unos diccionarios centrales, que almacenan la información acerca de los
cheros que se comparten y sus respectivas localizaciones en los clientes.
En la red `eDonkey' los clientes son los únicos nodos que comparten recursos. Sus
archivos se indexan mediante los servidores. Si un cliente quiere descargarse un archivo
o parte de él, primero se debe conectar vía TCP a un servidor o enviar una petición de
búsqueda vía UDP a uno o más servidores para obtener la información necesaria acerca
de qué clientes ofrecen el archivo que se solicita.
La red `eDonkey' usa un
hash
MD4 de 16 bytes para identicar unívocamente a los ar-
hashing no es infalible (puede
hash implica que, en una búsque-
chivos, independientemente de su nombre. El algoritmo de
haber colisiones), pero ofrece una alta abilidad. Este
da, son necesarios un par de pasos previos. Primero, se le envía al servidor una orden
de búsqueda completa de texto con el nombre del archivo. La correspondiente respuesta
incluye aquellos archivos que tienen un nombre asociado el cual coincide completamente
con el texto que se mandó buscar. En segundo lugar, el cliente solicita las fuentes al
servidor para un determinado
hash
de un archivo. Finalmente, el cliente se conecta a
las fuentes indicadas para solicitar la transferencia del archivo. La transferencia de dicho
archivo tiene lugar directamente entre los dos clientes participantes, sin involucrar a los
servidores, para así minimizar el coste de la operación.
Un cliente que use el protocolo `eDonkey' es capaz de transferirse un único archivo de
múltiples fuentes, lo cual provoca que se mejore la velocidad de transferencia y se reduzca
el riesgo de quedarse con archivos sin transferirse del todo. Los archivos se transeren en
trozos de 9,28 MB. Los archivos que se transeren parcialmente también son compartidos
por el cliente y pueden transferirse a otros usuarios. El
hash
MD4 permite identicar si
un determinado chero es el que se está solicitando o no. Como en el protocolo `eDonkey'
se comparten los trozos de un archivo por separado, se pueden llegar a identicar aquellos
que están corruptos. Todas estas características hacen que el uso de este protocolo sea
ideal para transferir archivos grandes, como por ejemplo, archivos de vídeo.
9
1. Introducción
A continuación, se muestra una descripción general del funcionamiento del protocolo
`eDonkey'.
1.3.1.
Descripción general del protocolo `eDonkey'
Tal y como se dene en [9], la red `eDonkey' está formada por varios cientos de servidores y millones de clientes. Cada cliente está precongurado con una lista de servidores
y una lista de archivos compartidos en su sistema de archivos local y usa una única conexión a uno de los servidores mencionados para obtener información acerca del archivo
deseado y otros clientes disponibles. Dicho cliente `eMule' también puede utilizar varios
cientos de conexiones TCP a otros clientes los cuales suelen subir y bajar determinados
archivos. Cada uno de ellos mantiene una cola de subida para cada uno de los archivos
que comparte. Así, los clientes que deseen descargar algún tipo de archivo se unen a la
cola y se colocan al nal de esta, y van avanzando gradualmente hasta que alcanzan
la primera posición, que es cuando comienzan a descargar el archivo. Un cliente puede
descargar el mismo archivo de varios clientes `eMule', obteniendo así diferentes fragmentos de cada uno de ellos, y también puede subir un trozo de un archivo que aún no se
ha terminado de descargar. Finalmente, `eMule' amplía las capacidades de `eDonkey' y
permite a los clientes intercambiar información acerca de los servidores, de otros clientes
y de archivos. Nótese que ambos, cliente y servidor, se comunican mediante TCP.
El servidor emplea una base de datos interna en la cual almacena información acerca de
clientes y archivos. Un servidor `eMule' no almacena ningún archivo, sino que actúa como
una ocina de interconexión de clientes `eMule'. Una función adicional del servidor, la cual
se está volviendo obsoleta, es hacer un puente entre dos clientes que se conectan a través
de un cortafuegos y no son capaces de aceptar conexiones entrantes. La funcionalidad
de este puente incrementa considerablemente la carga en el servidor. `eMule' usa UDP
para mejorar las capacidades del cliente frente al servidor y otros clientes. La habilidad
de los clientes para enviar y recibir mensajes UDP no siempre está disponible, ya que no
es obligatoria para que dichos clientes funcionen correctamente. Por ello, uno de estos
clientes funcionaría perfectamente aunque un cortafuegos le impida enviar y recibir estos
mensajes UDP.
A continuación se mostrará una descripción detallada del proceso seguido en las conexiones realizadas por el protocolo `eDonkey' entre cliente-servidor y entre cliente-cliente.
Conexión cliente-servidor
Al inicio, el cliente se conecta a un servidor `eMule' usando una conexión TCP. El
servidor proporciona al cliente un ID de cliente que es válido sólo durante el tiempo
de vida de la conexión cliente-servidor. Siguiendo el establecimiento de la conexión, el
cliente envía al servidor su lista de archivos compartidos. El servidor almacena la lista
en su base de datos interna, la cual normalmente contiene cientos de miles de archivos
disponibles en sus clientes activos. El cliente `eMule' también envía su lista de descarga
que contiene los archivos que desea descargar en ese momento.
La red mostrada en la Figura 1.6 esquematiza la estructura de red que sigue `eMule',
10
1. Introducción
la cual no sigue la topología de una red convencional, sino que se trata de una red lógica
situada por encima de la red física (overlay
network ).
Los nodos están conectados entre
sí por enlaces lógicos, cada uno de los cuales está implementado por un camino a través
de enlaces físicos en la red subyacente.
Cada cierto tiempo, el cliente envía solicitudes de búsqueda de archivos que son respondidas mediante una búsqueda de resultados. Una transacción de búsqueda normalmente
va seguida de una petición de fuentes para un archivo especíco. Esta petición es contestada mediante una lista de fuentes (IP y puerto) de las que el solicitante puede descargar
el archivo.
Después de establecer la conexión, el servidor `eMule' envía al cliente una lista de
otros clientes que tienen los archivos que desea descargar el cliente que se conecta (dichos
clientes son llamados `fuentes'). Desde este punto, el cliente `eMule' comienza a establecer
conexiones con otros clientes. Nótese que la conexión TCP cliente-servidor se mantiene
abierta durante toda la sesión del cliente. Después del intercambio inicial (handshake ),
las transacciones son provocadas principalmente por la actividad de los usuarios.
El protocolo UDP se usa para comunicaciones con otros servidores que no son el
servidor al cual está conectado el cliente en ese momento. El propósito de los mensajes
UDP es la mejora de la búsqueda de archivos, la mejora de la búsqueda de fuentes y,
nalmente, el envío de mensajes
keep-alive
(asegurarse de que todos los servidores `eMule'
de la lista de servidores del cliente son válidos).
Figura 1.6: Estructura de la red `eMule' (protocolo `eDonkey').
11
1. Introducción
Conexión cliente-cliente
Un cliente `eMule' se conecta a otro (una fuente) con la nalidad de descargar un
archivo, el cual está dividido en partes fragmentadas. Dicho cliente puede descargarse el
mismo archivo de varios clientes, obteniendo así distintos fragmentos de cada uno.
Cuando dos clientes se conectan, intercambian información de capacidad y negocian
el comienzo de una descarga (o subida, depende de la perspectiva). Cada cliente tiene
una cola de subida en la cual mantiene una lista de clientes que están esperando para
descargar determinados archivos. Cuando esta cola está vacía, una petición de descarga
dará como resultado más probable un comienzo de descarga inmediato (a menos que,
por ejemplo, el solicitante esté prohibido). Pero cuando la cola de descarga no está vacía,
la solicitud de descarga dará como resultado la adición del cliente solicitante a la cola.
Sólo se da servicio a unos pocos clientes en un momento dado, proporcionando para cada
uno de ellos un ancho de banda mínimo de 2.4 KB/seg. Uno de los clientes que esté
descargando un archivo puede ser reemplazado por otro cliente que estaba esperando y
que tenga un mayor
ranking
en la cola que él.
Cuando un cliente que desea descargar algún chero alcanza la primera posición de la
cola, el cliente que posee dicho chero inicia una conexión con él, con el n de enviarle las
partes del archivo que necesita. Un cliente `eMule' puede estar al mismo tiempo esperando
en las colas de otros clientes para descargar las mismas partes del archivo de cada uno de
ellos. Cuando el cliente solicitante termina de descargarse las partes correspondientes (de
uno de los otros clientes), no le notica al resto que le eliminen de sus colas; lo que hace
es, simplemente, rechazar que le envíen el archivo cuando alcance la primera posición en
las otras colas.
`eMule' emplea un sistema de crédito con el n de promover las subidas de archivos.
Para evitar la suplantación de identidad, `eMule' asegura el sistema de crédito usando
criptografía de clave pública RSA.
Las conexiones de los clientes pueden usar un conjunto de mensajes no denidos por
el protocolo `eDonkey'. Dichos mensajes son una ampliación del protocolo. El protocolo
extendido se usa para la implementación del sistema de crédito, para intercambio general
de información (tales como actualización de la lista de servidores y fuentes) y para mejorar
el rendimiento mediante el envío y la recepción de fragmentos de archivo comprimidos.
La conexión del cliente `eMule' utiliza UDP de una manera limitada para, periódicamente, comprobar el estado del cliente en la cola de subida de sus clientes
peer
mientras
está esperando para descargarse un archivo.
1.3.2.
ID del cliente
El ID del cliente es un identicador de 4 bytes que es proporcionado por el servidor
cuando realizan un intercambio de tramas con el objetivo de ponerse de acuerdo (conocido como
handshake ).
Este ID es válido sólo durante el tiempo de vida de una conexión
TCP cliente-servidor aunque, en el caso de que el cliente tenga un ID alto, todos los
servidores le asignarán el mismo ID, a no ser que cambie su IP. Los ID de los clientes
están divididos en ID bajos e ID altos. El servidor `eMule' típicamente asignará a un
12
1. Introducción
cliente un ID bajo cuando este no pueda aceptar conexiones entrantes. Tener un ID bajo
restringe el uso que hace el cliente de la red `eMule' y podría resultar en que el servidor
rechazara la conexión del cliente. Un ID alto se calcula en base a la dirección IP de un
cliente, tal y como se describe a continuación.
Un ID alto se le da a los clientes que permiten a otros clientes conectarse libremente
al puerto TCP de `eMule' de su host. Un cliente con un ID alto no tiene restricciones
en el uso de la red `eMule'. Cuando el servidor no puede establecer una conexión TCP
con el puerto del cliente de `eMule', entonces a este cliente se le asigna un ID bajo, lo
que suele ocurrir principalmente con los clientes que tienen un cortafuegos que restringe
las conexiones entrantes. Un cliente también puede recibir un ID bajo en los siguientes
casos:
Cuando el cliente está conectado a través de NAT o un servidor proxy.
Cuando el servidor al que se conecta el cliente está muy ocupado (provocando así
que el contador de reconexión con el servidor expire).
Los ID altos se calculan de la siguiente manera: si se asume que la dirección IP del host
es X.Y.Z.W, entonces su ID será X + 2^8 * Y + 2^16 * Z + 2^24 * W (representación
big endian). Un ID bajo es siempre menor que la cifra 16777216 (0x1000000).
Un cliente con un ID bajo no tiene IP pública a la cual se puedan conectar otros
clientes, por lo que todas las conexiones se deben realizar a través del servidor `eMule',
es decir, el servidor indica al cliente con ID bajo que realice una conexión saliente con el
otro cliente que desea conectar con él. Esto aumenta la carga computacional del servidor
y provoca que no suelan aceptar clientes con un ID bajo. Además, esto signica que un
cliente con un ID bajo no puede conectarse con otro cliente que también tenga ID bajo
y que esté en otro servidor.
Para que en `eMule' se soportaran los clientes con ID bajo, se introdujo un mecanismo
de
callback. Mediante este mecanismo, un cliente con ID alto solicita, a través del servidor
`eMule', que un cliente con ID bajo se conecte a él, con el n de intercambiar determinados
archivos, ya un cliente con ID bajo no admite conexiones entrantes (véase Apartado 3.1.1).
1.3.3.
ID del usuario
`eMule' soporta un sistema de crédito con el n de animar a los usuarios a compartir archivos. Cuantos más archivos transera un usuario a otros usuarios, más créditos
recibirá y más rápido ascenderá en las colas de espera de otros clientes.
º
º
El ID de usuario es un GUID de 16 bytes (128 bits) que se crea concatenando números
aleatorios. El 6
y el 15
no son aleatorios; sus valores son 14 y 111 respectivamente.
Mientras que un ID de cliente es válido sólo durante una sesión de un cliente con un
servidor especíco, un ID de usuario (también llamado
hash
de usuario) es único y se
usa para identicar a un cliente a través de diferentes sesiones (el ID de usuario identica la estación de trabajo). Este ID juega un papel importante en el sistema de crédito;
esta característica proporciona a los
hackers
una motivación para suplantar la identidad
de otros usuarios con el n de adquirir sus privilegios, obtenidos gracias a sus créditos.
13
1. Introducción
`eMule' soporta un esquema de cifrado que se diseñó para prevenir fraudes y suplantaciones de identidad de otros usuarios. La implementación es un simple intercambio de
reto-respuesta que tiene un cifrado RSA de clave pública/privada.
Cuando un cliente envía un chero a su
peer, el cliente que descarga el archivo actualiza
su sistema de crédito de acuerdo a la cantidad de datos transmitidos. Nótese que el
sistema de crédito no es global; el crédito de una transferencia lo mantiene localmente
el cliente que descarga, y se tendrá en cuenta únicamente cuando el cliente que envía el
archivo (el que gana el crédito) realiza una petición de descarga a ese cliente especíco.
El crédito se calcula como el mínimo entre:
1.
2.
totalsubido∗2
totalbajado . Cuando la descarga es cero, a la expresión se le asigna el valor 10.
√
totalsubido + 2.
Cuando el total de subida sea menor que 1 MB, la expresión
toma el valor 1.
La cantidad de subida o bajada se calcula en megabytes. En cualquier caso, el crédito
no puede exceder de 10 ni ser menor que 1.
1.3.4.
ID del archivo
Los ID de los archivos se usan tanto para identicar unívocamente archivos en la red,
como para detectar y recuperar archivos corruptos. Nótese que `eDonkey' no utiliza el
nombre del archivo para identicarlo unívocamente y catalogarlo; un archivo se identica con un ID único creado mediante el
hashing
de su contenido. Los ID se utilizan
principalmente por dos motivos:
Generar un ID único para el archivo.
Detección y recuperación de partes corruptas.
Los archivos están identicados unívocamente por un
hash
GUID de 128 bits, calculado
por el cliente y basado en el contenido del chero. Este GUID se calcula aplicando el
algoritmo MD4 a los datos de los archivos. Cuando se calcula el ID del archivo, dicho
archivo se divide en partes, cada una de 9.28 MB. Se calcula un GUID por separado
de cada parte y luego todos los
hash
se combinan para obtener un ID de archivo único.
Cuando un cliente que está descargando algo completa la descarga de una parte del
archivo, calcula el
ha enviado su
hash
peer.
de esta parte y lo compara con el
hash
de esa parte que le
Si la parte está corrupta, entonces el cliente intentará recuperarla
sustituyendo bits gradualmente (180 KB) hasta que los
El
hash
hash
sean los mismos.
principal (raíz) se calcula con cada parte del chero, usando el algoritmo SHA-
1, basado en bloques de 180 KB de tamaño. Proporciona un nivel mayor de abilidad y
recuperación de fallos.
1.3.5.
Límites blandos y duros
La conguración del servidor incluye dos tipos de límites en el número de usuarios
activos, los llamados límites blandos y límites duros . El límite duro es mayor o igual al
14
1. Introducción
límite blando. Cuando el número de usuarios activos alcanza el límite blando, el servidor
deja de aceptar clientes nuevos si tienen un ID bajo. Cuando la cuenta de usuarios alcanza
el límite duro, entonces el servidor está completo y no acepta la conexión de ningún cliente
más.
1.3.6.
¾Cómo selecciona `eMule' qué parte de archivo descargar?
`eMule' selecciona selectivamente el orden en el que se descargan las partes con el
objetivo de maximizar la tasa de transferencia global y los archivos compartidos. Cada
archivo está dividido en partes de 9.28 MB y cada parte está dividida en bloques de 180
KB. El orden en el que se descargan las partes lo determina el cliente que descarga, el
cual envía mensajes de solicitudes de partes concretas del archivo. Dicho cliente puede
descargar una única parte de cada fuente en un momento determinado, y todos los bloques
que son solicitados de la misma fuente residen en la misma parte. La prioridad (o
rating)
de descarga de las partes sigue los siguientes principios (en el orden en que aparecen):
1. La frecuencia de los trozos (disponibilidad), ya que los trozos más raros se descargan lo más rápidamente posible para ser una nueva fuente disponible.
2. Las partes que se usan para la previsualización (primer y último trozo), comprobación de un chero (p. ej., mp3, película).
3. Solicitud de estado (con una descarga en proceso), se intenta solicitar a cada fuente
un trozo diferente. Así se extienden las solicitudes entre todas las fuentes.
4. Completitud (el más inminente en completarse), los trozos recuperados parcialmente deberían completarse antes de comenzar a descargar uno nuevo.
El criterio de frecuencia dene tres zonas: común, raro y muy raro. Dentro de cada
zona, el criterio tiene un peso especíco, usado para calcular los
Las partes con menos
de
rating
0-9999
rating
ratings
de las partes.
se descargan primero. La siguiente lista especica los rangos
de los archivos, de acuerdo a los principios denidos más arriba:
partes muy raras no solicitadas o solicitadas.
10000-19999 previsualizaciones de partes y partes raras no solicitadas.
20000-29999 la mayoría de las partes comunes no solicitadas y completas.
30000-39999 previsualizaciones de partes y partes raras solicitadas.
40000-49999 partes comunes no completadas y solicitadas.
Este algoritmo normalmente selecciona primero las partes más raras. Sin embargo, las
partes parcialmente completadas que están cerca de completarse pueden ser seleccionadas preferentemente también. Para las partes comunes, las descargas se extienden entre
fuentes diferentes.
15
1. Introducción
1.3.7.
Características generales de la codicación de mensajes del
protocolo `eDonkey'
Todos los mensajes se codican como
little-endian
y no en
big-endian,
aunque este
último sea el orden convencional de bytes en redes. Esto se puede explicar sencillamente
por el hecho de que los clientes y/o servidores son aplicaciones basadas en
Windows
y corriendo en procesadores
Intel.
Microsoft
Todos los mensajes tienen, al menos, 6 bytes de cabecera. Algunos tendrán bytes adicionales conteniendo cierta información, dependiendo del tipo de mensaje que contienen.
La cabecera sigue la siguiente estructura (véase Figura 1.7):
Protocolo: Un único byte indicando el ID del protocolo, que es 0xE3 para `eDonkey' y
0xC5 para `eMule'.
Tamaño:
cuatro bytes indicando el tamaño del mensaje, sin incluir la cabecera. Por
ejemplo, en caso de que el mensaje no incluya carga útil (payload ) entonces
el tamaño será cero.
Tipo:
Un byte indicando el tipo. Un único mensaje con un ID.
1.4. Justicación del proyecto
En los apartados anteriores se ha puesto de maniesto que las redes P2P son ampliamente utilizadas en la actualidad, ya que poseen ciertas propiedades que una red
convencional no tiene. También se ha hecho mención al protocolo para redes
peer-to-peer
`eDonkey', uno de los más ampliamente utilizados en este tipo de redes, así como sus
características principales y su funcionamiento general.
Resulta evidente que garantizar la seguridad en las redes de comunicación es uno de los
puntos más importantes que las conciernen. Por ello, es necesario aportar mecanismos
de seguridad tales como contraseñas, cortafuegos o control de los registros de acceso
a las mismas ya que, sin estas medidas, gran cantidad de información se podría ver
comprometida.
Figura 1.7: Estructura de una trama del protocolo `eDonkey'.
Una de las herramientas existentes en la actualidad que forman parte de la seguridad
en redes de comunicación son los llamados Sistemas de Detección de Intrusiones (IDS,
Intrusion Detection Systems ), como se puede consultar en [8]. Dichos sistemas se utilizan
para detectar accesos no autorizados a una red o a un computador en particular. Los
IDS de red incorporan mecanismos para analizar el tráco de la red o de un sistema en
concreto y alertar cuando se produce algún tipo de comportamiento extraño.
Una de las categorías en las que se pueden dividir los IDS de acuerdo a su modelo
de detección es aquella en la que se detecta un comportamiento anómalo dentro del
16
1. Introducción
tráco analizado (detección de anomalías). Para ello, este tipo de IDS obtiene estadísticas
sobre el tráco típico en la red, se detectan cambios en los patrones de utilización o
comportamiento del sistema y se utilizan modelos estadísticos y se buscan desviaciones
estadísticas signicantes.
Sería, por tanto, una herramienta útil un IDS que sea capaz de analizar tráco P2P y
que fuera del tipo de IDS que alerten de alguna clase de anomalía cuando sea detectada. De esta manera, se está alertando al usuario cuando se detecta en dicho tráco un
comportamiento no habitual.
El objetivo de este proyecto es el desarrollo de una aplicación que haga las funciones de
un IDS capaz de detectar anomalías en tráco
peer-to-peer
y mostrar resultados acerca
del tráco no reconocido. Dado el amplio uso del protocolo `eDonkey' en la actualidad,
se ha decidido centrar el IDS en dicho protocolo. Para implementar los mecanismos de
detección de anomalías, se ha optado por el uso de técnicas basadas en autómatas de
estados nitos, que se describen en el Capítulo 2.
La memoria seguirá la siguiente estructura:
Capítulo 2: Se describirán los fundamentos tecnológicos necesarios para conocer cómo funcionan los autómatas de estados nitos, ya que son utilizados en el modelado
del protocolo `eDonkey'. También se explicará en qué consiste el paradigma clienteservidor, puesto que es este paradigma el utilizado en el protocolo mencionado. Por
último, se detallará cómo realizar el modelado de protocolos con autómatas de estados nitos y una serie de herramientas y utilidades adicionales que serán prácticas
de cara a la elaboración de la aplicación.
Capítulo 3: En este capítulo se describirá la estructura general y las funcionalidades
que ha de tener la aplicación a desarrollar para poder detectar anomalías en un
protocolo P2P. Asimismo, se mostrará el análisis del funcionamiento del protocolo
`eDonkey' y se realizará su modelado con autómatas de estados nitos, puesto que
la aplicación necesitará esta información para poder funcionar correctamente.
Capítulo 4: Se describirá la estructura de la aplicación con un nivel de detalle mayor, para poder comprender su funcionamiento. Se desglosará dicha estructura en
módulos y se explicará la misión de cada uno de ellos, así como el funcionamiento
global de la aplicación mediante dichos módulos. Se detallará también la jerarquía de clases utilizadas, que han hecho posible la elaboración de los módulos ya
mencionados.
Capítulo 5: Aquí se realizará la evaluación de la aplicación en dos bloques. El primero de ellos será la comprobación del buen funcionamiento de la aplicación mediante
cheros con trazas de tráco, los cuales han sido adquiridos en diferentes escenarios
pertenecientes al protocolo `eDonkey'. El segundo bloque verica la eciencia de la
aplicación, mediante diferentes mediciones de tiempos y análisis de los cuellos de
botella de la aplicación.
Capítulo 6: Se mostrará la planicación inicial que se realizó al inicio del proyecto
y el desglose de tareas a llevar a cabo. También se mostrará la evaluación de costes
17
1. Introducción
asociados al desarrollo de la aplicación.
Capítulo 7: Por último, se mostrarán una serie de conclusiones y logros nales, a
los cuales se ha llegado durante el desarrollo y estudio de la aplicación.
18
Capı́tulo
2
Fundamentos tecnológicos
Tal y como se ha comentado en el Capítulo 1, en este proyecto se aborda la implementación de un sistema de detección de intrusiones (IDS) diseñado para la detección de
anomalías en protocolos P2P y, más concretamente, para el protocolo `eDonkey'. Aunque existen numerosas técnicas disponibles para este tipo de análisis, se ha optado por
la utilización de autómatas de estados nitos con el n de explorar sus posibilidades en
este campo.
Para realizar esta tarea, es necesario conocer ciertos fundamentos de teoría de autómatas de estados nitos y también del paradigma cliente-servidor, ya que éste es intrínseco al
protocolo que se va a estudiar y a todos los protocolos P2P en general. También se incluye
una sección que ayuda a entender cómo se puede realizar un modelado del comportamiento del protocolo mediante autómatas de estados nitos. Por último, se muestra una
sección de herramientas y utilidades, en la cual se exponen las bibliotecas más relevantes,
de las cuales hará uso la aplicación, y otros programas útiles.
2.1. Teoría de autómatas de estados nitos
El diagrama de transición de un autómata de estados nitos es un grafo en el que los
nodos representan los distintos estados y los arcos las transiciones entre los estados. Un
autómata está formado por uno o más estados. Cada arco va etiquetado con un símbolo
asociado a dicha transición. Para facilitar la visualización del diagrama de transición,
el estado inicial y los nales vienen señalados de forma especial (por ejemplo, con un
ángulo el estado inicial y con un doble círculo los nales). En cada paso, el autómata
lee un símbolo de entrada y, según el estado en que se encuentre, cambia de estado y
pasa a leer el siguiente símbolo. Así sucesivamente hasta que termine de leer todos los
símbolos de entrada. Si en ese momento la máquina alcanza un estado nal, se dice que
el autómata acepta la secuencia de símbolos de entrada. Si no está en un estado nal, la
rechaza.
Para claricarlo, en la Figura 2.1 se muestra un ejemplo de autómata para crear frases
sencillas. Los estados son los círculos y las transiciones son las echas que los unen. Las
19
2. Fundamentos tecnológicos
transiciones están nombradas con el valor que debe recibir el autómata para transitar de
un estado a otro. Es decir:
Artículo: El, la, los, las, un, una, unos, unas.
Nombre: Cualquier nombre común.
Verbo: Cualquier verbo.
Adjetivo: Cualquier adjetivo.
Si, por ejemplo, se recibe la frase el coche es azul , este autómata la aceptaría, ya
que, el es un artículo, por lo que transitaría de
q0
a
q1 (q0
está marcado como estado
inicial); coche es un nombre común, por lo que transitaría de
así que se transitaría de
de
q3
a
q4 ,
q2
a
q3 ; y, por último, azul
q1
a
q2 ;
es es un verbo,
es un adjetivo, por lo que transitaría
que es un estado nal (marcado con un círculo doble), concluyéndose que el
autómata acepta la frase. Una palabra es cada uno de los términos de la frase que puede
hacer transitar a un autómata de un estado a otro.
Se pueden elaborar autómatas más complejos. Se muestra uno en la Figura 2.2, con
un bucle. Este aceptaría, por ejemplo, la frase: el coche es azul y está rayado , ya que,
en
q4
aceptaría la conjunción y y transitaría de
q4
a
q2 ;
y está rayado son un verbo
y un adjetivo, que le harían llegar al estado nal (puede haber más de uno).
Como se puede apreciar, los autómatas son útiles para modelar un determinado comportamiento. Por ello, se pueden utilizar como herramienta para modelar protocolos, ya
que se puede representar este comportamiento.
Figura 2.1: Autómata de ejemplo.
Figura 2.2: Autómata de ejemplo.
20
2. Fundamentos tecnológicos
2.1.1.
Autómatas de estados nitos determinísticos
Como se explica en [10], un autómata de estados nitos determinístico (AFD) es aquel
cuyo estado nal está determinado unívocamente por el estado inicial y los símbolos
observados por el autómata. Está formado por una quíntupla
M = (Q, A, δ, q0 , F )
en la
que:
Q es un conjunto nito llamado conjunto de estados.
A es un alfabeto (conjunto de símbolos observables) llamado alfabeto de entrada.
δ es una aplicación
δ(Q) : Q × A → Q
q0
llamada función de transición:
es un elemento de Q, llamado estado inicial.
F es un subconjunto de Q, llamado conjunto de estados nales.
Un ejemplo de autómata nito determinista es el mostrado en la Figura 2.3, en el que
los elementos de la quíntupla serían los siguientes:
Q = {q0 , q1 , q2 }
A = {a, b}
Función de transición:
δ(q0 , a) = q0
δ(q0 , b) = q1
δ(q1 , a) = q2
δ(q1 , b) = q1
δ(q2 , a) = q2
δ(q2 , b) = q2
Estado inicial =
q0
F = {q0 , q1 }
2.1.2.
Autómatas de estados nitos no determinísticos
Un autómata nito no determinístico (AFND) es aquel en el que existe al menos un
estado en el que es posible más de una transición para el mísmo símbolo. Dicho de otra
forma, un AFND es aquel en el que, dada una secuencia de símbolos observables, el estado
nal y/o la secuencia de estados seguidos por el autómata no es predecible (unívoca).
Queda denido por una quíntupla
M = (Q, A, δ, q0 , F )
en que:
Q es un conjunto nito llamado conjunto de estados.
A es un alfabeto (conjunto de símbolos observables) llamado alfabeto de entrada.
21
2. Fundamentos tecnológicos
Figura 2.3: Ejemplo de AFD.
δ es una aplicación llamada
δ(Q) : Q × A → ℘(Q × A)
q0
función de transición:
es un elemento de Q, llamado estado inicial. Puede haber varios estados iniciales.
F es un subconjunto de Q, llamado conjunto de estados nales.
Una secuencia de observaciones se dice aceptada por un AFND si, siguiendo en cada
momento alguna de las opciones posibles, se llega a un estado nal.
En la Figura 2.4 se muestra un ejemplo de AFND. Por ejemplo, en
q0
se puede recibir
el símbolo `a' y llevar a varios estados diferentes según la función de transición
δ.
Los
elementos de la quíntupla serían los siguientes:
Q = {q0 , q1 , q2 }
A = {a, b, c}
Función de transición:
δ(q0 , a) = {q0 , q1 , q2 }
δ(q0 , b) = {q1 , q2 }
δ(q0 , c) = {q2 }
δ(q1 , a) = Ø
δ(q1 , b) = {q1 , q2 }
δ(q1 , c) = {q2 }
δ(q2 , a) = Ø
δ(q2 , b) = Ø
δ(q2 , c) = {q2 }
Estado inicial =
q0
F = {q0 , q1 , q2 }
22
2. Fundamentos tecnológicos
Figura 2.4: Ejemplo de AFND.
2.2. Paradigma cliente-servidor
La comunicación entre cliente y servidor se puede realizar con el protocolo TCP o con
UDP, mediante el establecimiento de una conexión. Mediante una conexión, dos entidades
se ponen de acuerdo para realizar un determinado intercambio de datos, como se verá
más adelante. Es necesario destacar que este concepto sólo es aplicable al protocolo TCP,
ya que UDP es no orientado a conexión y, por tanto, no se necesita una conexión previa.
Sin embargo, de aquí en adelante, en el contexto UDP se entenderá que dos entidades
intercambiarán información dentro de una conexión.
Para poder analizar los mensajes intercambiados en el protocolo, es necesario extraerlos
primero, de modo que, la forma de observar estos mensajes P2P entre dos
peers, consiste
en extraer los datos de la conexión mediante la identicación de las duplas IP/puerto. El
peer
que inicie la conexión será el cliente y el que recibe esta conexión entrante será el
servidor. Este es el procedimiento utilizado en este proyecto para extraer los mensajes.
Una comunicación TCP o UDP está determinada por los siguientes elementos:
IP origen.
IP destino.
Puerto origen.
Puerto destino.
Dentro de una comunicación TCP o UDP existen ujos de información, producto
del diálogo entre dos
peers.
Un ujo es el intercambio de información que realizan dos
entidades, dentro de una conexión. Nótese que dentro de una misma conexión pueden
aparecer varios ujos diferentes, debido a los mensajes intercambiados entre los dos
peers.
Para claricar estos conceptos, supóngase la situación de la Figura 2.5. En ella se muestra
una supuesta conexión entre dos computadores. Para cada uno de ellos, se muestra la IP
y el puerto.
23
2. Fundamentos tecnológicos
Figura 2.5: Ejemplo de conexión entre dos computadores cualesquiera.
Supóngase ahora que los computadores mostrados en la Figura 2.5 son un cliente y
un servidor en una red P2P, que intercambian cierta información. Considérese que la
conexión entre los dos computadores permanece abierta durante un tiempo prolongado.
Durante este tiempo, el cliente y el servidor pueden intercambiar, por ejemplo, la información correspondiente a un establecimiento de conexión. Dicho establecimiento de
conexión se correspondería con un ujo de información. De la misma manera, durante esta conexión, posteriormente puede haber un intercambio de información correspondiente
a una búsqueda de archivos, que se correspondería con otro ujo. Por tanto, durante la
conexión, ha habido dos ujos de información.
Dada la naturaleza P2P del protocolo `eDonkey', es obvio que hace uso del modelo
cliente-servidor. Un servidor es una aplicación que permite el acceso remoto a ciertos
recursos software o hardware que existen en un host determinado, como se explica en
[11]. Una aplicación servidora se caracteriza por encontrarse inicialmente en un estado
latente de escucha sin realizar ninguna función, hasta que recibe una solicitud remota
para desarrollar un servicio ofertado por parte de un cliente. Un cliente es una aplicación
a través de la cual un usuario contacta con un servidor con el n de llevar a cabo el
desarrollo de un servicio concreto que se oferta.
Es a través de la consideración del estado de escucha de la parte servidora cómo
el paradigma cliente-servidor permite resolver de forma sencilla el problema conocido
como
rendez-vous,
el cual hace referencia a la sincronización a priori necesaria en la
inicialización de dos aplicaciones de usuario para hacer posible la comunicación entre
ellas.
Un servicio que sigue el modelo cliente-servidor se desarrolla en los siguientes pasos:
Inicialmente debe ejecutarse la aplicación servidora, pasando esta a modo de escucha y quedando a la espera de recibir solicitudes de servicio. Es lo que se conoce
como puesta en marcha pasiva del servicio.
La ejecución de la aplicación cliente dará lugar al envío de una solicitud de servicio
hacia el servidor. Esto supone una puesta en marcha activa del servicio.
El servidor responderá a dicha solicitud de acuerdo con la aplicación desarrollada,
llevándose a cabo el intercambio de información necesario para hacer efectivo el
servicio.
Tras el desarrollo de dicho servicio, el servidor volverá al estado de escucha a la
espera de nuevas solicitudes. Por otro lado, el cliente nalizará su ejecución.
24
2. Fundamentos tecnológicos
Características del cliente:
Los clientes comparten una serie de características, las
cuales son:
Son invocados por el usuario.
Inician el contacto con el servidor.
Pueden comunicarse con:
ˆ
ˆ
ˆ
Varios servidores alternativamente.
Varios servidores simultáneamente.
El mismo servidor concurrentemente.
Características del servidor:
Los servidores también tienen una serie de propiedades
comunes:
Esperan pasivamente la llegada de peticiones de clientes.
Pueden gestionar peticiones simultáneas de varios clientes, aunque no siempre es
así.
En la misma máquina pueden estar funcionando varios servidores de diferentes
servicios.
2.3. Modelado de protocolos con autómatas de estados
nitos
El comportamiento de protocolos puede ser modelado sin ambigüedad mediante las
indicaciones realizadas a continuación en esta sección y haciendo uso de las herramientas
anteriormente expuestas.
A modo de ejemplo, se supondrá el intercambio de tramas del protocolo `eDonkey' de
la Figura 2.6. En ella se puede apreciar que existen dos nodos en la red, con direcciones
IP1
e
IP2 ,
que intercambian tres tramas durante una conexión.
Para poder modelar este comportamiento mediante autómatas de estados nitos, se
ha de conocer el alfabeto a utilizar. Este alfabeto estará determinado por un campo
denominado tipo , existente en las tramas pertenecientes al protocolo `eDonkey'. Dicho
campo está formado por dos dígitos en hexadecimal, los cuales identican unívocamente
el tipo o naturaleza del mensaje. Por tanto, el intercambio de mensajes quedaría reducido,
por ejemplo, a lo mostrado en la Figura 2.7 y, en este caso, la información extraída de
las tramas intercambiadas (secuencia observable) es la mostrada en la Figura 2.8.
25
2. Fundamentos tecnológicos
Figura 2.6: Ejemplo de intercambio de paquetes entre dos nodos de una red P2P.
Figura 2.7: Ejemplo de información extraída en el intercambio de tramas entre dos nodos
en la red.
Entonces es posible que el intercambio de mensajes mostrado tenga algún signicado
concreto dentro del protocolo analizado. Por ejemplo, que impliquen un establecimiento
de conexión o una determinada solicitud propia del protocolo examinado. Con el objetivo
de comprobarlo, se puede elaborar un autómata asociado a ese ujo de información,
como se muestra en la Figura 2.9. En dicha Figura se puede observar cómo los mensajes
intercambiados entre los dos
peers
provocan que el autómata transite de un estado a
otro, hasta alcanzar un estado nal.
Siguiendo el procedimiento mostrado en este ejemplo, se podría modelar el comportamiento de cualquier protocolo y, en particular, los protocolos P2P, mediante autómatas
de estados nitos. En este proyecto se ha utilizado esta técnica para modelar el comportamiento del protocolo `eDonkey'. El análisis pertinente para derivar los correspondientes
autómatas se detalla en el Capítulo 3.
26
2. Fundamentos tecnológicos
2.4. Herramientas y utilidades
A continuación se muestran una serie de herramientas necesarias en el desarrollo de la
aplicación. Se han utilizado recursos disponibles para algunas de las funcionalidades necesarias. Del conjunto de bibliotecas de funciones utilizadas en la aplicación, se muestran
a continuación las más destacadas, así como una serie de programas prácticos.
Figura 2.8: Información extraída de tres tramas.
Figura 2.9: Ejemplo de modelado de protocolo con un autómata.
2.4.1.
Standard Template Library '
Biblioteca `
Esta biblioteca ha sido utilizada debido a las múltiples estructuras de datos que proporciona. Dichas estructuras de datos han resultado de utilidad en el desarrollo de los
autómatas de estados nitos, así como del almacén/clasicador de ujos utilizado (véase
Capítulo 4).
Como se indica en [13, 14], la Standard Template Library, también conocida como
STL, es una colección de estructuras de datos genéricas y algoritmos escritos en C++.
La STL no es la primera de tales bibliotecas, ya que la mayoría de los compiladores de
C++ proporcionan bibliotecas de funciones con una intención similar, y también están
disponibles muchas de ellas de tipo comercial. Uno de los problemas de las bibliotecas de
diferentes vendedores es que son incompatibles entre ellas, por lo que los programadores
están estudiando continuamente nuevas, y migrando de un proyecto a otro, y de un compilador a otro. La STL ha sido adoptada como un estándar por la International Standards
Organization, International Electrotechnical Commission (ISO/IEC) y por la American
National Standards Institute (ANSI), lo que signica que la STL es una extensión del
lenguaje que todos los compiladores soportan y está fácilmente disponible.
El concepto de STL está basado en la separación de datos y operaciones. Los datos
están manejados por clases de contenedores, mientras que las operaciones están denidas
por algoritmos congurables. Los iteradores son la unión entre estos dos componentes, ya
que permiten a los algoritmos interactuar con cualquier contenedor, tal y como se ilustra
en la Figura 2.10.
27
2. Fundamentos tecnológicos
Figura 2.10: Conexión entre los tres elementos principales de la STL.
En cierto modo, el concepto de STL contradice la idea original de la programación
orientada a objetos: la STL separa los datos y los algoritmos en vez de combinarlos. En
principio, se puede combinar todo tipo de contenedores con todo tipo de algoritmos, por
lo que el resultado es una extensión exible pero aún pequeña.
2.4.2.
Libpcap '
Biblioteca `
Mediante esta biblioteca ha sido posible la captura de tráco de un chero con trazas
de tráco o de una interfaz de red, así como el procesamiento de cada trama (véase
Capítulo 4).
La biblioteca de funciones `libpcap' (o `pcap'), como se detalla en [15], es un conjunto
de funciones de código abierto escritas en C con el objetivo de ofrecer al programador
una interfaz desde donde es posible capturar paquetes de la interfaz de red. `Libpcap'
tiene la ventaja de ser portable entre diferentes sistemas operativos y, además, ofrece una
serie de funciones sencillas de utilizar que cubren todos los requisitos deseables respecto
de la captura y gestión de tramas.
A continuación se muestran una serie de estructuras y métodos relevantes para el
manejo de esta biblioteca, que se utilizarán en la aplicación.
Principales estructuras utilizadas y funcionalidades
Información de interfaces.
lazada de estructuras
La llamada a
pcap_if (pcap_if
pcap_findalldevs,
pcap_if_t), en la
=
construye una lista encual se recoge toda la
información de cada una de las interfaces de red instaladas.
struct pcap_if
{
struct pcap_if * next; //enlace a la
interfaz
char * name; //nombre de la interfaz
char * description; //descripción de
struct pcap_addr * addresses;//lista
siguiente definición de
(eth0, wlan0...)
la interfaz o NULL
enlazada de direcciones
28
2. Fundamentos tecnológicos
};
asociadas a esta interfaz
u_int flags; //PCAP_IF_ interface flags
Una interfaz puede tener varias direcciones. Para contenerlas todas se crear una lista
con una estructura
pcap_addr
por cada una.
struct pcap_addr
{
struct pcap_addr * next; //enlace a la siguiente dirección
struct sockaddr * addr; //dirección
struct sockaddr * netmask; //máscara de red
struct sockaddr * broadaddr; //dirección de broadcast para
esa dirección
struct sockaddr * dstaddr; // dirección de destino
};
Estadísticas.
Mediantes la llamada a
pcap_stats se obtiene la siguiente estructura con
información estadística.
struct pcap_stat
{
u_int ps_recv; //número de paquetes recibidos
u_int ps_drop; //número de paquetes no procesados
u_int ps_ifdrop; //paquetes no procesados por cada interfaz
(aún no soportado)
};
Paquetes.
Cada paquete del
dump_file
(archivo donde se encuentran tramas almace-
nadas) va precedido por esta cabecera genérica, de modo que un mismo chero puede
contener paquetes heterogéneos.
struct pcap_pkthdr
{
struct timeval ts; //timestamp (marca de tiempo)
bpf_u_int32 caplen; //tamaño del paquete al ser capturado
bpf_u_int32 len; //tamaño real del paquete en el fichero;
};
struct pcap_file_header
{
bpf_u_int32 magic;
u_short version_major;
u_short version_minor;
bpf_int32 thiszone; //correción de GMT a local
29
2. Fundamentos tecnológicos
};
bpf_u_int32 sigfigs; //precisión de los timestamps
bpf_u_int32 snaplen; //tamaño máximo salvado de cada paquete
bpf_u_int32 linktype; //tipo de dataLink
La estructura `pcap_t'.
La estructura
pcap_t, que aparece en numerosas funciones, es
una estructura opaca para el usuario. Por lo tanto no es necesario detallar el contenido;
sólo es necesario conocer que `libpcap' almacena en este tipo de estructura el valor de
ciertas variables internas.
Métodos para obtener información del sistema
int pcap_lookupnet(char * device, bpf_u_int32 * netp,
bpf_u_int32 * maskp, char * errbuf)
Una vez obtenido el nombre de una interfaz válida, es posible consultar su dirección
de red (diferente a su dirección IP) y su máscara de subred. El parámetro device es un
puntero a un vector de caracteres que contiene el nombre de una interfaz de red válida,
netp y maskp son dos punteros a bpf_u_int32 en los que la función escribirá la dirección
de red y la máscara respectivamente. En caso de error la función devuelve -1 y una
descripción del error en errbuf.
Métodos para capturar paquetes
Existen varias funciones para capturar paquetes. Las principales diferencias entre ellas
son: el número de paquetes que se desea capturar, el modo de captura (normal o promiscuo) y la manera en que se denen sus funciones de llamada o
callbacks
(la función
invocada cada vez que se captura un paquete).
pcap_t * pcap_open_live(char * device, int snaplen, int promisc,
int to_ms, char * errbuf)
Antes de entrar en el bucle de captura hay que obtener un descriptor de tipo
para lo cual se emplea esta función. El primer parámetro (char
pcap_t,
* device) es el nombre
ANY o NULL fuerzan
del dispositivo de red en el que se desea iniciar la captura (los valores
la captura en todos los dispositivos disponibles).
El segundo argumento (int
El argumento
promisc
snaplen) especica el número máximo de bytes a capturar.
0 iniciara la
0 para modo normal.
indica el modo de apertura: un valor distinto de
captura en modo promiscuo,
Los programas basados en `libpcap' se ejecutan en la zona de usuario pero la captura
en sí se realiza en la zona del núcleo. Se hace por lo tanto necesario un cambio de
área. Estos cambios son muy costosos y es necesario evitarlos si se quiere optimizar
el rendimiento, por eso esta función permite especicar mediante el parámetro
to_ms
30
2. Fundamentos tecnológicos
cuántos milisegundos se desea que el núcleo agrupe paquetes antes de pasarlos todos
NULL,
errbuf.
simultáneamente a la zona de usuario. Si la función devuelve
un error y puede encontrarse una descripción del mismo en
se habrá producido
int pcap_loop(pcap_t * p, int cnt, pcap_handler callback,
u_char * user)
Esta función se utiliza para capturar y procesar los paquetes. El parámetro
dica el número máximo de paquetes a procesar antes de salir;
capturar indenidamente. El siguiente parámetro,
callback,
cnt = -1
cnt
in-
se usa para
es un puntero a la función
que será invocada para procesar el paquete. Para que un puntero a función sea de tipo
pcap_handler,
debe recibir unos parámetros:
u_char:
Puntero
Estructura
Es un puntero al propio paquete.
pcap_pkthdr.
-1 en caso de error, en cuyo
pcap_geterr() para mostrar un
La función devuelve el número de paquetes capturados o
caso se puede emplear las funciones
pcap_perror()
y
mensaje más descriptivo de dicho error. En caso de error se devolverá un número negativo
o
0
si el número de paquetes especicados por cnt se ha completado con éxito.
Métodos para manejar ltros
Un ltro es una cadena que dene los paquetes que va a capturar y procesar la interfaz
de red. Su principal uso es para librar al núcleo (kernel ) de carga de trabajo.
int pcap_compile(pcap_t * p, struct bpf_program * fp, char * str,
int optimize, bpf_u_int32 netmask)
Esta función se emplea para compilar un programa de ltrado (char
BPF equivalente (bpf_u_int32
netmask).
* str)
en su
Es posible que durante la compilación, el programa original se modique para optimizarlo. El parámetro netmask es la máscara de la red local, que puede obtenerse
llamando a
pcap_lookupnet. En caso de que la función devuelva -1, se habrá producido
un error. Para una descripción más detallada de lo sucedido se puede emplear la función
pcap_geterr().
int pcap_setfilter(pcap_t * p, struct bpf_program * fp)
Una vez compilado el ltro sólo es necesario aplicarlo; para ello es suciente pasar
como parámetro a esta función el resultado de compilar el ltro con
En caso de error la función devolverá
llada del error con
pcap_geterr().
-1
pcap_compile.
y puede obtenerse una descripción más deta-
31
2. Fundamentos tecnológicos
Métodos para manejar cheros relacionados con la captura de tráco
pcap_open_offline(filename, errbuf)
Este método sirve para abrir un chero con paquetes ya guardados en formato
tcpdump
en modo lectura.
filename
Los parámetros son:
2.4.3.
NULL en
errbuf.
para indicar la ruta del chero, devuelve
de que la función falle. Para consultar la descripción del error, se utiliza
caso
Pthread '
Biblioteca `
Mediante esta biblioteca de funciones, ha sido posible la programación multihebrada
de la aplicación, permitiendo concurrentemente analizar ujos de varios cheros de red,
así como de interfaces de red. También ha sido fundamental para la extracción de ujos
del almacén/clasicador de ujos implementado, realizando esta tarea entre varias hebras
para liberar de carga a la hebra principal (véase Capítulo 4).
En arquitecturas de multiprocesadores con memoria compartida, tales como los SMP,
las hebras se pueden utilizar para implementar paralelismo, como se puede consultar
en [19]. Históricamente, los fabricantes de hardware tenían implementadas sus propias
versiones de hebras, convirtiendo así la portabilidad en un problema que concernía a
los desarrolladores de software. En los sistemas UNIX, se ha especicado una interfaz de
programación de hebras estandarizada en lenguaje C, mediante el estándar IEEE POSIX
1003.1c. Las implementaciones adheridas a este estándar se conocen como hebras POSIX
o Pthreads.
¾Por qué usar `Pthreads' ?
La principal motivación para usar Pthreads es para realizar programas con una
gran ganancia en rendimiento.
Cuando se compara con el coste de crear y mantener un proceso, una hebra puede
generarse con mucha menos sobrecarga por parte del sistema operativo.
Por ejemplo, la tabla mostrada en la Figura 2.11 compara los resultados en tiempo
fork() (crear un proceso hijo) y para la subrutina
pthread_create() (crear una hebra). Los tiempos reejan las creaciones de 50000
procesos/hebras, que se midieron mediante la utilidad time, en segundos, sin ningún
de cómputo para la subrutina
tipo de optimización.
Todas las hebras de un proceso comparten el mismo espacio de direcciones. La
intercomunicación entre hebras es más eciente en muchos casos y más fácil de
usar que la intercomunicación entre procesos.
Las aplicaciones programadas mediante hebras ofrecen una potencial ganancia en
rendimiento y ventajas frente a las aplicaciones sin hebras de otras maneras:
32
2. Fundamentos tecnológicos
Plataforma
real
sys
pthread_create()
real user sys
AMD 2.4 GHz Opteron (8 cpu/nodo)
41.07
60.08
9.01
0.66
0.19
0.43
IBM 1.9 GHz POWER5 p5-575 (8 cpu/nodo)
64.24
30.78
27.68
1.75
0.69
1.10
IBM 1.5 GHz POWER4 (8 cpu/nodo)
104.05
48.64
47.21
2.01
1.00
1.52
INTEL 2.4 GHz Xeon (2 cpu/nodo)
54.95
1.54
20.78
1.64
0.67
0.90
INTEL 1.4 GHz Itanium2 (4 cpu/nodo)
54.54
1.07
22.22
2.03
1.26
0.67
Figura 2.11: Costes en tiempo (aproximados) para
fork()
user
fork()
y
pthread_create().
Solapamiento de trabajo de la CPU con entrada/salida: Por ejemplo, un programa
puede tener secciones donde se lleve a cabo una larga operación de entrada/salida.
Mientras una hebra está esperando una llamada al sistema de entrada/salida para
completarse, el trabajo intensivo de la CPU lo pueden realizar otras hebras.
ˆ
ˆ
Programación con prioridades y/o en tiempo real: Las tareas que son más importantes pueden ser programadas para reemplazar o interrumpir otras tareas
con menor prioridad.
Manejo de eventos asíncronos: Las tareas cuyos eventos (de frecuencia y duración indeterminada) pueden estar entremezclados. Por ejemplo, un servidor
web puede transferir datos de una solicitud previa y manejar solicitudes nuevas
al mismo tiempo.
El motivo principal para considerar el uso de
Pthreads
en una arquitectura SMP
es para conseguir un rendimiento óptimo.
La API Pthread
La API Pthread se dene en el estándar ANSI/IEEE POSIX 1003.1 - 1995.
Las subrutinas que comprenden la API Pthread pueden agruparse informalmente
en tres clases principales:
ˆ
ˆ
Manejo de hebras: La primera clase de estas funciones trabaja directamente
con las hebras (creándolas, uniéndolas, etc.). También incluyen funciones para
establecer o consultar algún atributo de la hebra.
Mutexes: La segunda clase de estas funciones están relacionadas con la sincronización. El nombre es mutex debido a la abreviatura de
mutual exclusion.
Las funciones mutex proporcionan funcionalidades para crear, destruir, bloquear y desbloquear mutexes. También existen funciones relacionadas con los
atributos de dichos mutexes, las cuales pueden establecer un atributo nuevo o
ˆ
modicarlo.
Variables de condición: La tercera clase de funciones manejan comunicaciones
entre hebras que comparten un mutex. Están basadas en condiciones especicadas por el programador. Esta clase incluye funciones para crear, destruir,
33
2. Fundamentos tecnológicos
bloquear y desbloquear hebras en base a valores de variables especicados.
También se incluyen funciones para consultar o establecer atributos en las
variables de condición.
Convenciones de nombrado: Como se muestra en la tabla de la Figura 2.12, todos
los identicadores de la biblioteca de hebras comienzan por
La API Pthread contiene más de 60 subrutinas.
Debido a la portabilidad, la cabecera
pthread.h
pthread_.
se debe incluir en cada chero
fuente que utilice la biblioteca Pthread.
El estándar POSIX actual está denido en lenguaje C.
2.4.4.
Wireshark
Como se puede consultar en [17], wireshark es un analizador de paquetes de la red. Un
analizador de este tipo intentará capturar los paquetes de la red y mostrar los datos de
dichos paquetes lo más detalladamente posible.
Se podría decir que un analizador de paquetes de la red es un dispositivo medidor que
se usa para examinar qué está pasando dentro de un cable de red.
Algunos usos de Wireshark son:
Buscar problemas en la red por los administradores de redes.
Examinar problemas de seguridad por ingenieros en este campo.
Depurar implementaciones de protocolos por desarrolladores de software.
Estudiar el funcionamiento de un protocolo de red.
En este proyecto, esta herramienta será útil para analizar el funcionamiento del protocolo `eDonkey'.
Prejo de las rutinas
pthread_
pthread_attr_
pthread_mutex_
pthread_mutexattr_
pthread_cond_
pthread_condattr_
pthread_key_
Grupo funcional
Las propias hebras y subrutinas generales
Atributos de las hebras
Mutexes
Atributos de los mutexes
Variables de condición
Atributos de las condiciones
Claves de datos especícos de las hebras
Figura 2.12: Grupos funcionales de rutinas
Pthread.
34
2. Fundamentos tecnológicos
2.4.5.
Doxygen
Doxygen, como se puede consultar en [20], es un generador de documentación que
se utiliza para documentar múltiples lenguajes de programación, como pueden ser C++,
Java o Python, entre otros. Como es fácilmente adaptable, funciona en varias plataformas.
Doxygen es una herramienta para escribir documentación de referencia en el software.
Esta documentación se escribe aparte del código, y es relativamente fácil mantenerla actualizada. Doxygen puede crear referencias cruzadas entre el código y la documentación,
por lo que un lector de documentos puede desplazarse fácilmente hacia el código.
35
2. Fundamentos tecnológicos
36
Capı́tulo
3
Análisis
En este capítulo se aborda el análisis del proyecto. En él se detalla el modelado del protocolo `eDonkey' mediante autómatas de estados nitos, ya que es una parte fundamental
en el funcionamiento de la aplicación. También se detallan los requisitos y funcionalidades
de dicha aplicación, así como su estructura principal.
3.1. Procedimientos en el protocolo `eDonkey'
A continuación se detallan los procedimientos más relevantes del protocolo `eDonkey'
en base al intercambio de mensajes, con todos los diálogos mostrados, como se detalla en
[9]. El objetivo es derivar los autómatas de estados nitos correspondientes a cada uno
de los procedimientos del protocolo. Dichos procedimientos o diálogos se dividen en:
Comunicación TCP entre el cliente y el servidor:
ˆ
ˆ
ˆ
ˆ
Establecimiento de conexión.
Intercambio de mensajes al inicio de la conexión.
Búsqueda de archivos.
Mecanismo de
callback.
Comunicación UDP entre el cliente y el servidor:
ˆ Keep-alive
ˆ
del servidor.
Información de estado.
Comunicación TCP entre dos clientes:
ˆ Handshake
ˆ
ˆ
ˆ
inicial.
Identicación segura del usuario.
Solicitud de cheros.
Transferencia de datos.
37
3. Análisis
ˆ
ˆ
ˆ
Consulta de los archivos y carpetas compartidos.
Intercambio de los
hash
de fragmentos de archivos.
Obtención de la previsualización de un archivo.
Comunicación UDP entre dos clientes.
ˆ
Uso del protocolo UDP en escenarios relacionados con la descarga de archivos.
En todos los diálogos posibles existen escenarios (situaciones donde se producen
intercambios de mensajes) entre el cliente y el servidor o entre dos clientes. Dichos escenarios, que no son más que un intercambio de mensajes a lo largo del tiempo, pueden
modelarse mediante autómatas de estados nitos, siguiendo el procedimiento mostrado
en el Capítulo 2.
A continuación se recorren los posibles diálogos más destacados, con los escenarios más
importantes conocidos para dichos diálogos y con el intercambio de mensajes correspondiente y su modelado mediante un autómata de estados nitos.
3.1.1.
Comunicación TCP cliente-servidor
Cada cliente se conecta exactamente a un servidor usando una conexión TCP. El
servidor asigna al cliente un ID, que será usado para identicarle durante toda la sesión
con ese servidor (un cliente con ID alto lo ha obtenido siempre a partir de su dirección
IP, como se explica en la sección 1.3.2). Para poder operar, el cliente `eMule' requiere
siempre que se establezca una conexión con un servidor. Dicho cliente no puede estar
conectado a varios servidores al mismo tiempo ni tampoco cambiar de uno a otro de
manera dinámica sin la intervención directa del usuario.
Establecimiento de conexión
Cuando se establece la conexión con un servidor, el cliente intenta conectar con varios servidores en paralelo, pero abandona todos los intentos una vez se haya conectado
exitosamente a uno.
Existen tres posibles casos de establecimiento de conexión:
Conexión con ID alto: El servidor asigna un ID alto al cliente que se conecta.
Conexión con ID bajo: El servidor asigna un ID bajo al cliente que se conecta.
Sesión rechazada: El servidor rechaza al cliente.
Existe, por supuesto, el caso trivial en el que el servidor está caído o es inalcanzable.
La Figura 3.1 describe la secuencia de mensajes que da lugar a una conexión con ID
alto. En este caso, el cliente establece una conexión TCP con el servidor y le envía un
login. El servidor se conecta al cliente usando otra conexión TCP y realiza
handshake cliente-cliente para asegurarse de que el cliente al que se conecta tiene la
capacidad de aceptar conexiones de otros clientes `eMule'. Tras completar el handshake el
servidor termina la segunda conexión y completa el handshake cliente-servidor enviando
mensaje de
un
38
3. Análisis
un mensaje de cambio de ID (`ID change'). El mensaje de `eMule' info está representado
en la Figura con color gris por el hecho de pertenecer a una extensión del protocolo, que
es parte de `eDonkey'.
La Figura 3.2 describe la secuencia de mensajes que dan lugar a una conexión con ID
bajo. En este caso, el servidor falla al intentar conectarse al cliente que se conecta a él,
por lo que se le asigna un ID bajo. El servidor suele enviar un mensaje de precaución,
de la forma: Warning
[detalles del servidor] You have a low ID. Please review your
network cong and/or your settings .
Los handshake correspondientes a conexiones tanto de ID alto como de ID bajo, nal-
mente se completan con el mensaje de cambio de ID, el cual asigna al cliente un ID para
su conexión con el servidor.
La Figura 3.3 describe la secuencia de mensajes que se suceden para una conexión
rechazada por el servidor. Dicho servidor podría actuar así debido a que el cliente tiene
un ID bajo o cuando alcanzan su capacidad máxima. El mensaje del servidor contendrá
una breve cadena que describe el motivo del rechazo.
Figura 3.1: Conexión con ID alto.
39
3. Análisis
Figura 3.2: Conexión con ID bajo.
El modelado de los tres tipos de conexiones con un autómata daría lugar a lo mostrado
en la Figura 3.4, en la que se representa el intercambio de mensajes que se producen
entre cliente y servidor. La sintaxis seguida por el mensaje que acompaña a la echa
es mensaje del cliente/mensaje del servidor , ya que los autómatas están diseñados de
cara a considerarlos como si se vieran desde el propio cliente. Por ejemplo, para llegar al
q
q q
escenario nal en el que al cliente se le asigna un ID bajo, primero el cliente se conecta
mediante TCP al servidor (q0
servidor (q1
q
1 ); tras esto, el cliente envía un mensaje de
login
al
2 ); entonces el servidor se conecta con este cliente para vericar que
q
acepta conexiones entrantes ( 2
mensaje del servidor (q3
ID (q9
q
3 ); al comprobar que no puede, el cliente recibe un
9 ); por último, el cliente recibe un mensaje de cambio de
10 ). Es en este punto donde se llega a la conclusión de que al cliente se le ha
asignado un ID bajo.
Figura 3.3: Conexión rechazada.
40
3. Análisis
Figura 3.4: Establecimiento de conexión modelado con autómata de estados nitos.
Es viable unir los tres posibles escenarios en un solo autómata, ya que comparten parte
de los mensajes intercambiados y la utilización y gestión de este autómata no es compleja.
En realidad, sería posible denir un único autómata capaz de modelar todo el protocolo
considerando todos los escenarios posibles. Sin embargo, por razones operativas y de escalabilidad, se usarán autómatas parciales, correspondientes a escenarios concretos. En
el caso de considerar un único autómata, resultaría muy complejo analizar el protocolo
y modelar nuevos escenarios y añadirlos a la especicación. Análogamente en este caso,
los tres escenarios se podían haber modelado con tres autómatas más pequeños, que son,
en realidad, tres sub-autómatas del mostrado en la Figura 3.4. Sin embargo, como se ha
comentado, el autómata nal resultante no es tan complejo como para dividirlo. Además, los tres sub-autómatas forman parte del establecimiento de conexión entre cliente
y servidor (mismo escenario).
Intercambio de mensajes al inicio de la conexión
Tras un establecimiento de conexión exitoso, el cliente y el servidor intercambian algunos mensajes. El propósito de estos mensajes es actualizar ambas partes, contemplando
el estado de los
peers. El cliente comienza ofreciendo al servidor una lista con sus archivos
compartidos y luego realiza una petición de actualización de su lista de servidores. El
servidor le envía su estado y su versión y luego la lista de todos los servidores `eMule' que
conoce, junto con algunos detalles más del propio servidor. Finalmente, el cliente realiza
una petición de fuentes (es decir, otros clientes a los que pueda acceder que contengan
partes de archivos en su lista de descarga) y el servidor le contesta con una serie de
mensajes, uno por cada archivo de la lista de descarga del cliente. La Figura 3.5 ilustra
esta secuencia.
41
3. Análisis
Figura 3.5: Secuencia de mensajes al inicio de la conexión.
El modelado de la serie de mensajes expuestos en la Figura 3.5 se correspondería con
el autómata de la Figura 3.6.
Búsqueda de archivos
La búsqueda de archivos la inicia el usuario. La operación es simple: se envía una solicitud de búsqueda al servidor y este contesta con un resultado. Cuando existen múltiples
resultados, el mensaje con el resultado de la búsqueda se comprime. Tras esto, el usuario
decide descargar uno o más archivos, por lo que envía peticiones de búsqueda de fuentes
para cada uno de estos archivos y el servidor contesta con una lista de fuentes para cada
uno de dichos archivos. El servidor puede enviar un mensaje de estado opcional, antes
de la respuesta con las fuentes encontradas.
Figura 3.6: Secuencia de mensajes al inicio de la conexión modelada con autómata de
estados nitos.
42
3. Análisis
El mensaje de estado contiene información acerca del número de usuarios y archivos
soportados por el servidor. Es importante señalar que también existe una secuencia de
mensajes UDP para mejorar la habilidad de un cliente para localizar fuentes en las
búsquedas de archivos. Tras vericar que las fuentes obtenidas son nuevas, el cliente
`eMule' inicia un intento de conexión y las añade a su lista de fuentes. El orden en el que
se contacta con las fuentes es el orden con el que el cliente las recibió.
El cliente `eMule' se va conectando a las fuentes en el orden en el que están en su lista
de fuentes. No hay ningún mecanismo de prioridad para decidir a qué fuente conectar,
pero sí existe un complicado articio para resolver situaciones donde se le pueden enviar
múltiples solicitudes a una misma fuente porque esta posea varios de los archivos de la
lista de descarga del cliente (nótese que `eMule' sólo permite una única conexión entre
clientes). El algoritmo de selección está basado en las especicaciones de prioridad del
usuario pero, si no existen, por defecto se atiende al orden alfabético. La Figura 3.7
muestra este mecanismo, mientras que la Figura 3.8 muestra el autómata resultante.
Mecanismo de
callback
El mecanismo de
callback
se diseñó para superar la incapacidad de los clientes con
ID bajo de aceptar conexiones entrantes y, así, poder compartir sus archivos con otros
clientes. El mecanismo es simple: en el caso de que `A' y `B' estén conectados al mismo
servidor `eMule' y `A' necesite un archivo que posee `B', pero `B' tenga un ID bajo,
entonces `A' puede enviar al servidor una solicitud de
callback
al servidor, para que este
le solicite a `B' que se conecte con `A'. El servidor, que ya tiene una conexión TCP
establecida con `B', le envía a `B' un mensaje de
callback
con la dirección IP y puerto
de `A'. Entonces `B' ya puede conectarse con `A' y enviarle el archivo que le falta, sin
más sobrecarga en el servidor. Obviamente, sólo un cliente con ID alto puede realizar
solicitudes de
callback
hacia clientes con ID bajo (un cliente con ID bajo no puede aceptar
conexiones entrantes). La Figura 3.9 describe esta secuencia.
Figura 3.7: Secuencia de mensajes de búsqueda de archivos.
43
3. Análisis
Figura 3.8: Autómata de estados nitos para la búsqueda de archivos.
Existe también una característica que permite a dos clientes con ID bajo intercambiar
archivos a través de la conexión que tienen con el servidor, utilizándola como una pasarela.
Pero la mayoría de servidores no soportan esta opción ya que produce una gran sobrecarga
en ellos.
Los autómatas que modelan este intercambio de mensajes se muestran en las Figuras
3.10, 3.11 y 3.12. El motivo de denir, en este caso, tres autómatas es porque existen
tres entidades que participan en el proceso. Si se considerara solamente una de ellas, no
se podrían apreciar todos los intercambios de mensajes, porque siempre hay alguno que
involucra a una tercera entidad no representada.
Figura 3.9: Secuencia de mensajes para el mecanismo de
callback.
44
3. Análisis
Figura 3.10: Secuencia de mensajes para el mecanismo de
callback
modelada con auto-
callback
modelada con auto-
callback
modelada con auto-
mata de estados nitos (Cliente A).
Figura 3.11: Secuencia de mensajes para el mecanismo de
mata de estados nitos (Servidor).
Figura 3.12: Secuencia de mensajes para el mecanismo de
mata de estados nitos (Cliente B).
3.1.2.
Comunicación UDP cliente-servidor
El cliente `eMule' y el servidor usan el protocolo no able UDP para
keep-alive
y para
mejoras en las búsquedas. La cantidad de paquetes UDP que genera un cliente `eMule'
puede alcanzar el 5 % del total de paquetes, pero depende del número de servidores en
la lista del cliente, del número de fuentes para cada archivo de su lista de descarga y del
número de búsquedas realizadas por el usuario. Estos paquetes se van enviando de acuerdo
con un contador que expira cada 100 ms. Si se tiene en cuenta que sólo existe una hebra
responsable del tráco UDP saliente, se obtiene una tasa máxima de 10 paquetes/seg.
Keep-alive
del servidor e información de estado
El cliente comprueba, periódicamente, el estado de los servidores de su lista de servidores. Esta comprobación se realiza usando los mensajes de solicitud de estado del servidor
UDP y de solicitud de descripción del servidor UDP. El esquema
keep-alive
que se des-
cribe a continuación no genera más de una docena de paquetes por hora. En cualquier
caso, la tasa máxima es de 0.2 paquetes/seg (o un paquete cada 5 segundos). Cuando se
comprueba el estado de un servidor, el cliente primero envía un mensaje de solicitud de
estado y posteriormente, sólo una vez cada dos intentos, una solicitud de descripción del
servidor, tal y como se muestra en la Figura 3.13.
45
3. Análisis
Figura 3.13: Ciclo de
keep-alive
UDP.
El mensaje de solicitud de estado incluye un número aleatorio que el servidor incluye
en su mensaje de respuesta. En caso de que el número que envíe el servidor sea diferente
al reto del cliente, el mensaje se descartará. Cada vez que el cliente envía un mensaje
de este tipo, incrementa en una unidad un contador de intentos. Cualquier mensaje
recibido por parte del servidor (incluyendo resultados de búsquedas, etc), pone a cero
dicho contador. Cuando este contador alcanza un número límite, el cual es congurable,
el servidor se considera muerto y se quita de la lista de servidores del cliente. Las
respuestas proporcionadas por un servidor incluyen varios tipos de datos. La respuesta
a una solicitud de estado incluye el número actual de usuarios y archivos en el servidor
y también los límites blandos y duros (descritos anteriormente). La respuesta a una
solicitud de descripción del servidor incluye el nombre de este y una cadena de texto con
una breve descripción. La Figura 3.14 ilustra el intercambio de mensajes en una secuencia
keep-alive
completa entre un cliente y un servidor y el modelado resultante se encuentra
en la Figura 3.15.
Figura 3.14: Secuencia
keep-alive
UDP.
46
3. Análisis
Figura 3.15: Secuencia
keep-alive
UDP modelada con autómata de estados nitos.
En esta situación, se han podido unir los dos escenarios en un mismo autómata. Esto
es porque en el primer escenario sólo se indicaban las solicitudes que realizaba el cliente
al servidor y la frecuencia con las que las realizaba. Sin embargo, en el segundo escenario,
se muestran las solicitudes junto con sus respuestas, por lo que existe una parte común
entre los dos escenarios que se pueden resumir en un solo autómata sencillo.
3.1.3.
Comunicación TCP cliente-cliente
Tras registrarse en el servidor y enviarle solicitudes de archivos y fuentes, el cliente
`eMule' necesita contactar con otros clientes con el objetivo de descargarse los cheros
que desee. Así, se crea una conexión TCP dedicada para cada par {archivo, cliente}.
Las conexiones se cierran cuando no hay actividad en un
determinado (40 segundos por defecto) o cuando el
peer
socket
durante un tiempo
cierra la conexión.
Con el objetivo de proporcionar tasas de descarga razonables, `eMule' no permite a un
cliente comenzar la descarga de un archivo hasta que no pueda ofrecerle una tasa mínima
(la cual es 2.4 KB/seg).
Handshake
El
inicial
handshake
inicial es simétrico, ya que ambas partes se envían la misma informa-
ción. Los clientes intercambian información acerca del otro, la cual incluye identicación,
versión e información acerca de determinadas capacidades. Participan dos tipos de mensajes: el mensaje de `Hello' y el mensaje de información acerca del `eMule'. El primero
de ellos es parte del protocolo `eDonkey' y es compatible con los clientes. El segundo es
parte del protocolo extendido del cliente, el cual es único en `eMule'. En la Figura 3.16
se muestra este funcionamiento, y su autómata correspondiente es el de la Figura 3.17.
47
3. Análisis
Figura 3.16:
Figura 3.17:
Handshake
Handshake
inicial de los clientes `eMule'.
inicial de los clientes `eMule' modelado con autómata de estados
nitos.
En este autómata se incluyen tanto los mensajes intercambiados del protocolo `eDonkey', como la extensión del protocolo proporcionada por `eMule'. Como se puede apreciar,
no es necesario disponer de la extensión de `eMule' para poder satisfacer este escenario.
Identicación segura del usuario
En el Apartado 1.3.3 se describió brevemente los ID del usuario y la motivación que
pueden tener otros para suplantar la identidad de un determinado usuario. La identicación segura es parte de la extensión de `eMule'. En el caso de que los clientes soporten
este tipo de identicación, esta tiene lugar justo después del
handshake
inicial. El propó-
sito de la identicación segura es prevenir la suplantación de identidad. Es un esquema
simple basado en RSA. Cuando se aplica dicha identicación, suponiendo dos clientes `A'
y `B', tienen lugar los siguientes pasos:
1. En el
handshake
inicial, `B' indica que soporta la identicación segura y que desea
utilizarla.
2. El cliente `A' reacciona enviando un mensaje de identicación segura, el cual indica
si `A' necesita la clave pública de `B' o no, y que también contiene un reto de 4
bytes que `B' tiene que rmar.
48
3. Análisis
3. En el caso de que `A' haya indicado que necesita la clave pública de `B', entonces
`B' se la envía.
4. `B' envía un mensaje rmado que se crea usando el reto recibido y una palabra
doble adicional que es la dirección IP de `A', en el caso de que `B' tenga un ID
bajo, o el ID de `B' en el caso de que tenga ID alto.
Las Figuras 3.18 y 3.19 ilustran dicha secuencia de mensajes. El autómata se muestra
en la Figura 3.20.
En este caso se muestra un autómata único en el que ha sido posible unir varios
escenarios debido a su sencillez y al hecho de compartir mensajes entre ellos.
Solicitud de cheros
Como ya se describió, se crea una conexión para cada par {cliente, chero}. Inmediatamente después del establecimiento de conexión, el cliente envía varios mensajes indicando
el archivo que desea descargar (Figura 3.21). Existen varios casos en la solicitud de cheros y se describen a continuación.
Figura 3.18: Identicación segura. `A' no tiene la clave pública de `B'.
Figura 3.19: Identicación segura. `A' tiene la clave pública de `B'.
49
3. Análisis
Figura 3.20: Identicación segura modelada con autómata de estados nitos.
Figura 3.21: Solicitud de chero.
Intercambio básico de mensajes.
Está compuesto por cuatro mensajes. En primer
lugar, `A' envía un mensaje de solicitud de archivo e inmediatamente después, otro con
el ID del archivo que se solicita. `B' responde a la solicitud de archivo con una solicitud
de respuesta de archivo. Al mensaje con el ID del archivo solicitado contesta con un
mensaje de estado del chero.
El protocolo extendido añade dos mensajes a esta secuencia: una solicitud de fuentes y
una respuesta a esta solicitud. Esta extensión se utiliza para transmitir las fuentes de `B'
(en el caso de que `B' sea el cliente que descarga) a `A'. No existe ningún requerimiento
que establezca que `B' necesite descargar el archivo completo para poder compartir partes
con otros clientes, por lo que `B' puede enviar a `A' otros fragmentos del chero que tenga
completos.
Escenario de archivo no encontrado.
Se produce cuando `A' solicita un archivo a `B'
pero `B' no disponga de dicho archivo en su lista de archivos compartidos. `B' no envía
la respuesta de solicitud de archivo, sino que envía un mensaje de archivo no encontrado,
inmediatamente después de recibir el mensaje con el ID del archivo que se solicita (Figura
3.22). Asimismo, el autómata que modela tanto la solicitud de un chero como el escenario
de un chero no encontrado es el de la Figura 3.23.
50
3. Análisis
Figura 3.22: Solicitud de archivo fallida. Archivo no encontrado.
Figura 3.23: Solicitud de chero modelada con autómata de estados nitos.
En este caso, se ha podido, una vez más, unir varios escenarios dentro de un mismo
autómata. La parte inicial corresponde a la búsqueda de archivos en ambos casos, pero
se diferencia en la parte nal en caso de que el archivo no se haya encontrado, o bien en
el caso de que sí se haya encontrado.
Adición de archivos a la cola de subida.
En el caso de que `B' disponga de un determi-
nado archivo que se le ha solicitado y su cola de subida no esté vacía, signica que existen
clientes que se están descargando archivos de él y probablemente existirán también otros
clientes en cola. `A' y `B' realizan el
handshake
completo, pero cuando `A' solicita a `B'
la descarga de un archivo, `B' le añade a la cola de subida y le envía un mensaje de
ranking,
el cual contiene la posición de `A' en la cola.
Gestión de la cola de subida.
Para cada archivo enviado, el cliente mantiene una cola
de subida con prioridad. La prioridad de cada cliente en dicha cola se calcula en base
51
3. Análisis
al tiempo que lleva el cliente en la cola y un modicador de prioridad, llamado
rating
(Figura 3.24).
En la cabeza de la cola están los clientes que tienen la puntuación más alta. Dicha
puntuación se calcula usando la siguiente fórmula:
puntuacion =
rating×segundosEnLaCola
100
Puede ser innito en caso de que el cliente que descarga esté denido como amigo. El
valor del
rating
rating
inicial es 100, excepto para los usuarios prohibidos (expulsados), cuyo
es 0 (y así se evita que alcancen la cabeza de la cola). El
rating
es modicado o
bien por el crédito del cliente que descarga (cuyo rango es del 1 al 10) o por la prioridad
del archivo que se envía (0.2 1.8) el cual lo modica el cliente que lo envía. Cuando
la puntuación de un cliente es mayor que la del resto de los clientes de la cola, entonces
comienza la descarga del archivo. El cliente estará descargando dicho archivo a no ser
que se dé una de las siguientes situaciones:
1. El usuario desconecta al cliente que envía el archivo.
2. El cliente que descarga tiene todas las partes que necesita.
3. El cliente que descarga es adelantado por otro que tiene más prioridad que él.
Con el objetivo de permitir a un cliente que acaba de comenzar a descargar archivos
obtener algunos megabytes antes de ser adelantado por otro, `eMule' impulsa el
rating
inicial del cliente que descarga a 200 durante los primeros 15 minutos.
El autómata que modela el escenario de la Figura 3.24 es el de la Figura 3.25.
Figura 3.24: Cola de espera para una solicitud de un archivo.
52
3. Análisis
Figura 3.25: Cola de espera para una solicitud de un archivo modelada con autómata de
estados nitos.
Alcanzando el inicio de la cola de subida.
subida de `B', `B' se conecta a `A', realiza el
Cuando `A' alcanza el inicio de la cola de
handshake
inicial y luego envía un mensaje
de aceptación para la cola de subida. `A' puede ahora elegir entre continuar y comenzar
a descargar el archivo enviando una solicitud, o bien cancelar la descarga (en caso de que
ya tenga el fragmento de otra fuente) enviando un mensaje de cancelación de transferencia. La Figura 3.26 ilustra estas opciones y el autómata correspondiente se muestra en
la Figura 3.27. Debido a que los dos escenarios sólo se diferencian en el mensaje nal, es
posible aunarlos en un mismo autómata, claricando en el estado nal las dos posibles
transiciones.
Figura 3.26: Descarga de un archivo.
53
3. Análisis
Figura 3.27: Descarga de un archivo modelada con autómata de estados nitos.
Transferencia de datos
El paquete de datos.
El envío y recepción de fragmentos de archivos es la mayor parte
de la actividad de la red `eMule'. El tamaño de un fragmento enviado puede variar entre
5000 y 15000 bytes (dependiendo también de la compresión). Con el objetivo de evitar
la fragmentación, los mensajes de partes de cheros se envían en trozos y cada trozo en
un paquete TCP por separado. En la versión 0.30e de `eMule', el tamaño máximo de una
pieza es de 1300 bytes (nótese que este número se reere únicamente a la carga útil del
paquete TCP). En otras palabras, mientras cada mensaje de control se envía en un único
paquete TCP, a veces, junto con otro mensaje, los mensajes de datos están divididos en
varios paquetes TCP. El primer paquete contiene la cabecera del mensaje de la parte del
archivo que se envía. El resto de los paquetes contienen sólo datos. En caso de que el
paquete se divida, en el primero de ellos se envía un recordatorio (el que lleva el mensaje
de cabecera) que lo indica. Los detalles se muestran en la Figura 3.28, y el autómata que
lo modela es el de la Figura 3.29.
Figura 3.28: Detalles del mensaje de la parte de un archivo.
54
3. Análisis
Figura 3.29: Detalles del mensaje de la parte de un archivo modelado con autómata de
estados nitos.
Secuencia de transferencia de datos.
Una secuencia de transferencia de una parte con-
creta puede comenzar inmediatamente después de la respuesta a la solicitud del archivo.
El cliente que descarga, `A', envía una solicitud de comienzo de envío, la cual se responde
mediante otro mensaje de aceptación. Inmediatamente después de esto, `A' comienza a
solicitar fragmentos de archivo y `B' contesta enviando las partes solicitadas.
Cuando ambos clientes soportan el protocolo extendido, los fragmentos del archivo se
pueden enviar comprimidos. Dicho protocolo también soporta un mensaje adicional de
información que puede ser enviado justo antes del mensaje de aceptación de envío. Esta
secuencia está ilustrada en la Figura 3.30 y el autómata que lo modela es el de la Figura
3.31.
Figura 3.30: Intercambio de fragmentos de archivo.
55
3. Análisis
Figura 3.31: Intercambio de fragmentos de archivo modelado con autómata de estados
nitos.
Consulta de los archivos y carpetas compartidos
Hay dos tipos de mensajes que manejan la visualización de los archivos y carpetas
compartidas por los clientes
peer.
El primero es el mensaje de visualización de archivos
compartidos, el cual se envía justo tras el
handshake
inicial. Este mensaje siempre es
contestado por otro de respuesta. Cuando el cliente que contesta desea esconder su lista
de archivos compartidos, la respuesta no contendrá ningún archivo (en vez de enviar
un mensaje que signique que el acceso ha sido denegado). La Figura 3.32 muestra la
secuencia de mensajes.
El segundo mensaje comienza con una solicitud de vista de la lista de las carpetas
compartidas, el cual es respondido con la lista de las carpetas y, tras esto, para cada carpeta del mensaje de respuesta, un mensaje para mostrar el contenido de la misma. Cada
uno de estos mensajes es contestado con una lista de contenidos. Se puede comprobar en
la Figura 3.33. En caso de que el cliente esté congurado para bloquear las solicitudes
de archivos y carpetas compartidos, contesta con un mensaje de denegación, como se
muestra en la Figura 3.34.
Los intercambios de mensajes pueden modelarse con el autómata de la Figura 3.35.
Dado que los escenarios se sitúan en el mismo contexto, se puede elaborar un autómata
con tan sólo ocho estados que sea capaz de recoger los cuatro escenarios.
Figura 3.32: Solicitud de vista de archivos compartidos.
56
3. Análisis
Figura 3.33: Consulta de archivos y carpetas compartidos.
Figura 3.34: Solicitudes de vista de archivos y carpetas denegadas.
Intercambio de los
hash
de fragmentos de archivo
Con el objetivo de obtener los
hash
de partes de archivo, se envía una solicitud, a la
cual el cliente contestará con un mensaje de respuesta de
hash, que contendrá dicho hash
del fragmento del archivo. La Figura 3.36 ilustra este hecho y el autómata que lo modela
es el de la Figura 3.37.
Obtención de la previsualización de un archivo
El cliente puede pedir a su
peer
obtener la previsualización de un archivo descarga-
do. Las previsualizaciones dependen de las aplicaciones y de los tipos de archivos. Las
versiones más antiguas de `eMule' (0.30e) soportan la previsualización de imágenes. El
escenario se detalla en la Figura 3.38 y el autómata correspondiente en la Figura 3.39.
57
3. Análisis
Figura 3.35: Vista de archivos y carpetas compartidos modelada con autómata de estados
nitos.
Figura 3.36: Solicitud de
Figura 3.37: Solicitud de
hash
hash
de fragmento de archivo.
de fragmento de archivo modelada con autómata de esta-
dos nitos.
58
3. Análisis
Figura 3.38: Obtención de la previsualización de un archivo.
Figura 3.39: Obtención de la previsualización de un archivo modelada con autómata de
estados nitos.
3.1.4.
Comunicación UDP cliente-cliente
El cliente `eMule' envía periódicamente mensajes usando el protocolo UDP. En la versión de `eMule' 0.30e, los mensajes UDP se usan únicamente para que el cliente pregunte
a su
peer
la posición en la que está en la cola de descarga. El esquema simple solicitud-
respuesta se inicia con un mensaje de re-solicitud de un chero concreto. Existen tres
posibles respuestas para este mensaje:
1. Posición en la cola: La posición del cliente en la cola del que envía.
2. Cola completa: La cola del cliente que envía está llena.
3. Archivo no encontrado: El cliente no tiene el archivo solicitado en su lista.
El mensaje de re-solicitud se envía en intervalos de aproximadamente 20 minutos para
cada cliente que el
peer
que envía haya añadido a su cola de descarga (Figura 3.40). El
autómata que lo modela es el de la Figura 3.41.
3.2. Análisis de requisitos y funcionalidades de la aplicación
En base a lo detallado hasta este punto, resulta sencillo evidenciar que la aplicación
a desarrollar necesita una determinada información para poder funcionar correctamente,
por lo que los elementos a considerar serían:
Información de entrada a la aplicación acerca de los autómatas.
Ficheros con trazas de tráco a analizar también como bloque de entrada, o bien
una interfaz de red para realizar una captura en vivo. Es decir, un sensor que
proporcione información acerca del tráco a analizar.
59
3. Análisis
Figura 3.40: Mensaje de re-solicitud de archivo.
Figura 3.41: Mensaje de re-solicitud de archivo modelado con autómata de estados nitos.
Un programa principal que construya los autómatas y analice las trazas de tráco
proporcionado.
Una salida que proporcione información acerca del tráco analizado.
Por tanto, la estructura principal del programa, que cumpla estos requisitos, sigue la
estructura mostrada en la Figura 3.42. En dicha gura, pueden observarse los siguientes
bloques, los cuales se detallan a continuación.
Sensor
El sensor de entrada es el bloque que proporciona datos acerca del tráco que se quiere
analizar en busca de un determinado comportamiento. Este sensor puede ofrecer el tráco
a la aplicación de dos posibles tipos de fuentes de tráco. La primera de ellas es un chero
con trazas de tráco. La segunda es indicar una interfaz de red para realizar una captura
60
3. Análisis
de tráco en vivo e introducirla en la aplicación sin necesidad de almacenar los datos en
un chero.
Los cheros con trazas de tráco deben estar en formato
pcap,
ya que la biblioteca
utilizada en la aplicación (véase Apartado 2.4.2) es capaz de trabajar con este tipo de
cheros de manera sencilla. Por tanto, la funcionalidad principal de este sensor es ofrecer
a la aplicación información acerca del tráco.
Autómatas
Tal y como se ha detallado anteriormente, el modelado del protocolo con autómatas
de estados nitos es fundamental para comprobar su funcionamiento. Ya que se necesita
analizar tráco en busca de determinados patrones de comportamiento, es necesario
introducir a la aplicación un almacén de datos con información acerca de los autómatas
que modelan el protocolo. Es decir, el objetivo es proporcionar al programa la descripción
de los autómatas denidos previamente.
Dicha información estará almacenada en un chero. El principal motivo de ser una
entrada externa a la aplicación es la exibilidad, ya que las modicaciones sobre estos
autómatas pueden ser continuas y variar con el paso del tiempo. De esta manera, se evita
la potencial necesidad de modicar el código fuente. Si no se proporcionaran de esta
manera, sería una tarea tediosa realizar dichas modicaciones.
Para ello es necesario conocer en detalle el protocolo a analizar y poder derivar de él los
autómatas de estados nitos correspondientes. Una vez se introduzca esta información
en el mencionado chero (véase Sección 4.1.7), la aplicación construirá en memoria la
estructura de estos autómatas y ya dispondrá de información suciente como para evaluar
el tráco de entrada.
Programa principal
La funcionalidad básica del programa principal es tomar toda la información de la que
dispone en los bloques de entrada, construir los autómatas que se le indican y analizar
el tráco para, nalmente, mostrar una salida con determinados resultados.
Figura 3.42: Estructura principal del programa.
61
3. Análisis
En base al tráco proporcionado, este bloque también debe clasicar los ujos de
información reconocidos. Un ujo es el intercambio de datos entre dos determinadas
entidades (peers en este caso) durante un tiempo. A grandes rasgos, el programa principal
tomará todo el tráco y lo clasicará en ujos de información en base a las características
propias de una conexión, estas son, IP y puerto origen y destino. Dado que durante una
conexión pueden haber varios ujos, se utilizarán parámetros adicionales para distinguir
entre ellos. Como en el protocolo UDP no existen conexiones, el programa principal
utilizará otros criterios para poder detectar los ujos de información, como se explicará
más adelante.
En su labor de análisis del tráco (parsing ) el programa principal puede mostrar, para
cada ujo analizado, uno de los siguientes resultados:
El ujo de información está siguiendo un comportamiento esperado, ya que se ha
logrado modelar mediante uno de los autómatas denidos. Por tanto, se mostrará
un mensaje indicando que el ujo responde a un autómata.
No existe denido ningún autómata que sea capaz de modelar la información contenida en el ujo que se está examinando. Por tanto, es posible que no estén todos los
autómatas que modelan el protocolo, o bien que sí estén todos pero que no logren
explicar adecuadamente el ujo observado. Se mostrará un mensaje indicando que
el ujo analizado no se ha reconocido.
Es posible que un ujo de datos esté incompleto, y que le falte muy poca información
para ser modelado mediante un autómata pero que, por alguna razón, este ujo
está truncado. Esto se reejará en la aplicación mostrando un mensaje de autómata
incompleto. Se considera que un autómata está incompleto cuando se reconocen
más del 80 % de los estados, pero no en su totalidad. Este umbral es simplemente
orientativo y puede ser congurable por el usuario.
Salida
El bloque de salida es el que toma los resultados que proporciona el programa principal
acerca del tráco analizado. Este bloque representa de forma esquematizada los ujos
detectados en el tráco analizado, su correspondencia con autómatas denidos y unas
estadísticas globales acerca de las detecciones realizadas.
Más concretamente, la información mostrada detallará todas las propiedades de todas
las conexiones detectadas con sus ujos de información asociados: IP origen, IP destino,
puerto origen y puerto destino; también mostrará la información que se ha intercambiado
entre los dos
peers
a lo largo de esa conexión y, por último, si el ujo de información
ha sido reconocido en base a los autómatas introducidos en el archivo de datos de entrada. Asimismo, muestra unas estadísticas sobre el porcentaje de ujos reconocidos, no
reconocidos e incompletos.
Por tanto, es el bloque que muestra las conclusiones acerca de toda la tarea realizada por el programa principal y es el encargado de clasicar los ujos en acordes a la
especicación de autómatas o no.
62
3. Análisis
3.3. Discusión del análisis
Tras el estudio del protocolo `eDonkey', así de como el de la extensión proporcionada
por `eMule', se ha propuesto un modelado para los diferentes escenarios posibles en dicho
protocolo.
Dichos escenarios corresponden a diálogos tanto TCP como UDP entre clientes y servidores. Como se comentó anteriormente, los autómatas representan partes o interacciones
entre dos determinados
peers
que usan el protocolo. Por tanto, es necesario establecer un
alineamiento entre los eventos que tienen lugar en un ujo de información y los autómatas
asociados.
Un autómata sucede a otro. Es decir, todos los autómatas están unidos mediante algún
punto común. Por ejemplo, el realizado para el establecimiento de conexión entre cliente y
servidor (que ya recogía tres posibles escenarios) le sucede el que representa los mensajes
intercambiados al inicio de la conexión entre el mismo cliente y servidor. La razón de
separarlos es por motivos de complejidad y escalabilidad.
Es necesario tener en cuenta que el comportamiento del protocolo va variando con el
tiempo, y con él, van surgiendo nuevas versiones que proporcionan nuevos escenarios o
modican los ya existentes. Si fuera necesario añadir nuevos autómatas, en esta situación
sería sencillo. Sin embargo, si se unica todo en un gran autómata general, la tarea sería
mucho más compleja.
Una buena propuesta para no tener que actualizar la aplicación sería un nuevo módulo que sea capaz de generar automáticamente modelados en base a la observación
del comportamiento del protocolo. Pero sería necesario hacer distinción de lo que es un
comportamiento correcto y uno anómalo mediante el aprendizaje de la aplicación en un
entorno controlado en el que solamente se produzcan diálogos libres de anomalías, ya
que, si no fuera así, cualquier comportamiento sería susceptible de ser catalogado como
normal.
63
3. Análisis
64
Capı́tulo
4
Diseño e implementación
En este capítulo se detalla la arquitectura de la aplicación, así como de su estructura en
módulos y los elementos necesarios para construirlos. Está destinado a explicar detalles
de la implementación y diseño del software.
4.1. Estructura modular de la aplicación
Una vez se ha propuesto el modelado mediante autómatas de estados nitos en el
Capítulo 3 para los diferentes escenarios, en esta sección se analiza la estructura detallada
de la aplicación, así como las principales dicultades en su diseño, para poder denir
las soluciones propuestas. Más concretamente, se detallan cada una de las partes del
programa principal, bloque fundamental denido en la Sección 3.2.
Para conseguir implementar el modelado del protocolo `eDonkey' y comprobar su correcto funcionamiento, el programa principal debe tener una estructura muy denida y
basada en módulos, para proporcionar al núcleo información suciente para cumplir los
requisitos propuestos.
Dichos módulos y estructuras se dividirán en las siguientes categorías:
Módulo de preprocesamiento.
Módulo de detección de ujos.
Almacén/clasicador de ujos.
Módulo de extracción y análisis de ujos.
De esta manera, se utilizará la estructura mostrada en la Figura 4.1, en la cual se
detalla en profundidad la estructura interna del programa principal.
Como se muestra en la Figura 4.1, la aplicación principal está dividida en una serie de
módulos. Los módulos de preprocesamiento y detección de ujos se ejecutan para cada
trama analizada, mientras que el módulo de extracción y análisis lo hace paralelamente
al resto. Dichos módulos se detallan a continuación.
65
4. Diseño e implementación
Figura 4.1: Estructura en módulos del programa principal.
4.1.1.
Preprocesamiento
Este módulo es el encargado de tomar como entrada el tráco que le proporciona el
sensor de manera externa. En esta primera fase se preparan las tramas antes de enviarlas
al siguiente módulo.
La misión principal del módulo de preprocesamiento es realizar un ltrado en el que
solamente pasan tramas útiles de cara al análisis. Este tipo de tramas son aquellas que
contienen segmentos TCP y UDP. De esta manera, se ahorra carga computacional a otros
módulos, ya que el tráco entrante está siendo limitado a aquel que contiene información
relevante para su análisis.
Este módulo también realiza una distinción de las tramas que tienen carga útil (pay-
load )
con las que no, ya que pueden ser interpretadas de manera errónea por el módulo
de detección de ujos.
Por tanto, el módulo de preprocesamiento examina tanto las cabeceras de las tramas
entrantes para poder ltrarlas en base a una determinada regla establecida (en este caso,
segmentos TCP y UDP), así como la carga útil de dichas tramas, para descartar aquellas
que no tengan un tamaño acorde con el esperado.
4.1.2.
Detección de ujos
El módulo detector de ujos es uno de los más importantes y es donde reside una
de las partes más importantes de la aplicación. Es el encargado de clasicar las tramas
recibidas por el módulo de preprocesamiento en ujos de información en base a alguna
conexión entre dos
peers.
Clasicar estos ujos no es una tarea sencilla ya que existen
determinados escenarios que es necesario contemplar.
Por tanto, los escenarios contemplados son los siguientes:
Que en una conexión entre dos
peers
se produzcan varios ujos de información.
Por ejemplo, un cliente y un servidor pueden intercambiar, durante una misma
conexión, varios ujos pertenecientes a búsquedas de archivos.
66
4. Diseño e implementación
Que se produzcan varias conexiones en paralelo, ya que el sensor puede proporcionar
información de varias fuentes al mismo tiempo.
Que un mensaje `eDonkey' esté separado en varias tramas.
Que una trama contenga más de un mensaje del protocolo.
El módulo de preprocesamiento detallado anteriormente, ayuda a la detección de ujos
mediante una tarea adicional. Esta es la de noticar la nalización de un ujo, por haber
nalizado la conexión entre dos
peers. Esto lo realiza mediante la recepción de segmentos
TCP cuyo bit de cabecera FIN esté activo. En ese caso, signicará la nalización de una
conexión y, por tanto, de su ujo (o ujos) asociado (nótese que, como se detalló en 2.2,
dentro de ese ujo aparente pueden existir varios de ellos). En este momento envía al
módulo de extracción y análisis dicho ujo para su examen. Mediante esta tarea, se evita
enviar al módulo de extracción y análisis tráco innecesario ya que, debido a que se ha
detectado el nal de un ujo, evita realizar esta tarea al módulo siguiente. Esto es sólo
aplicable al protocolo TCP. Para el UDP se utilizará el procedimiento de ujos antiguos
detallado en 4.1.4.
El módulo de detección de ujos resuelve la tarea de separar los mensajes intercambiados entre dos
peers
y clasicarlos en ujos. Sin embargo, no contempla que, dentro
de la conexión analizada, pueden existir varios ujos de información, como se explicó
anteriormente. Por lo que dentro de lo que en este módulo se considera un ujo, pueden
existir realmente varios de ellos. Pero este problema lo resuelve el módulo de extracción
y análisis, como se explicará más adelante.
Como estas situaciones anteriores, pueden producirse muchos casos, producto de las
combinaciones de tráco proporcionadas por el sensor y de la actividad que tenga el
protocolo en un momento determinado. Es decir, numerosos mensajes de numerosas conexiones pueden aparecer entremezclados. Por tanto, la detección de ujos de información
no es una tarea sencilla. La detección de ujos sigue los siguientes pasos:
1. En el caso del protocolo `eDonkey', los mensajes intercambiados entre los
peers
tienen un campo protocolo, el cual almacena una determinada información característica del protocolo. En protocolo `eDonkey', dicho campo toma el valor 0xE3.
Como se ha visto en el Capítulo 3, `eMule' proporciona una serie de funcionalidades
adicionales al protocolo `eDonkey'. Los mensajes pertenecientes a estas extensiones
toman el valor 0xC5 en el campo protocolo mencionado.
Por tanto, las tramas recibidas del módulo de preprocesamiento son examinadas en
busca de características propias del protocolo P2P que se está analizando. En este
caso, se busca que el campo protocolo tome los valores mencionados. En cierto
modo, este paso realiza un ltrado de las tramas que únicamente pertenecen al
protocolo analizado.
2. Para cada una de las tramas seleccionadas, se buscan en ellas los rasgos característicos de una determinada conexión, es decir, la IP origen y destino, y los puertos
origen y destino. Para ello, se accede a la cabecera de dichas tramas, en busca de
la información mencionada.
67
4. Diseño e implementación
3. Una vez llegado a este punto, se puede crear una estructura de datos que almacene
un ujo de información, ya que se dispone de datos sucientes. A este ujo se le
añade una marca de tiempo, que se corresponde con el instante en el que se recibió
el primer paquete de dicho ujo entre los dos
peers.
Las tramas llegadas hasta este punto (las pertenecientes a `eDonkey' o su extensión
`eMule') poseen un campo tipo que almacena una cifra en hexadecimal que indica
qué tipo de mensaje es (establecimiento de conexión, búsqueda de archivos, etc.).
La información contenida en este campo se añadirá a la estructura de datos que
conforma un ujo de información.
El campo tipo puede aparecer más de una vez dentro de la misma trama. En ese
caso se añadirá, de la misma manera que se indicó anteriormente, a la estructura
de datos que almacena información acerca del ujo.
4. Por último, se busca en el almacén/clasicador global si existe algún ujo de información con las mismas características del obtenido en el paso 3 (mismas IP y
mismos puertos). En caso armativo, signica que ya existía una conexión idéntica,
por lo que los datos obtenidos en el paso 3 son datos nuevos pertenecientes a una
conexión que ya estaba contemplada. Por tanto, todos los campos tipo recopilados en el paso anterior, se añaden junto con los ya existentes en la estructura de
datos dentro del almacén/clasicador de ujos.
En caso contrario, signica que se han obtenido datos de una conexión nueva, por
lo que se añade un ujo nuevo al almacén/clasicador de ujos.
El problema de detectar varios subujos dentro de un ujo de información concreto se resuelve como se explica a continuación. Cuando se extrae un ujo del almacén/clasicador,
se envía a analizar (parsing ) como se verá más adelante. Si el módulo de extracción y
análisis, al comparar el ujo con los autómatas, llega a un estado nal sin haber terminado de examinar todos los mensajes del ujo, entonces se entiende que dentro de ese
ujo había otro más pequeño, por lo que el resto de mensajes que no se han examinado
se vuelven a incluir en el almacén/clasicador.
4.1.3.
Almacén/clasicador de ujos
El almacén/clasicador de ujos es una estructura de datos global a toda la aplicación.
Su funcionalidad básica es servir de almacén para los ujos que le proporciona el módulo
de detección de ujos.
Es un contenedor en el que se almacenan estructuras de datos que se corresponderían
con contenido acerca de conexiones y ujos de información. Aunque puedan analizarse
varios ujos simultáneamente, hay que tener en cuenta que esta estructura es global a
toda la aplicación, por lo que habrá que tomar precauciones para evitar problemas de
inconsistencia, como se verá más adelante.
Este almacén/clasicador es utilizado por dos módulos, ya que el de detección de ujos
inserta nuevos elementos, mientras que el módulo de extracción y análisis, como su propio
nombre indica, extrae ujos para posteriormente analizarlos.
68
4. Diseño e implementación
4.1.4.
Extracción y análisis
El último de los módulos es el de extracción y análisis, que lleva a cabo la tarea de
comparar los ujos del almacén/clasicador con la estructura de autómatas existente en
la aplicación. Denominamos a esta tarea como
parsing.
Para cumplir esta funcionalidad, este módulo debe considerar cuándo un ujo está
listo para ser analizado, por lo que se plantea el problema de saber si una conexión
se da por terminada o, por el contrario, va a seguir añadiendo información al ujo del
almacén/clasicador.
Para resolver este problema, este módulo extrae los ujos considerados como antiguos
y los analiza. Un ujo se considera antiguo cuando lleva un determinado tiempo sin
actualizarse. Este tiempo es congurable y por defecto está establecido a 5 segundos. Por
este motivo, todos los ujos del almacén/clasicador llevan una marca de tiempo.
El criterio utilizado para la consideración de ujos antiguos se detalla a continuación,
aunque se plantean dos problemas principales:
1. Como se explicó anteriormente, el sensor puede proporcionar trazas de tráco tanto
de un chero estático como de una captura en vivo, procedente de una interfaz de
red.
El análisis de un chero almacenado en disco se lleva a cabo relativamente rápido si
es comparada con una captura en vivo. En esta última, no se puede saber a priori
con qué velocidad se van a capturar las tramas, puesto que la actividad entre dos
determinados
peers
en una conexión depende en parte del usuario, ya que puede
provocar voluntariamente una determinada actividad.
Por ejemplo, puede existir una conexión entre cliente y servidor abierta durante
mucho tiempo y, sin embargo, no existir ningún tipo de actividad.
2. Es necesario considerar que una conexión entre dos
peers
puede haber nalizado y
la aplicación no ser consciente de ello, debido a que el tipo de conexión sea UDP,
puesto que nunca se recibe una trama de nalización de conexión, como se explicó
en la Sección 2.2.
En ambos casos es importante considerar el criterio de ujo antiguo: Se establece una
variable global que indica un umbral de tiempo máximo. Si un ujo lleva sin actualizarse
igual o más tiempo del indicado en este umbral, se considera una conexión terminada,
por lo que se extrae del almacén/clasicador y se analiza. Para proporcionar exibilidad
a la aplicación, este umbral puede ser modicado sin repercutir negativamente en otros
módulos.
Por tanto, la tarea principal del módulo de extracción y análisis es examinar el almacén/clasicador en busca de ujos antiguos. Cuando encuentre un ujo apto para ser
examinado, lo extrae del almacén/clasicador y proceda a su análisis.
4.1.5.
Justicación de los módulos
La estructura modular de la aplicación está diseñada de manera que aporte exibilidad.
Los módulos podrían modicarse sin excesiva dicultad con el objetivo de ser útiles en
69
4. Diseño e implementación
el análisis de otros protocolos.
El módulo de preprocesamiento realiza un ltrado de tramas y libera de carga al núcleo
de la aplicación, por lo que su funcionalidad se hace evidente.
El módulo de detección de ujos es fundamental a la hora de encontrar, parcialmente,
los ujos de información dentro de varias conexiones.
El almacén/clasicador es una estructura intermediaria entre dos módulos. Es esencial
disponer de una estructura de este tipo para poder almacenar información acerca de los
ujos y conexiones detectadas.
Por último, el módulo de extracción y análisis realiza la tarea nal, en la que extrae
ujos según un determinado criterio y realiza el
parsing
de estos, proporcionando unos
resultados ya visibles.
4.1.6.
Diseño global de la implementación
El programa se ha diseñado de manera multihebrada. Es posible ejecutarlo para varios
cheros e interfaces de red al mismo tiempo, los cuales se analizarán concurrentemente
para, nalmente, mostrar un resultado global. Por cada chero con trazas o interfaz a
analizar, se crea una hebra inicial que se encarga de procesar su información por separado.
En la aplicación, la estructura del almacén/clasicador de ujos es global a todas las
hebras. Sin embargo, el módulo de preprocesamiento y parte del de detección de ujos
los ejecutan cada hebra independientemente de las demás. El motivo de esto es que una
parte del módulo de detección de ujos accede al almacén/clasicador como se puede ver
en la Figura 4.1. Como esta es una estructura global, es necesario controlar las hebras
para no crear problemas de inconsistencia.
Debido al diseño multihebrado, es necesario considerar el problema de la exclusión
mutua, ya que existen secciones críticas que pueden ser ejecutadas por varias hebras a
la vez, pudiendo producir un resultado inconsistente. La sección crítica sería, en este
caso, los accesos al almacén/clasicador de tramas, ya que está siendo actualizado por
múltiples hebras que analizan los módulos de entrada.
Por tanto, es necesario garantizar que no se produce un acceso simultáneo al almacén/clasicador de ujos por varias hebras. Mediante el uso de
mutexes
de la biblioteca
`Pthread' (véase Sección 2.4.3) se logra este objetivo.
Al mismo tiempo que la ejecución del módulo de preprocesamiento y detección de
ujos, existe inicialmente otra hebra independiente que ejecuta el módulo de extracción
y análisis de ujos del almacén/clasicador. Esta hebra se encarga de revisar este almacén/clasicador y comprobar periódicamente si existen ujos antiguos. El problema
de este modo de procesamiento es que podrían existir múltiples hebras añadiendo ujos
al almacén/clasicador mientras que sólo una se encargaría de la extracción y análisis;
es decir, podría producir un desbordamiento del almacén/clasicador si aumenta demasiado de tamaño. Esto se soluciona mediante otro diseño multihebrado: el hilo que
controla el módulo de extracción y análisis comprueba periódicamente el tamaño del
almacén/clasicador; si el tamaño es mayor que un umbral establecido, genera otras hebras que ayudan a liberar carga de la principal. Cuando estas hebras nalizan su trabajo,
mueren automáticamente y permanece la principal que controlaba este módulo.
70
4. Diseño e implementación
Esta solución multihebrada del módulo de extracción y análisis plantea nuevamente
un problema: el acceso en exclusión mutua al almacén/clasicador. Pero se soluciona de
la misma manera que anteriormente, ya que se usan
mutexes
que garantizan la exclusión
mutua.
4.1.7.
Formato del chero de autómatas
Un usuario con algunas nociones acerca del funcionamiento de la aplicación podría
introducir información acerca de nuevos autómatas, modicar los ya existentes, o eliminar
alguno de ellos. En denitiva, es capaz de manejar la información que tiene la aplicación
acerca del protocolo.
Para hacer posible esto, se ha denido un tipo de lenguaje en el que escribir los
autómatas. Estos residen en un chero, el cual se puede editar para modicar dicha
información.
Las características principales de la sintaxis de este chero son las siguientes:
El carácter ` %' indica un comentario. Se deben comentar líneas completas, siendo
este carácter el primero de la línea. No se admiten líneas en blanco en el chero, ya
que se entiende que no están comentadas y, por lo tanto, tienen algún signicado.
Todos los estados que conforman todos los autómatas se consideran un solo conjunto
y siguen una numeración. Es decir, si se escribe un autómata con cinco estados, se
numerarán 0, 1, 2, 3 y 4. Si luego se escribe otro autómata con tres estados, aunque
sea independiente del anterior, la numeración de los estados será 5, 6 y 7. Y así
sucesivamente.
El nal de línea se indica con el carácter `$' o bien con el carácter `*' si es el estado
nal, en el cual el autómata deberá llevar un nombre.
El formato de las líneas de descripción de un autómata es:
NUM_ESTADO S/N S/N [# CADENA NUM_ESTADO_DESTINO [# ... ]] $
[NOMBRE_AUTOMATA *]
1.
NUM_ESTADO
2.
S/N
indica el número del estado. Por ejemplo,
0
o
1.
indica si el estado es inicial o no, en el primer caso. En el segundo caso indica
si el estado es nal o no.
3.
# CADENA NUM_ESTADO_DESTINO
indica la relación de transiciones. Es decir, hace
referencia a la cadena asociada a la transición y al número del estado al que se
transita. Puede haber tantas cadenas como se desee. Se indica que no hay más
transiciones con
4.
$
NOMBRE_AUTOMATA
indica el nombre del autómata. Es necesario indicarlo cuando el
estado es nal.
71
4. Diseño e implementación
Se muestra el proceso de creación del archivo de descripción del autómata representado
en la Figura 4.2.
Si se quisiera escribir con la sintaxis indicada en este autómata, sería necesario seguir
los siguientes pasos:
El estado
q0
se nombrará como `0', suponiendo que sea el primer estado del chero
de autómatas. Si no es así, se continuará la numeración del último estado que hay.
q1
De la misma manera, el estado
se nombrará como `1' y el estado
q2
se nombrará
como `2'.
Tras el número identicador del estado, se ha de indicar si los estados son iniciales
y/o nales. Por tanto, para el estado
es nal. Para el estado
q1
por último, para el estado
q0
se indicará `S' y `N' ya que es inicial y no
se indicará `N' y `N', ya que ni es inicial ni es nal. Y
q2
se indicará `N' y `S' ya que no es inicial y es nal.
Tras esto, se añaden unos separadores para indicar las posibles transiciones hacia
otros estados. Para el estado
transición hacia el estado
q1 .
q0 ,
se añadirá el separador `#', ya que tiene una
Para el estado
tiene una transición hacia el estado
q2 .
q1
se añadirá el separador `#', ya que
Por último, para el estado
q2
se añadirá el
separador `$', ya que no tiene transiciones hacia ningún otro estado.
Tras indicar los separadores, es necesario mostrar las transiciones. Para el estado
q0 ,
se debería indicar `AA 1' ya que, si recibe el mensaje `AA' transita al estado
numerado como `1'. Para el estado
q2
se ha de indicar `BB 2', ya que, si recibe
el mensaje `BB' transita al estado numerado como `2'. Para el estado
q2
no se
escribiría nada, ya que no tiene transiciones.
El siguiente paso es indicar que los autómatas no tienen ninguna transición más.
Para esto, en el estado
q0
se escribirá el carácter `$' para indicar que no tiene más
transiciones. Para el estado
q1
también se escribirá el carácter `$' por el mismo
motivo.
El último paso es indicar el nombre del autómata. Hasta este punto, las descripciones de todos los estados terminan con el carácter `$'. Para el estado
q2 ,
que es
el estado nal, se ha de indicar el nombre. Para ello, tras el carácter `$' se escribe
el nombre y se indica que el autómata llega a su n con el carácter `*'.
El resultado nal para el autómata de la Figura 4.2 sería un archivo con el siguiente
contenido:
Figura 4.2: Autómata de ejemplo.
72
4. Diseño e implementación
%
0
1
2
Sintaxis del autómata de la Figura 4.2
S N # AA 1 $
N N # BB 2 $
N S $ Ejemplo *
Se muestra ahora un ejemplo más complejo en la Figura 4.3.
Se supondrá que el autómata de la Figura 4.3 se quiere añadir a continuación del
autómata de la Figura 4.2. Los pasos a seguir son:
El estado
q0
se nombrará como `3', ya que el último estado del autómata de la
Figura 4.2 es el estado `2'. Siguiendo esta misma regla, los estados
q1 , q2
y
q3
se
numerarán como `4', `5' y `6' respectivamente.
Los siguientes caracteres para los estados
q0 , q1 , q2
y
q3
serán `S N', `N N', `N N'
y `N S' respectivamente, siguiendo la regla de estados iniciales y nales.
Los separadores para
q0 , q1 , q2
y
q3
son `#', `#', `# y `$' respectivamente, siguiendo
la norma del carácter añadido si tienen transiciones o no.
Los siguientes caracteres para
q0
serán: `AA 4', separador `#', `CC 6', separador
`#', `DD 5', indicador de n de transiciones `$'.
Los siguientes caracteres para
q1
serían: `BB 6', indicador de n de transiciones `$'.
Los siguientes caracteres para
q2
serían: `EE 6', indicador de n de transiciones `$'.
El siguiente carácter para
q3
Por último, en el estado nal
sería: indicador de n de transiciones `$'.
q3
se añadiría: `Ejemplo 2 *', para indicar el nombre
del autómata y su n.
El chero resultante sería el siguiente:
Figura 4.3: Autómata de ejemplo.
73
4. Diseño e implementación
%
0
1
2
%
%
%
%
3
4
5
6
Sintaxis del autómata de la Figura 4.2
S N # AA 1 $
N N # BB 2 $
N S $ Ejemplo *
Sintaxis del autómata de la Figura 4.3
S N # AA 4 # CC 6 # DD 5 $
N N # BB 6 $
N N # EE 6 $
N S $ Ejemplo 2 *
Como se puede apreciar, es sencillo añadir autómatas nuevos en la especicación. Sólo
es necesario continuar las numeraciones de los estados, y añadir, para cada uno de ellos,
sus propiedades y transiciones en una sola línea.
4.2. Descripción de las estructuras de datos utilizadas
En base a la Figura 4.1, la aplicación está construida mediante diversos módulos de
procesamiento, cada uno de ellos destinado a realizar una tarea independiente. El diseño
especíco de la aplicación se corresponde con el detallado en los siguientes apartados.
4.2.1.
Diseño de los estados de los autómatas
Los autómatas de estados nitos están divididos en uno o más estados. Como se explicó
en 2.1, se puede transitar de un estado a otro teniendo en cuenta una serie de palabras
aceptadas. Para realizar el diseño de los estados que componen un autómata, se ha denido una clase a tal efecto. La clase `estado' es la base del funcionamiento de la aplicación.
Agrupa todas las funciones para el manejo de estados de un autómata. Un estado se
considera un conjunto de elementos y está diseñado, en base a sus funcionalidades, de la
siguiente manera:
Un identicador (un número entero) único globalmente. Es decir, dado un identicador, se puede conocer con certeza a qué estado pertenece.
Una variable booleana que indica si el estado es inicial.
Una variable booleana que indica si el estado es nal.
Un nombre que proporciona una descripción de ese estado (una cadena de caracteres).
Un puntero a una estructura `mensaje' (se detalla a continuación).
74
4. Diseño e implementación
Una estructura `mensaje', la cual indica las posibles transiciones que tiene un estado
hacia otros estados y los motivos por los cuales transitaría. Dicha estructura está
compuesta por:
ˆ
ˆ
ˆ
Un motivo por el cual transitaría a otro estado (una cadena de caracteres). En
este caso, un motivo es la recepción de determinados mensajes en el protocolo.
Un puntero a otro mensaje siguiente (puede haberlo o no).
Un puntero hacia el estado al cual transitaría en el caso de que se veriquen
ciertas condiciones relacionadas con un determinado mensaje.
Lo que se implementa es una lista enlazada con los diferentes mensajes que pueden
aparecer en cada estado. De forma esquemática, un estado se asemeja a la estructura
mostrada en la Figura 4.4.
A continuación se muestran una serie de ejemplos para ilustrar el funcionamiento de
la clase `estado'.
Ejemplo 1: Se muestra un autómata con un solo estado. En la Figura 4.5 se muestra
el autómata en cuestión y en la Figura 4.6 se muestra la correspondencia de dicho
autómata con la estructura de datos utilizada.
Ejemplo 2: Autómata con un solo estado. Acepta un número indeterminado de
mensajes identicados con el tipo `44' (Figuras 4.7 y 4.8).
Ejemplo 3: Autómata con tres estados (Figura 4.9). Se muestra el objeto `estado'
para el estado
q0
en la Figura 4.10.
Figura 4.4: Esquema de un objeto de la clase `estado'.
Figura 4.5: Autómata con un estado.
75
4. Diseño e implementación
Figura 4.6: Objeto `estado' para el estado de la Figura 4.5..
Figura 4.7: Autómata con un estado.
Figura 4.8: Objeto `estado' para el estado de la Figura 4.7.
Figura 4.9: Autómata con tres estados.
76
4. Diseño e implementación
Figura 4.10: Objeto `estado' para el estado de la Figura 4.9.
Los métodos que se implementan en esta clase se detallan en el Apéndice A.
4.2.2.
Diseño de los autómatas
Como se explicó en la Sección 2.1, un autómata está formado por uno o más estados.
En base a la especicación de los autómatas indicada en el archivo de entrada del programa principal, pueden existir cero o más autómatas en la aplicación. La clase `automatas'
alberga todos los que se han denido. Es decir, esta clase contendrá un conjunto de estados entrelazados entre sí mediante punteros. Es por esto que la clase `estado' es una
generalización de `automatas' o, dicho de otra manera, se dice que la clase `automatas'
hereda (o es una especicación) de la clase `estado'. El motivo de esto es, como se ha explicado, que la clase `automatas' está compuesta por un número determinado de estados.
Por tanto, esta clase debe tener conocimiento de cómo es un objeto `estado', así como de
todas sus funciones, para poder manejarlo con otras funciones más especícas y poder
proporcionar un nivel de encapsulado mayor.
Una instanciación de la clase `automatas' está compuesta simplemente por un vector
dinámico, en el que cada casilla alberga un objeto `estado'. El desplazamiento de un
estado a otro mediante los punteros que se encuentran dentro de sus mensajes equivaldría
a moverse a través de las casillas de este vector dinámico.
Por tanto, con un objeto de la clase `automatas' se puede representar por completo un
conjunto de autómatas reales y comprobar su funcionamiento.
Los métodos pertenecientes a esta clase se detallan en el Apéndice A.
4.2.3.
Diseño de un ujo de información
Como se explicó en la Sección 2.2, una conexión entre dos
peers
se identica median-
te cuatro elementos: Las IP origen y destino y los puertos origen y destino. La clase
`datosFlujo' se basa en la existencia de ujos de información dentro de una conexión
entre cliente y servidor, o bien entre dos clientes. En el protocolo UDP, también existen
estas características, pero no se necesita un establecimiento de conexión previo ni una
nalización como ocurre en el contexto TCP. Por tanto, la estructura de datos es igualmente válida para los dos protocolos. Mediante estos ujos, los
peers
intercambian cierta
cantidad de información relacionada con el protocolo.
77
4. Diseño e implementación
La clase `datosFlujo' incluirá la información de dichos ujos, junto con otra añadida ya
que, como se explicará más adelante, es necesario tener en cuenta el momento en el que
ocurren cambios en el ujo de información y qué información se está intercambiando.
Por lo tanto, esta clase tendrá los siguientes elementos:
Una cadena de caracteres donde se almacenará la IP origen.
Una cadena de caracteres donde se almacenará la IP destino.
Un número entero indicando el puerto origen.
Un número entero indicando el puerto destino.
Una variable en coma otante de doble precisión para indicar el momento (times-
tamp )
en el que suceden cambios en un determinado ujo de información. Estos
cambios se reeren a la adición de información nueva a un objeto de esta clase; en
el momento en el que se añada algún dato nuevo, se considerará que se ha producido un cambio y se actualizará el
timestamp.
Esta variable es útil para determinar
cuándo un ujo es antiguo y puede ser analizado.
Un vector de cadenas de caracteres en el que se almacenará, con el paso del tiempo, la información intercambiada entre dos
peers
dentro de la misma conexión, es
decir, contendrá determinados datos del protocolo. Estos datos son los tipos de los
mensajes intercambiados.
Por tanto, la estructura de un objeto de la clase `datosFlujo' será la de la Figura 4.11.
Los métodos pertenecientes a esta clase se detallan en el Apéndice A.
4.2.4.
Diseño del almacén/clasicador de ujos
Como en el tráco proporcionado por el sensor es muy probable que existan numerosas conexiones (y por tanto, numerosos ujos de información), es necesario un almacén/clasicador de ujos global que almacene toda esta información. La clase `clasicadorFlujos' se ha diseñado con tal n, ya que es capaz de almacenar un conjunto de objetos
de la clase `datosFlujo'. Es decir, la clase `clasicadorFlujos' tiene una sola variable miembro, consistente en un vector dinámico (es decir, que varía su tamaño dinámicamente)
en el que en cada casilla almacena un objeto de la clase `datosFlujo'.
Esto explica la herencia entre estas dos clases: la clase `datosFlujo' es una generalización de la clase `clasicadorFlujos', ya que esta última está formada por un número
determinado de objetos de la clase `datosFlujo'. Por ello, es necesario que sepa manejarlos,
conozca todas sus funciones y sus variables miembro, ya que va a necesitar modicarlos
para darle una estructura de un almacén/clasicador aparente, y mostrar un mayor grado
de encapsulado y simplicidad a la hora de utilizar un objeto de esta clase.
También existe una relación de agregación de composición entre la clase `autómatas'
y la clase `clasicadorFlujos', ya que la primera está compuesta de elementos de la clase
`clasicadorFlujos', aunque sólo está formado por uno.
Es decir, la relación básica entre las clases sería la mostrada en la Figura 4.12.
78
4. Diseño e implementación
Figura 4.11: Estructura de un objeto de la clase `datosFlujo'.
Figura 4.12: Relaciones entre las clases diseñadas.
4.2.5.
Diagrama de clases
Partiendo de las estructuras de datos detalladas anteriormente, se puede elaborar un
diagrama completo que muestre los métodos y las relaciones entre las clases. En la Figura
4.13 se muestra el diagrama detallado el cual representa la elaboración de clases dentro de
la aplicación que se ha desarrollado. En él se pueden distinguir varios elementos: las clases
diseñadas, las relaciones entre ellas, las variables miembro y los métodos implementados
en cada una de ellas.
Existen dos relaciones de herencia principales, las cuales se ven reejadas en el diagrama
de clases de diseño:
La primera de ellas es una generalización de la clase `automatas' a la clase `estado' y la segunda es una generalización de la clase `clasicadorFlujos' a la clase
`datosFlujo'.
La segunda de las relaciones es una agregación de composición, o solamente composición entre la clase `clasicadorFlujos' y `automatas'. El motivo de eso es que
la clase `automatas' está compuesta por elementos del tipo `clasicadorFlujos'. La
multiplicidad de los extremos indica que debe existir un objeto de la clase `automatas' para que exista un objeto de la clase `clasicadorFlujos', y sólo existirá
uno.
79
4. Diseño e implementación
Figura 4.13: Diagrama de clases de diseño para la aplicación desarrollada.
80
Capı́tulo
5
Evaluación
El objetivo de este capítulo es comprobar el buen funcionamiento de la aplicación. Para
ello, primero se muestran una serie de pruebas a ejecutar, que vericarán su buen funcionamiento. Por último, se realizarán pruebas para medir la velocidad y el rendimeinto
de la aplicación.
5.1. Diseño de las pruebas de evaluación
Con el objetivo de facilitar la evaluación de la aplicación, se han elaborado una serie
de chas de pruebas para la aplicación, las cuales se detallan a continuación.
Las pruebas se han diseñado de manera que pueda probarse las funcionalidad de la
aplicación. Por ello, se comienza con pruebas simples para avanzar en pruebas de mayor
complejidad, que requieran más carga computacional.
Con las pruebas propuestas se pretende evaluar el buen funcionamiento de la aplicación,
es decir, comprobar que, para una serie de cheros con trazas de tráco, es capaz de
reconocer ujos de información acordes con la especicación de autómatas introducida.
En las pruebas propuestas se muestra la conguración del chero de autómatas y se
introducirán cheros con trazas de tráco, adquiridos en situaciones controladas, por lo
que también se detallará el resultado esperado. Asimismo, se muestra el contenido de los
cheros con trazas de tráco, para poder comprender mejor los resultados obtenidos.
Es muy importante destacar que las versiones de los autómatas realizados son una
mera referencia, puesto que la versión indicada puede no coincidir con la actual. La
especicación de autómatas está escrita para versiones del cliente `eMule' del año 2008,
aunque también incluye algunas del año 2009.
Los cheros de prueba son los siguientes:
1.
1-establecimiento_conexion.pcap.
2.
2-buscar.pcap.
3.
3-cliente_cliente.pcap.
81
5. Evaluación
4.
4-de_todo.pcap.
En la Figura 5.1 se muestra una tabla con un resumen estadístico de los cheros de
prueba.
5.1.1.
Ficheros de trazas
Son cheros con trazas de tráco que se han obtenido en determinadas situaciones.
Para ello, se ha hecho uso de la aplicación `wireshark' y `eMule' (véase Capítulo 2).
Fichero 1
Este chero contiene los mensajes intercambiados entre dos
peers
cliente y servidor,
los cuales realizan un establecimiento de conexión.
En la Figura 5.2 se muestran las estadísticas del uso de protocolos en el chero. En
este chero existen ujos asociados con el establecimiento de conexión entre un cliente y
un servidor.
Fichero 2
El segundo de los cheros de prueba se corresponde con el tráco producido entre un
cliente y un servidor con motivo de una búsqueda de archivos, por lo que existirán ujos
asociados con las búsquedas de archivos. En la Figura 5.3 se muestran estadísticas en el
uso de protocolos.
Fichero
Tiempo entre el primer
Bytes totales
y el último paquete
transmitidos
18
0.368 s.
2306
2
4
2.161 s.
345
3
180
2.560 s.
19984
4
4959
232.919 s.
1672320
1
Paquetes capturados
Figura 5.1: Estadísticas generales de los cheros de prueba.
º
Figura 5.2: Estadísticas del uso de protocolos para el chero de pruebas n 1.
82
5. Evaluación
º
Figura 5.3: Estadísticas del uso de protocolos para el chero de pruebas n 2.
Fichero 3
El tercer chero corresponde con el tráco producido en una conexión entre dos clientes.
Es algo más complejo, puesto que contiene más cantidad de tráco que los ejemplos
anteriores. En él existen ujos asociados a la conexión entre dos clientes, como puede ser
handshakes
iniciales. En la Figura 5.4, al igual que en los ejemplos anteriores, se muestra
las estadísticas del uso de protocolos.
Fichero 4
Para nalizar, el último de los cheros contiene una gran cantidad de trazas de tráco,
ya que contiene mensajes de todo tipo, tanto de cliente-cliente, como de cliente-servidor,
por lo que existen ujos de todo tipo, estos pueden ser, establecimiento de conexión,
secuencia de inicio de conexión, etc. En la Figura 5.5 las estadísticas del uso de protocolos.
5.1.2.
Prueba 1
º
La prueba se realizará con el chero n 2. El archivo de descripción de autómatas
contiene el autómata correspondiente a Búsqueda de archivos mostrado en la Figura
5.6, por lo que el contenido del chero es el siguiente:
º
Figura 5.4: Estadísticas del uso de protocolos para el chero de pruebas n 3.
83
5. Evaluación
º
Figura 5.5: Estadísticas del uso de protocolos para el chero de pruebas n 4.
Figura 5.6: Autómata correspondiente a Búsqueda de archivos.
%
0
1
2
%
Búsqueda de archivos
S N # 16 1 $
N N # 33 2 $
N S $ Busqueda de archivos *
Como se puede ver, en la especicación de autómatas se ha incluido información
suciente como para que el contenido del chero de trazas sea reconocido, por lo que se
espera que se reconozcan todos los ujos.
5.1.3.
Prueba 2
En esta prueba se incluirán en la especicación de autómatas algunos nuevos. Estos
º
son, Establecimiento de conexión, Secuencia de inicio de conexión y Búsqueda de
archivos. Se ejecutará con el chero n 1. Los autómatas introducidos son en el chero
de especicación son los mostrados en las Figuras 5.7, 5.8 y 5.9, por lo que el contenido
del chero es el siguiente:
Figura 5.7: Autómata correspondiente a Establecimiento de conexión.
84
5. Evaluación
Figura 5.8: Autómata correspondiente a Secuencia de inicio de conexión.
Figura 5.9: Autómata correspondiente a Búsqueda de archivos.
% Establecimiento de conexión
0 S N # 01 1 $
1 N N # 40 2 $
2 N N # 34 3 $
3 N S $ Establecimiento de conexion *
%
%
% Secuencia de inicio de conexión
4 S N # 14 5 $
5 N N # 32 6 $
6 N N # 41 7 $
7 N S $ Secuencia de inicio de conexion *
%
%
% Handshake inicial
8 S N # 01 9 $
9 N N # 4C 10 $
10 N S $ Handshake inicial * %
%
Según la especicación indicada, el resultado esperado es que se reconozcan todos
los ujos que existe en las trazas de tráco, ya que la especicación de los autómatas
supuestamente incluye información suciente.
5.1.4.
Prueba 3
Se tomará el chero de pruebas y la misma especicación de autómatas que en la
Prueba 2, con una modicación, ya que en el chero de trazas de tráco se borrará uno
de los mensajes. Este mensaje será aquel que contiene los mensajes con campo tipo con
los valores `32' y `41' correspondientes a la Figura 5.8. El resultado esperado es que el
ujo correspondiente a este autómata no se reconozca. No se mostrará como incompleto
porque no se cumple el requisito de reconocer el 80 % de los mensajes.
85
5. Evaluación
5.1.5.
Prueba 4
En esta prueba se utilizará también el mismo procedimiento que en la Prueba 3, pero
en este caso se desea comprobar el reconocimiento de los ujos incompletos.
En el código fuente está indicado que un autómata se considera incompleto cuando
se reconocen más del 80 % de los estados. Para poder probar esto, este dato sufrirá una
modicación y se disminuirá al 30 %. De esta manera, el ujo que en la Prueba 4 no se
reconocía, ahora se espera que se muestre como incompleto, en lugar de no reconocido.
5.1.6.
Prueba 5
Ahora la especicación de autómatas es algo más completa, ya que su contenido será el
mostrado en las Figuras 5.10, 5.11, 5.12, 5.13, 5.14 y 5.15. Los autómatas añadidos han
sido Búsqueda de archivos, Nueva secuencia de inicio de conexión y Ofrecer cheros.
Por tanto, el contenido del chero es el siguiente:
Figura 5.10: Autómata correspondiente a Establecimiento de conexión.
Figura 5.11: Autómata correspondiente a Secuencia de inicio de conexión.
Figura 5.12: Autómata correspondiente a Búsqueda de archivos.
Figura 5.13: Autómata correspondiente a Handshake inicial.
86
5. Evaluación
Figura 5.14: Autómata correspondiente a Nueva secuencia de inicio de conexión.
Figura 5.15: Autómata correspondiente a Ofrecer cheros.
% Establecimiento de conexión
0 S N # 01 1 $
1 N N # 40 2 $
2 N N # 34 3 $
3 N S $ Establecimiento de conexion *
%
%
% Secuencia de inicio de conexión
4 S N # 14 5 $
5 N N # 32 6 $
6 N N # 41 7 $
7 N S $ Secuencia de inicio de conexion *
%
%
% Búsqueda de archivos
8 S N # 16 9 $
9 N N # 33 10 $
10 N S $ Busqueda de archivos *
%
%
% Handshake inicial
11 S N # 01 12 $
12 N N # 4C 13 $
13 N S $ Handshake inicial *
%
%
% Nueva secuencia de inicio de conexión
14 S N # 38 15 $
15 N N # 14 16 $
16 N N # 32 17 $
87
5. Evaluación
17 N N # 41 18 $
18 N S $ Nueva secuencia de inicio de conexion *
%
%
% Ofrecer ficheros
19 S N # 15 20 $
20 N S $ Ofrecer ficheros *
%
º
El chero utilizado en este caso es el n 3. Ya que el contenido del chero es bastante
amplio y no se conoce a priori la cantidad de ujos existentes, se espera que se reconozcan
los ujos asociados con los autómatas especicados, ya que, en el escenario contemplado
en el chero de pruebas, se intercambia bastante información. De toda esta información,
el chero de autómatas sólo la contiene parcialmente.
5.1.7.
Prueba 6
º
En esta prueba se utilizará la misma especicación de autómatas que en la Prueba 5.
En este caso, el chero utilizado es el n 4, el cual contiene trazas de tráco de todo tipo.
En este caso, tampoco se conoce a priori su contenido pero, dada la especicación de
los autómatas, se considera que se reconocerán los ujos existentes que se correspondan
º
con la especicación en el chero de autómatas. De la misma manera que en la Prueba 5,
en el chero n 4 se intercambia gran cantidad de información, de la cual sólo se especica
una parte de ella en el chero de especicación de autómatas.
5.1.8.
Prueba 7
º º º
º
Con el n de comprobar el buen funcionamiento de la concurrencia de la aplicación,
se realizará la evaluación de la aplicación para los cheros n 1, n 2, n 3 y n 4 al mismo
tiempo. El contenido del chero de autómatas es el mismo que en la Prueba 5. El resultado
debe ser unas estadísticas generales de la unión de todos los cheros por separado.
5.2. Evaluación de la funcionalidad de la aplicación
En esta sección se ha evaluado la funcionalidad de la aplicación para cada una de las
chas de prueba elaboradas anteriormente.
5.2.1.
Resultados para la Prueba 1
En este caso, el resultado mostrado por la aplicación es el siguiente:
IP origen: 192.168.1.4
IP destino: 87.230.83.44
Puerto origen: 34763
88
5. Evaluación
Puerto destino: 4661
Flujo observado: 16 33
Flujo reconocido: Busqueda de archivos
--------------------------------------------------------------------Numero de flujos totales: 1
Porcentaje de flujos reconocidos: 100 %
Porcentaje de flujos no reconocidos: 0 %
Porcentaje de flujos incompletos: 0 %
--------------------------------------------------------------------5.2.2.
Resultados para la Prueba 2
Ahora, el resultado mostrado por la aplicación para esta prueba es el siguiente:
IP origen: 87.230.83.44
IP destino: 192.168.1.4
Puerto origen: 34648
Puerto destino: 36121
Flujo observado: 01 4C
Flujo reconocido: Handshake inicial
---------------IP origen: 192.168.1.4
IP destino: 87.230.83.44
Puerto origen: 43742
Puerto destino: 4661
Flujo observado: 01 40 34
Flujo reconocido: Establecimiento de conexion
---------------IP origen: 192.168.1.4
IP destino: 87.230.83.44
Puerto origen: 43742
Puerto destino: 4661
Flujo observado: 14 32 41
Flujo reconocido: Secuencia de inicio de conexion
--------------------------------------------------------------------Numero de flujos totales: 3
Porcentaje de flujos reconocidos: 100 %
Porcentaje de flujos no reconocidos: 0 %
Porcentaje de flujos incompletos: 0 %
--------------------------------------------------------------------Como se puede observar, cuanto más grande es el chero y más paquetes contiene,
más ujos son detectados en su interior. En esta prueba, se han reconocido todos los
ujos observados en el chero de trazas. Se puede comprobar que un establecimiento de
89
5. Evaluación
conexión implica tres ujos de información y, por tanto, tres autómatas ya modelados
anteriormente. A modo ilustrativo, en la Figura 5.16 se puede observar con
wireshark,
como se puede ver en [17] el contenido de una trama de este chero, cuyo campo tipo
es `01'.
5.2.3.
Resultados para la Prueba 3
En este caso, la salida de la aplicación muestra lo siguiente:
IP origen: 87.230.83.44
IP destino: 192.168.1.4
Puerto origen: 34648
Puerto destino: 36121
Flujo observado: 01 4C
Flujo reconocido: Handshake inicial
---------------IP origen: 192.168.1.4
IP destino: 87.230.83.44
Puerto origen: 43742
Puerto destino: 4661
Flujo observado: 01 40 34
Flujo reconocido: Establecimiento de conexion
---------------IP origen: 192.168.1.4
Figura 5.16: Muestra de una trama `eDonkey' con Wireshark.
90
5. Evaluación
IP destino: 87.230.83.44
Puerto origen: 43742
Puerto destino: 4661
Flujo observado: 14
Flujo no reconocido
--------------------------------------------------------------------Numero de flujos totales: 3
Porcentaje de flujos reconocidos: 66.6667 %
Porcentaje de flujos no reconocidos: 33.3333 %
Porcentaje de flujos incompletos: 0 %
--------------------------------------------------------------------La ejecución de la aplicación ha mostrado los resultados esperados. La traza borrada,
como se puede comprobar, contenía dos mensajes `eDonkey': uno con tipo `32' y otro con
tipo `41'. Por tanto, el ujo no es reconocido, ya que no hay información suciente, y el
resultado es el esperado.
5.2.4.
Resultados para la Prueba 4
Para ejecutar esta prueba, se modicará el porcentaje que establece cuándo un autómata es incompleto al 30 %. De manera que, utilizando el chero de pruebas indicado, el
resultado es el siguiente:
IP origen: 87.230.83.44
IP destino: 192.168.1.4
Puerto origen: 34648
Puerto destino: 36121
Flujo observado: 01 4C
Flujo reconocido: Handshake inicial
---------------IP origen: 192.168.1.4
IP destino: 87.230.83.44
Puerto origen: 43742
Puerto destino: 4661
Flujo observado: 01 40 34
Flujo reconocido: Establecimiento de conexion
---------------IP origen: 192.168.1.4
IP destino: 87.230.83.44
Puerto origen: 43742
Puerto destino: 4661
Flujo observado: 14
Flujo incompleto
---------------------------------------------------------------------
91
5. Evaluación
Numero de flujos totales: 3
Porcentaje de flujos reconocidos: 66.6667 %
Porcentaje de flujos no reconocidos: 0 %
Porcentaje de flujos incompletos: 33.3333 %
--------------------------------------------------------------------Como se puede observar, la salida muestra un resultado esperado ya que, cambiando el
criterio de ujos incompletos, se ha conseguido que se reconozca la modicación realizada
en el chero de trazas.
5.2.5.
Resultados para la Prueba 5
En este caso, se mostrará sólo el resultado de las estadísticas de la salida del programa,
ya que el resto del contenido es bastante extenso, del cual se muestra un resumen en le
Figura 5.17:
--------------------------------------------------------------------Numero de flujos totales: 18
Porcentaje de flujos reconocidos: 44.4444 %
Porcentaje de flujos no reconocidos: 55.5556 %
Porcentaje de flujos incompletos: 0 %
--------------------------------------------------------------------Como se puede observar, el resultado es aproximado al esperado. Con una especicación
de autómatas simple, se han logrado reconocer el 44.44 % de los ujos observados, todos
ellos relacionados con el chero de especicación de autómatas.
5.2.6.
Resultados para la Prueba 6
Una vez más, se muestran sólo los resultados estadísticos de la salida, puesto que los
ujos observados en el chero de trazas es extenso. Los resultados son los siguientes, y
un resumen de la salida es el mostrado en la Figura 5.18:
--------------------------------------------------------------------Numero de flujos totales: 200
Porcentaje de flujos reconocidos: 50 %
Autómata
Handshake
inicial
Flujos no reconocidos
Número de veces observado
8
10
Figura 5.17: Salida observada para la Prueba 5.
92
5. Evaluación
Autómata
Handshake
inicial
Número de veces observado
92
Establecimiento de conexión
3
Secuencia de inicio de conexión
3
Búsqueda de archivos
2
Flujos no reconocidos
100
Figura 5.18: Salida observada para la Prueba 6.
Porcentaje de flujos no reconocidos: 50 %
Porcentaje de flujos incompletos: 0 %
--------------------------------------------------------------------Como se puede observar, la cantidad de ujos observados es considerable. El resultado
mostrado en la salida era predecible, ya que, de un chero extenso, se reconocen los ujos
que se corresponden con los autómatas especicados. Estos son el 50 % de todos los ujos
observados en el chero de pruebas.
5.2.7.
Resultados para la Prueba 7
En esta última prueba, los resultados han sido los siguientes, y un resumen de la salida
observada se muestra en la Figura 5.19:
--------------------------------------------------------------------Numero de flujos totales: 222
Porcentaje de flujos reconocidos: 50.4505 %
Porcentaje de flujos no reconocidos: 49.5495 %
Porcentaje de flujos incompletos: 0 %
--------------------------------------------------------------------Prestando atención al número de ujos totales, se puede vericar que coincide con la
suma de los ujos observados de los cheros analizados por separado. Las estadísticas
son globales a todos los ujos, por lo que la concurrencia de la aplicación funciona tal y
como se esperaba.
Autómata
Handshake
inicial
Número de veces observado
101
Establecimiento de conexión
4
Secuencia de inicio de conexión
4
Búsqueda de archivos
3
Flujos no reconocidos
110
Figura 5.19: Salida observada para la Prueba 7.
93
5. Evaluación
5.2.8.
Conclusiones de la evaluación de funcionalidades
Salvo la prueba 1 (y en parte la prueba 2) los resultados de la aplicación son bastante
positivos. En una situación real de tráco P2P producido por el protocolo `eDonkey'
se han reconocido el 50'4505 % (analizando todos los cheros de trazas de prueba con
un número reducido de autómatas) de los autómatas, que es prácticamente la mitad.
Teniendo en cuenta que el chero de especicación de autómatas contenía solamente
detalles de seis de ellos, el porcentaje de reconocimiento es bastante alto. Completando
el chero de especicación se lograría un comportamiento mucho más able.
El principal inconveniente de la especicación de autómatas es la continua actualización
del protocolo `eDonkey', que convierte dichas especicaciones en obsoletas en relativamente poco tiempo. Por tanto, sería interesante un módulo en la aplicación que fuera
capaz de deducir el comportamiento del protocolo `eDonkey' simplemente en base a su
funcionamiento, de manera que pudiera elaborar los patrones de reconocimiento por sí
solo.
5.3. Evaluación del rendimiento de la aplicación
A continuación, se muestran medidas del rendimiento de la aplicación. Para poder
medir tiempos de ejecución, se ha utilizado la herramienta
time
de Linux, la cual ofrece
información precisa de los tiempos de ejecución de los programas. En la Figura 5.20
se muestra una tabla en la que se miden los tiempos de ejecución de cada una de las
pruebas. Como se puede observar, los tiempos mostrados son bastante bajos, incluso con
los cuatro cheros de prueba ejecutándose simultáneamente. Esto prueba la eciencia de
las hebras ya que, incluso con cheros grandes, los resultados en tiempo son buenos.
Otra de las medidas de rendimiento realizadas con la aplicación, es el análisis de los
cuellos de botella existentes. Conociendo este dato, se podría realizar una mejora que
disminuyera los tiempos de ejecución.
En la Figura 5.21 se muestra un árbol de llamadas, realizado mediante VTune, como
se puede consultar en [16], con la actividad que producen dichas llamadas que se hacen
durante la ejecución de la aplicación. Las pruebas se han realizado para la ejecución del
programa con los datos de la cha de la Prueba 8, ya que contiene un gran número de
trazas y las llamadas se realizan de manera multihebrada, por lo que proporciona unas
mejores estimaciones en los resultados.
En el grafo de la Figura 5.21 se muestra el árbol de llamadas resultado de la ejecución
de la aplicación. La función que más llamadas produce es
pthread_join(),
función que
se utiliza para unir hebras. Dada la naturaleza multihebrada del programa y de la cha
de prueba utilizada, es lógico vericar este hecho. Asimismo, se muestran enmarcadas en
rojo las funciones que más tiempo consumen del total de la ejecución del programa.
En la Figura 5.22 se muestra el porcentaje de
ticks
de reloj que consumen determina-
das llamadas al programa. Como se puede apreciar en dicha gura, la función que más
ticks
consume está relacionada con el almacén/clasicador existente, debido a que esta
estructura es utilizada por varios módulos y está siendo continuamente actualizada, como
se vio anteriormente. También se proporciona un detalle preciso del porcentaje de
ticks
94
5. Evaluación
de reloj que ha ejecutado cada procesador del computador en el que se ejecuta.
Prueba
Tiempo de ejecución
1
0.004 s.
2
0.004 s.
3
0.004 s.
4
0.004 s.
5
0.004 s.
6
0.012 s.
7
0.472 s.
8
0.536 s.
Figura 5.20: Tiempos de ejecución de las pruebas realizadas.
Figura 5.21: Actividad del grafo de llamadas.
Figura 5.22: Mediciones de tiempos para algunos métodos de la aplicación.
95
5. Evaluación
5.3.1.
Conclusiones de la evaluación del rendimiento
Como se ha mostrado anteriormente, se han realizado una serie de pruebas de rendimiento a la aplicación desarrollada. Analizando los cuellos de botella de la aplicación, se
puede concluir que una posible optimización residiría en tratar de reducir el número de
hebras utilizadas en el almacén/clasicador general, ya que es la parte que más tiempo
consume.
Por otro lado, resulta inevitable constatar que, si se reduce el número de hebras,
probablemente aumentaría la carga de trabajo de otros módulos. Por lo tanto, aunque
las hebras consuman una gran cantidad de tiempo de la ejecución del programa, la
programación multihebrada es una buena solución. Los buenos tiempos mostrados se
deben, en parte, a optimizaciones del compilador realizadas.
96
Capı́tulo
6
Planicación y estimación de recursos
En este capítulo se mostrará la planicación inicial que se hizo para el proyecto, así
como los recursos utilizados en él. Por último, se muestra un estudio económico realizado.
6.1. Planicación
Para poder calcular la duración del proyecto, inicialmente se dividió en una serie de
tareas con una duración aproximada. Las tareas se dividen en las siguientes:
Planicación: En ella se realizaba una planicación inicial de la duración estimada
del proyecto. No es una tarea sencilla calcular a priori dicha duración, por lo que
se incluye un punto de replanicación, en el que se replanteaban objetivos y se
modicaban las asignaciones de tiempo.
Estudio del arte: En este estudio, el objetivo es familiarizarse con el proyecto y las
materias relacionadas. Por ello, es necesario realizar un estudio de estos puntos y,
al nal, entregar una parte de documentación referente a lo estudiado.
Desarrollo y análisis: En esta sección se realiza el análisis del protocolo `eDonkey', así como el diseño de la solución propuesta. Realización de una parte de la
documentación con esta información detallada. Programación de la aplicación.
Pruebas: Fase en la que se realiza la evaluación de la aplicación desarrollada, a n
de vericar su funcionamiento e ilustrarlo mediante algunos ejemplos.
Documentación: Capítulo nal en el que se documenta debidamente los pasos seguidos y la motivación para el desarrollo del proyecto. Entrega de la documentación
nal.
En la Figura 6.1 se muestran estas tareas, mientras que en la Figura 6.2 se muestran el
diagrama de Gantt correspondiente.
97
6. Planicación y estimación de recursos
Figura 6.1: Esquema de las tareas inicialmente planicadas.
98
6. Planicación y estimación de recursos
Figura 6.2: Diagrama de Gantt.
99
6. Planicación y estimación de recursos
6.2. Recursos
Los recursos utilizados se pueden clasicar en tres bloques, atendiendo a su naturaleza.
6.2.1.
Recursos software
Sistema operativo Ubuntu 8.04 Hardy Heron.
Editor de imágenes GIMP.
Gestor de proyectos Planner.
Editor para L TEX: LYX 1.6.3.
Microsoft Oce 2007.
Wireshark (véase [17]).
Cliente eMule (véase [18]).
Herramienta para documentación de código Doxygen (véase [20]).
Herramienta para dibujar diagramas estructurados Dia 0.96.1.
Editor de textos KWrite.
Compilador gcc.
Herramienta de creación de autómatas JFlap.
A
6.2.2.
Recursos hardware
PC con procesador Intel Centrino Duo 2 GHz con 1GB de memoria principal y 200
GB de disco duro.
Tarjeta de red Intel ipw3945abg.
6.2.3.
Recursos humanos
Dos profesores del Departamento de Teoría de la Señal, Telemática y Comunicaciones de la Escuela Técnica Superior de Ingenierías Informática y Telecomunicación
de la Universidad de Granada, como directores del proyecto.
Un alumno de Ingeniería Informática de la Escuela Técnica Superior de Ingenierías
Informática y Telecomunicación de la Universidad de Granada, como desarrollador
del proyecto.
6.3. Estudio económico
A continuación se muestra un análisis de costes asociado al desarrollo de la aplicación.
100
6. Planicación y estimación de recursos
6.3.1.
Costes asociados a los materiales
Respecto a los costes de los materiales, será necesario incluir los costes asociado al
equipo informático utilizado en la realización del proyecto. Este se calculará mediante el
prorrateo del coste del propio equipo entre un tiempo, el cual se ha estimado que sean
cuatro años, ya que se trata de un equipo informático que se calcula se volverá obsoleto
tras ese período.
Por tanto, sabiendo que el equipo informático tuvo un precio original de 200
¿
¿
, y
teniendo en cuenta que la duración de la realización del proyecto es de, aproximadamente,
300 días, esto sumaría un total de 410.51
¿
a abonar en concepto de materiales.
Adicionalmente, se incluyen los gastos correspondientes a licencias software, los cuales
sumarían un total de 1000
6.3.2.
.
Costes de mano de obra
La estimación de los costes se calculará en base al tiempo aproximado empleado en la
realización del proyecto.
En España, cada día tiene disponibles 8 horas laborables y esto es lo que consideraremos.
A continuación se detallan todas las fases del proyecto, cada una con el tiempo estimado
de duración:
Planicación:
ˆ
ˆ
ˆ
Planicación inicial: 72 horas.
Corrección de la planicación: 40 horas.
Elaboración de presupuesto: 56 horas.
Estudio del arte:
ˆ
ˆ
ˆ
Estudio de los protocolos implicados: 136 horas.
Elección de las aplicaciones a estudiar y justicación: 56 horas.
Estudio del funcionamiento de las aplicaciones elegidas: 280 horas.
Desarrollo y análisis:
ˆ
ˆ
ˆ
Captura de tráco P2P: 56 horas.
Estudio del tráco generado por aplicaciones estudiadas en base al tráco
capturado: 264 horas.
Establecimiento de patrones en función del funcionamiento de las aplicaciones
P2P: 240 horas.
Pruebas:
ˆ
Vericación del funcionamiento de la aplicación desarrollada: 640 horas.
Documentación:
101
6. Planicación y estimación de recursos
ˆ
ˆ
ˆ
ˆ
ˆ
Descripción del funcionamiento de los protocolos propios de la arquitectura
TCP/IP: 80 horas.
Descripción del funcionamiento de las aplicaciones elegidas en base a sus protocolos: 120 horas.
Descripción del funcionamiento de las aplicaciones elegidas en base al tráco
que generan: 160 horas.
Descripción de los patrones elaborados en base al tráco de las aplicaciones:
120 horas.
Estudio económico: 80 horas.
Total: 2400 horas.
¿
Teniendo en cuenta la duración considerada del proyecto, el precio total correspondiente
a la mano de obra, sería de 120000
6.3.3.
.
Otros costes
Se incluirán los costes asociados a reuniones con el cliente, tanto para comprender las
especicaciones iniciales del proyecto, como para dialogar con el susodicho cliente acerca
del transcurso del proyecto para la resolución de posibles dudas y/o potenciales mejoras.
Se calcula que, a lo largo del tiempo estimado de realización del proyecto, se realizarán
15 reuniones, cada una de 1 hora de duración.
¿
Dado que se estima que el precio de trabajo de una hora es de 50
coste asociado a las reuniones sería de 750
6.3.4.
.
Total
La suma total correspondería a un total de 120750
¿
, la suma total del
¿
.
102
Capı́tulo
7
Logros y conclusiones
En esta sección se indican los logros obtenidos mediante la realización del proyecto,
así como las conclusiones a las que se ha podido llegar.
7.1. Logros
Comprender el funcionamiento del protocolo `eDonkey'.
Entender el funcionamiento de las redes
Entender el funcionamiento de los autómatas de estados nitos.
Aprender a modelar comportamientos de protocolos mediante autómatas de estados
peer-to-peer.
nitos.
Lograr diseñar una aplicación que sea capaz de realizar un proceso de determinada
información mediante autómatas de estados nitos.
Conocer el funcionamiento de la aplicación
Wireshark,
y cómo trata cada tipo de
trama.
Comprender el funcionamiento de la herramienta
VTune
para la realización de
análisis de rendimiento de aplicaciones.
Aprender cómo afrontar un proyecto de cierta envergadura y realizar una buena
documentación.
7.2. Conclusiones
Las herramientas de modelado de protocolos mediante autómatas de estados nitos
son ecaces para la detección de anomalías en dichos protocolos. Sin embargo, es
una tarea complicada denir completamente todo el comportamiento (diseñar los
autómatas).
103
7. Logros y conclusiones
El protocolo `eDonkey' es un protocolo difícil de modelar, ya que surgen versiones
nuevas con el paso de los meses. Por ello, una determinada especicación podría
quedar obsoleta en poco tiempo.
Una posible mejora sería, como se comentó anteriormente, un módulo capaz de
aprender por sí mismo el comportamiento de un determinado protocolo, para evitar
el trabajo de la especicación de autómatas.
104
Bibliografía
[1] http://www.techcrunch.com/2009/01/23/comscore-internet-population-passes-onebillion-top-15-countries/
[2] http://www.ipoque.com/resources/internet-studies/internet-study-2007.
[3] Wai-Sing Loo, A. (2007): Peer-to-peer
Web Technologies .
Springer. ISBN: 1846283817, 9781846283819.
[4] Wang, W. (2004): Steal
sharing .
Computing: Building Supercomputers with
this le sharing book: what they won't tell you about le
No Starch Press. ISBN: 159327050X, 9781593270506.
[5] Millán Tejedor, R. J. (2006): Las
redes P2P (peer to peer) .
Creaciones Copyright.
ISBN: 849630020X, 9788496300200.
[6] Hemmje, M.; Neuhold, E. J.; Niederee, C; Risse, T. (2005): From
integrated publication and information systems to virtual information and knowledge environments .
Springer. ISBN: 3540245510, 9783540245513.
[7] Asensio Asensio, G. (2006): Seguridad
en Internet . Ediciones Nowtilus S.L. ISBN:
8497632931, 9788497632935.
[8] Barnard, R. L. (1988): Intrusion
Detection Systems . Gulf Professional Publishing.
ISBN: 0750694270, 9780750694278.
[9] Kulbak, Y.; Bickson, D; Kirkpatrick, S. (2004): The
eMule protocol specication .
School of Computer Science and Engineering.The Hebrew University of Jerusalem,
Jerusalem.
[10] http://decsai.ugr.es/%7Esmc/docencia/mci/automata.pdf
[11] García Teodoro, P.; Díaz Verdejo, J. E.; López Soler, J. M. (2003): Transmisión
Datos y Redes de Computadores .
[12] Larman, C. (2006): UML
Prentice Hall. ISBN: 9788420539195.
y Patrones .
Prentice Hall. ISBN: 8420534382.
105
de
Bibliografía
[13] Robson, R. (2000): Using
the STL: the C++ standard template library .
Springer.
ISBN: 0387988572, 9780387988573.
[14] Josuttis, N. M. (2002): The
C++ Standard Library: A Tutorial and Reference .
Addison-Wesley. ISBN: 0201379260, 9780201379266.
[15] López
Monge,
A.
(2005):
Aprendiendo
a programar con Libpcap .
URL:
http://www.e-ghost.deusto.es/docs/2005/conferencias/pcap.pdf.
[16] http://software.intel.com/en-us/intel-vtune/
[17] http://www.wireshark.org/
[18] http://www.emule-project.net/
[19] https://computing.llnl.gov/tutorials/pthreads/
[20] http://www.doxygen.org/
106
Apéndice
A
Descripción de los métodos utilizados
En esta sección se incluyen la descripción del funcionamiento de los métodos de las
clases detalladas en el Capítulo 4. También se incluye al nal unos detalles generales
acerca del uso de la aplicación.
Métodos de la clase `estado'
Los métodos principales de la clase estado son los siguientes:
estado()
Constructor por defecto de la clase. Inicializa:
0.
Identicador a
Estado inicial a
Estado nal a
Puntero a mensaje a
false.
false.
null.
estado(const estado & orig)
Constructor de copias de la clase. Copia el objeto de la clase
estado
parámetro en el objeto implícito el cual llama al constructor de copias.
eliminar(mensaje * p)
Libera la memoria asociada a una lista enlazada de elementos
virtual ~estado()
Destructor de la clase.
107
mensaje.
pasado por
A. Descripción de los métodos utilizados
void setID(const int & a)
Establece el valor del identicador propio de cada estado al valor entero que se pasa
por parámetro a este procedimiento.
int getID()
Obtiene el valor del identicador del estado implícito que llama a la función, y lo
devuelve.
void setInicial(const bool & a)
Modica la variable booleana de un estado que indica si dicho estado es inicial o no, y
la cambia al valor
a
pasado por parámetro.
bool getInicial()
Obtiene el valor booleano del objeto
estado
implícito que indica si dicho estado es
inicial o no y lo devuelve.
void setFinal(const bool & a)
Modica la variable miembro de un estado que indica si dicho estado es nal o no y la
establece al valor pasado por parámetro.
bool getFinal()
Devuelve el valor de la variable miembro
final que indica si el estado implícito es nal
o no.
void setMensaje(const string & mot, estado * nxt)
Este procedimiento añade un nuevo mensaje a la lista de mensajes del estado. En su
interior, pueden ocurrir dos situaciones:
Que no exista ningún mensaje para ese estado: actualiza el valor del puntero del
estado y añade un mensaje nuevo. Es decir, a modo de ejemplo:
Se parte del estado de la Figura A.1. Si se realiza la llamada a este procedimiento
con el argumento primero con valor `B7' y el segundo es un puntero al estado 0,
entonces resultaría el estado de la Figura A.2.
Que ya existan mensajes: En este caso habría que recorrer la lista de todos los
mensajes existentes y añadir uno nuevo al nal. Es decir, siguiendo con el ejemplo:
Se parte del estado de la Figura A.3. Si ahora se realiza la llamada al procedimiento,
con parámetros `47' y un puntero a un hipotético estado
q2 ,
entonces resultaría lo
mostrado en la Figura A.4.
108
A. Descripción de los métodos utilizados
Figura A.1: Ejemplo de estado.
Figura A.2: Ejemplo de estado tras la llamada a `setMensaje'.
Figura A.3: Ejemplo de estado con un mensaje.
Figura A.4: Ejemplo de estado con un mensaje tras la llamada a `setMensaje'.
109
A. Descripción de los métodos utilizados
mensaje * getMensaje()
Devuelve el valor del puntero al primer mensaje del objeto implícito
estado que realiza
la llamada a esta función.
string getNombre()
Obtiene la descripción (en caso de haber alguna) del objeto implícito que hace la
llamada, y lo devuelve.
void setNombre(const string & nombre)
Establece el valor de la descripción de un objeto de la clase
estado
al valor concreto
que se pasa como parámetro del procedimiento.
void setNull()
Modica, para un objeto
y lo cambia a valor
null.
estado implícito, el valor de su puntero a la lista de mensajes,
int numeroMensajes()
Cuenta el número de mensajes que tiene un objeto
estado
y lo devuelve como pará-
metro. En el ejemplo de la Figura A.4 devolvería 2.
friend ostream & operator(ostream & fo, estado & e)
Sobrecarga del operador `<<' para permitirle mostrar por pantalla todas las variables
miembro de un estado, incluyendo la lista de mensajes que tiene con el detalle de cada
uno de ellos.
estado & operator=(const estado & orig)
Sobrecarga del operador `=' para permitir a un estado poder igualarlo a otro. Tiene
la misma funcionalidad que el constructor de copias de la clase, pero este requiere más
simplicidad a la hora de utilizarlo.
Métodos de la clase `automatas'
Los principales métodos de esta clase se detallan a continuación:
automatas()
Constructor por defecto de la clase. Se inicializan las variables estadísticas a cero.
También se inicializan los mutexes.
110
A. Descripción de los métodos utilizados
automatas(const automatas & orig)
Constructor de copias de la clase. Para copiar un vector a otro, sólo es necesario
utilizar el operador de asignación, ya que se encuentra sobrecargado y se puede utilizar
con sencillez gracias al encapsulado proporcionado por las clases.
virtual ~automatas()
Destructor de la clase. No es necesario liberar memoria, ya que esta función se encuentra
integrada en la clase
vector.
Se destruyen los mutexes.
void setTamanio(const int & n)
Aunque el vector utilizado como variable miembro de la clase es dinámico, sí es necesario inicializar dicho vector a un tamaño inicial. Con este procedimiento se logra ese
objetivo, estableciendo el tamaño del vector al parámetro entero del módulo.
void muestraV()
Procedimiento de ayuda el cual solamente muestra el contenido de cada casilla del
vector del objeto
clase
estado,
automatas.
Gracias a que el operador `<<' está sobrecargado en la
es posible realizar esta operación, ya que en cada casilla del vector se
encuentra un elemento de este tipo.
vector<estado> devuelveV()
Devuelve el vector que forma parte de un objeto de la clase
automatas,
el cual llama
a esta función.
extraeFlujosAntiguos()
Procedimiento de la hebra encargada de la extracción y análisis. Comprueba periódicamente si existen ujos antiguos que extraer del almacén/clasicador. Si el almacén/clasicador tiene un tamaño mayor que un umbral, se crean hebras que ayudan a
liberar carga de la hebra principal.
void leerAutomatas(const char * nombre)
Lee una serie de autómatas contenidos en un chero. La utilidad de este procedimiento
reside en construir el vector de objetos
estado
a partir de información contenida en un
chero de texto. Esta información está relacionada con el funcionamiento del protocolo
que se quiere examinar, en este caso `eDonkey'.
Se establece un tamaño inicial para el vector de objetos
estado.
Cada casilla del
vector se rellena con los datos del chero, estableciendo las variables miembro a un valor
adecuado para su posterior vericación.
111
A. Descripción de los métodos utilizados
int leerTramas(const int & modo, const char * nombre)
Otra de las funciones destacadas la que lee un chero de tramas almacenado en disco
o abre una interfaz de red para un modo de captura en vivo. El formato del chero de
tramas debe ser
pcap,
ya que la biblioteca utilizada trabaja con este tipo de cheros
(véase Sección 2.4.2).
En esta función se observan dos funcionalidades principales:
modo
Si el argumento
es igual a 0: Signica que se ha llamado al programa con la
intención de examinar si un determinado chero de tramas almacenado cumple una
serie de patrones de funcionamiento.
En este modo, el parámetro
nombre
es el nombre del chero
pcap
que contiene las
tramas a examinar.
Si el argumento
modo es igual a 1: En este caso se ha elegido la opción de abrir una
interfaz de red para hacer un análisis en vivo de un determinado protocolo P2P.
En este modo se establece la captura de tráco en modo promiscuo y se indica un
ltro, ya que realiza una captura de tráco más eciente debido a que ahorra coste
computacional. El ltro establecido por defecto es tcp.
En este modo, el parámetro
nombre
es el nombre de la interfaz de red para la
captura en vivo.
La función devuelve un código de error (EXIT_FAILURE) en caso de que se produzca
algún error, o un valor de retorno indicando éxito (EXIT_SUCCESS) en caso de que se
ejecute con normalidad.
muestraEstadisticas()
Muestra las estadísticas correspondientes de los resultados del análisis de los ujos
detectados.
bool comparaAutomata(datosFlujo datos)
Realiza el
parsing
de un autómata. Es decir, en base a todos los autómatas construidos
a partir de un chero dado de autómatas, los cuales proporcionan información acerca de
un determinad protocolo (en este caso, el protocolo `eDonkey'), comprueba si un ujo está
siguiendo el patrón denido en alguno de estos autómatas. Mediante este procedimiento
se llega a la conclusión de si el funcionamiento del protocolo se modela mediante los
autómatas denidos o no.
El parámetro
datos
se corresponde con el ujo de información determinado que se va
a analizar para ver si cumple o no con ciertos patrones de funcionamiento.
La función devuelve
true
en caso de poder modelar el ujo observado mediante un
autómata, o estar este ujo incompleto, y
false
en caso contrario.
void comparaTodo()
112
A. Descripción de los métodos utilizados
Extrae todos los ujos de información existentes en el almacén/clasicador. Se realiza
el
parsing
de cada uno de los ujos extraídos.
operator=(const automatas & orig)
Sobrecarga del operador `=' de la clase.
int getNumeroEstados(vector <estado> V, const int & i)
estado
Devuelve, para un vector de objetos
dado y una posición dentro de ese vector,
el número de posiciones (o estados) que restan hasta encontrar un estado nal.
Funciones auxiliares
Funciones que no forman parte de la clase, pero son necesarias por proporcionar algunas
funcionalidades imprescindibles para manejar un objeto de la clase
automatas.
inline int hex2int(const char * cadena)
Convierte una cadena de caracteres pasada por parámetro que contiene un número en
hexadecimal en el número entero correspondiente.
void parsingAutomata(datosFlujo datos)
Realiza el
parsing
de un autómata. Es decir, en base a todos los autómatas construidos
a partir de un chero dado de autómatas, los cuales proporcionan información acerca de
un determinad protocolo (en este caso, el protocolo `eDonkey'), comprueba si un ujo está
siguiendo el patrón denido en alguno de estos autómatas. Mediante este procedimiento
se llega a la conclusión de si el funcionamiento del protocolo se modela mediante los
autómatas denidos o no.
El parámetro
datos
se corresponde con el ujo de información determinado que se va
a analizar para ver si cumple o no con ciertos patrones de funcionamiento.
La función devuelve
true
en caso de poder modelar el ujo observado mediante un
autómata, o estar este ujo incompleto, y
false
en caso contrario.
Esta función no pertenece a la clase.
liberarCarga(void * arg)
Función de las hebras encargadas de liberar la carga de la hebra principal del módulo
de extracción y análisis. El parámetro
arg
indica la cantidad de trabajo que tendrán las
nuevas hebras creadas.
void evaluaFinFlujo(const string & IPorigen,
const string & IPdestino, const int & puertoOrigen,
const int & puertoDestino, const bool & finTCP)
113
A. Descripción de los métodos utilizados
Uno de los procedimientos principales de la aplicación es aquel que determina cuándo
es el inicio y cuándo el n de un determinado ujo de información. Esta función se llama
para cada trama TCP o UDP que no tenga carga útil.
Dentro de ella, se comprueba que la trama sea TCP y tenga el bit
FIN
activado. En
este caso, signicará que se ha recibido una trama de nalización de una conexión, por lo
que, desde que se inició la transmisión de datos hasta ese punto, se considera un ujo. En
ese caso, se ha de examinar a cuál de todos los ujos existentes corresponde esa trama de
nalización de conexión TCP. Cuando se encuentre una coincidencia, se extraerá dicho
ujo del almacén/clasicador y se analizará para vericar si coincide con alguno de los
autómatas conocidos.
void rellenaClasificadorFlujos(const string & IPorigen,
const string & IPdestino, const int & puertoOrigen,
const int & puertoDestino, const char * payload)
Mediante este procedimiento, correspondiente al módulo de detección de ujos detallado en el Apartado 4.1.2, se clasican las tramas leídas en ujos de información. Dicho
procedimiento puede ser modicado para la compatibilidad con otros protocolos ya que
es en él donde se realizan las funciones intrínsecas al protocolo `eDonkey'. Para ello, se
lee la carga útil de la trama antes de operar con ella, ya que los datos de la cabecera
se incluyen en los parámetros de este procedimiento. Los pasos que se siguen son los
siguientes:
Se comprueba que la trama tenga una carga útil lo sucientemente grande como para ser examinada. Si los datos de la trama tienen un tamaño inferior a 11 caracteres,
no se considerará.
Se comprueba que la trama pertenezca al protocolo `eDonkey' o a la extensión del
protocolo proporcionada por `eMule'. Esto se conoce gracias a un parámetro
tipo
el cual es `E3' en el caso de que la trama pertenezca a `eDonkey' o `C5' si pertenece
a `eMule'.
Se examina el tamaño de la carga útil mediante un parámetro existente a tal efecto.
Si el tamaño es superior a 100000 bytes, se considera que la información es errónea
y se descarta la trama, ya que no existen tramas tan grandes.
Dependiendo del tamaño del almacén/clasicador de ujos:
ˆ
ˆ
Si el almacén/clasicador no contiene ningún ujo de información, se creará uno nuevo y se introducirán los datos referentes a la trama que se está
examinando en él.
Si el almacén/clasicador ya tiene otros ujos anteriores, se comprobará cada
uno de ellos para vericar si la trama que se está examinando pertenece a un
ujo de información ya existente. En el caso de no haber ninguna coincidencia,
se creará uno nuevo.
114
A. Descripción de los métodos utilizados
El proceso se repite tantas veces como existan datos referentes al protocolo `eDonkey'. Esto sucede ya que, en una misma trama, pueden aparecer de manera encadenada, varias subtramas pertenecientes al protocolo `eDonkey'.
void my_callback(u_char * args, const struct pcap_pkthdr * header,
const u_char * packet)
Este procedimiento corresponde con el módulo de preprocesamiento explicado en el
pcap, llamada pcap_loop.
pcap_loop, por lo que dentro
Apartado 4.1.1, y está ligado a la función de la biblioteca
Dicho procedimiento se ejecuta para cada trama leída con
se puede escribir el código que se desee.
Una de las funciones básicas que se ha implementado dentro de este procedimiento,
es el ltrado de tramas que no se necesitan evaluar. Conforme se van leyendo estas
tramas, se accede a los distintos niveles de información de la cabecera. De esta manera,
se pueden desechar las tramas que no pertenezcan ni al protocolo TCP ni al UDP, puesto
que son únicamente las que proporcionan información relevante para la evaluación con
los autómatas.
La segunda y última de las funciones destacadas dentro de este módulo es el tratamiento de la carga útil de la trama leída. Dado que no todos los caracteres leídos tienen
por qué ser ASCII, entonces no todos pueden ser representados por algún carácter que
pueda ser leído e interpretado por un lector cualquiera. Para un mejor tratamiento de la
información contenida en las cargas útiles, la opción tomada es realizar una conversión
de todos los caracteres a base hexadecimal. Con esta transformación es posible identicar los protocolos a los que pertenece cada trama, así como otro tipo de información
relevante para la construcción de las diferentes estructuras que conforman la aplicación.
Una vez realizada la conversión mencionada, la trama se envía para incluirla dentro
del almacén/clasicador de ujos, en caso de que tenga carga útil, o bien es examinada
para comprobar si proporciona algún tipo de información referente al nal de un ujo de
información, en caso de no tener carga útil.
Métodos de la clase `datosFlujo'
Esta clase tiene los siguientes métodos:
datosFlujo()
Constructor por defecto de la clase. No es necesario inicializar ninguna variable miembro del objeto, pues ni las cadenas, ni los números enteros, ni los vectores necesitan
inicializarse.
datosFlujo(const datosFlujo & orig)
Constructor de copias de la clase. Realiza una copia simple de todos los elementos del
objeto
orig
pasado por parámetro al objeto implícito.
115
A. Descripción de los métodos utilizados
virtual ~datosFlujo()
Destructor de la clase. No realiza liberación de memoria de ningún tipo puesto que
no es necesario reservar memoria para crear un objeto de la clase. Todas las variables
miembro son objetos ya encapsulados que incorporan sus propios destructores.
string getIPorigen()
Devuelve el valor de la variable miembro que almacena la IP origen para el objeto que
llama a esta función.
void setIPorigen(const string & IP)
Establece el valor de la variable que almacena la IP origen del objeto que llama a la
función al valor pasado por parámetro,
IP.
string getIPdestino()
Obtiene el valor de la variable miembro que almacena la IP destino del objeto implícito
y la devuelve.
void setIPdestino(const string & IP)
Establece el valor de la variable IP destino del objeto implícito al valor que se le pasa
por parámetro a la función.
int getPuertoOrigen()
Esta función toma el valor del puerto origen del objeto implícito que la llama, y lo
devuelve.
void setPuertoOrigen(const int & puerto)
Establece el valor de la variable miembro que almacena el puerto origen al valor indicado en el parámetro de la función.
int getPuertoDestino()
Devuelve el valor de la variable miembro que almacena el puerto destino para el objeto
implícito que llama a la función.
void setPuertoDestino(const int & puerto)
Establece el valor del puerto destino del objeto que realiza la llamada al valor del
parámetro de la función.
int getTimestamp()
116
A. Descripción de los métodos utilizados
Obtiene el valor de la variable miembro que almacena la marca de tiempo (timestamp )
y la devuelve.
void setTimestamp(const int & timestamp)
Establece el valor del timestamp de un objeto de la clase
datosFlujo
al valor que se
le pasa por parámetro al procedimiento.
vector<string> getTypes()
Devuelve, para el objeto implícito que realiza la llamada a la función, un vector de
cadenas que contiene la información propia del protocolo transmitida entre dos
peers.
void setTypes(const string & type)
Mediante este procedimiento se añade al nal del vector de cadenas que forma parte
de las variables miembro, la información contenida en el parámetro de la función.
friend ostream & operator(ostream & fo, datosFlujo & d)
Sobrecarga del operador `<<' para un objeto de la clase
datosFlujo.
Mediante este
operador se puede mostrar por pantalla toda la información de las variables miembro del
objeto implícito.
Métodos de la clase `clasicadorFlujos'
Las funciones y procedimientos de esta clase son los siguientes:
clasificadorFlujos()
Constructor de la clase. Dado que la única variable miembro de un objeto de esta clase
es un vector de la STL, se inicializa dicho vector un una función diseñada a tal efecto.
clasificadorFlujos(const clasificadorFlujos & orig)
Constructor de copias de la clase. Ya que sólo está compuesta por un vector, sólo es
necesario copiar el contenido de este.
virtual ~clasificadorFlujos()
Destructor de la clase. Ya que está formada por un objeto de la STL, no es necesario
implementar un destructor, puesto que la STL ya implementa funciones a tal efecto.
int tamClasificador()
Para un objeto de la clase
clasificadorFlujos
determinado, devuelve el tamaño del
vector de ese objeto.
117
A. Descripción de los métodos utilizados
datosFlujo getPosicion(const int & i)
Para un objeto implícito que llama a esta función, devuelve el contenido (es decir, un
objeto
datosFlujo)
que se encuentra en la posición que indica el parámetro
i.
void setPosicion(const datosFlujo & nueva)
Añade un nuevo ujo de datos, es decir, un nuevo objeto de la clase
datosFlujo,
al
clasicador de ujos.
string getIPorigen(const int & i)
Devuelve el valor de la IP origen del objeto
i
datosFlujo que se encuentra en la posición
del objeto que llama a la función.
void setIPorigen(const int & i, const string & str)
Establece el valor de la IP origen de un objeto de la clase
posición
i
al valor
str
datosFlujo
situado en la
pasado por parámetro.
string getIPdestino(const int & i)
Devuelve el valor de la IP destino del objeto
i
datosFlujo que se encuentra en la posición
del objeto que llama a la función.
void setIPdestino(const int & i, const string & str)
Establece el valor de la IP destino de un objeto de la clase
posición
i
al valor
str
datosFlujo
situado en la
pasado por parámetro.
int getPuertoOrigen(const int & i)
Devuelve el valor del puerto origen del objeto
posición
i
datosFlujo
que se encuentra en la
del objeto que llama a la función.
void setPuertoOrigen(const int & i, const int & puerto)
Establece el valor del puerto origen de un objeto de la clase
posición
i
al valor
puerto
datosFlujo
situado en la
pasado por parámetro.
int getPuertoDestino(const int & i)
Devuelve el valor del puerto destino del objeto
posición
i
datosFlujo
que se encuentra en la
del objeto que llama a la función.
void setPuertoDestino(const int & i, const int & puerto)
118
A. Descripción de los métodos utilizados
Establece el valor del puerto destino de un objeto de la clase
la posición
i
al valor
puerto
datosFlujo
situado en
pasado por parámetro.
double getTimestamp(const int & i)
Devuelve el valor de la marca de tiempo del objeto
la posición
i
datosFlujo
que se encuentra en
del objeto que llama a la función.
void setTimestamp(const int & i, const double & _timestamp)
Establece el valor de la marca de tiempo de un objeto de la clase
en la posición
i
al valor
_timestamp
datosFlujo
situado
pasado por parámetro.
vector<string> getTypes(const int & i)
Devuelve el vector de cadenas situado en la posición
almacena la información del protocolo para dos
peers
i
del almacén/clasicador, que
determinados.
void setTypes(const int & i, const string & str)
Añade en el vector de cadenas situado en la posición
i
del almacén/clasicador, con
información del protocolo y las tramas intercambiadas entre dos
parámetro
str.
peers
la información del
datosFlujo BorrarElemento(const int & i)
Para un objeto de la clase
clasificadorFlujos determinado, borra el objeto datosFlujo
(es decir, borra toda la información referente a un ujo de datos) situado en la posición
i
del almacén/clasicador. Finalmente, devuelve este elemento.
Detalles generales del uso de la aplicación
A modo de ayuda, se muestran una serie de pautas en la utilización de la aplicación:
La aplicación ya está compilada. En caso de que se desee compilar de nuevo, tan
sólo es necesario ejecutar la orden
make.
No requiere ningún tipo de instalación.
./bin/.
El ejecutable del programa se encuentra en el directorio
El chero de autómatas se encuentra en
Todo el código está documentado con la herramienta Doxygen (véase Sección
./dat/automatas.dat.
2.4.5). Se puede acceder a esta documentación mediante el HTML
Los archivos de cabeceras se encuentran en
./doc/index.html.
./include/.
Existe un manual de referencia con la documentación del código, en formato
Dicho manual se encuentra en
./latex/refman.pdf.
pdf.
119
A. Descripción de los métodos utilizados
Se ha creado una biblioteca con la estructura de la aplicación, con el n de facilitar
su uso en el futuro. Dicha biblioteca se encuentra en
Los cheros objeto producto de la compilación de la aplicación se encuentran en
./obj/.
./lib/libpfc.a.
Para borrarlos, es necesario ejecutar la orden
En el directorio
./pcap/
./make clean.
se incluyen algunos cheros de ejemplo con trazas de
tráco. Los resultados de la ejecución de estos cheros se muestran, a modo de
ejemplo, en el directorio
./resultados/.
./src/.
Los cheros con el código fuente se encuentran en
A continuación se muestra un ejemplo de uso de la aplicación. Si se deseara ejecutar
dicha aplicación para dos cheros del directorio
denominada
eth0,
./pcap/ y para una interfaz de red
la llamada sería la siguiente (es necesario otorgar permisos de
superusuario si se desea analizar una interfaz de red):
./bin/p2pdetector -f ./pcap/1-establecimiento_conexion.pcap
-f ./pcap/2-buscar.pcap -i eth0
120

Documentos relacionados