Rafael Arce Nazario 069bba67b0 initial | 9 years ago | |
---|---|---|
doc | 9 years ago | |
images | 9 years ago | |
README.md | 9 years ago | |
SimpleSniffer.pro | 9 years ago | |
ethernet_hdr.h | 9 years ago | |
ethernet_packet.cpp | 9 years ago | |
ethernet_packet.h | 9 years ago | |
imagepacket.cpp | 9 years ago | |
imagepacket.h | 9 years ago | |
images.qrc | 9 years ago | |
ip_hdr.h | 9 years ago | |
ip_packet.cpp | 9 years ago | |
ip_packet.h | 9 years ago | |
main.cpp | 9 years ago | |
mainwindow.cpp | 9 years ago | |
mainwindow.h | 9 years ago | |
mainwindow.ui | 9 years ago | |
sniffer.cpp | 9 years ago | |
sniffer.h | 9 years ago | |
tcp_hdr.h | 9 years ago | |
udp_hdr.h | 9 years ago |
La programación orientada a objetos (object oriented programming, OOP) es un paradigma de programación que promueve el diseño de programas en el que distintos objetos interactúan entre sí para resolver un problema. C++ es uno de los lenguajes de programación que promueve la programación orientada a objetos, permitiendo que los programadores creen sus propias clases desde cero o derivadas de otras clases existentes. Algunos otros lenguajes que promueven OOP son Java, Python, javascript y PHP.
En OOP, cada objeto encapsula dentro de él ciertas propiedades sobre el ente que está modelando (por ejemplo, un objeto que modela un punto encapsula dentro de sí las coordenadas x y y del punto que representa). Además, cada objeto permite realizar ciertas acciones sobre sí, i.e. contiene sus métodos. Por ejemplo, un objeto de clase punto puede realizar la acción de cambiar el valor de su coordenada x.
Cuando la clase de objetos que necesitamos utilizar en nuestro programa no ha sido predefinida en el alguna librería, necesitamos declarar e implementar nuestra propia clase. Para esto definimos clases que contengan datos con ciertas propiedades o atributos y acciones que queremos hacer con esos datos por medio de métodos o funciones miembro. De esta manera, podremos organizar la información y procesos en objetos que tienen las propiedades y métodos de una clase. En la experiencia de laboratorio de hoy practicarás el definir una clase e implementar algunos de sus métodos completando analizador de redes (sniffer) simple. El sniffer captura todos los paquetes de protocolo de internet (IP) que fluyen a través de tu computadora en el laboratorio, y alguna información adicional de los paquetes.
Practicar la declaración e implementación de clases en C++.
Implementar métodos de una clase.
Antes de llegar al laboratorio debes haber:
Repasado la declaración e implementación de clases en C++.
Estudiado los conceptos e instrucciones para la sesión de laboratorio.
Tomado el quiz Pre-Lab que se encuentra en Moodle.
Las computadoras se comunican por medio del Internet utilizando el Protocolo de Internet (IP, por sus siglas en inglés). Cuando una computadora envía información (o mensaje) a otra computadora, la información se envía por Paquetes de Internet que contienen la dirección fuente (“source address”), que es la dirección de Internet de la computadora que está enviando la información, y la dirección del destino (“destination address”), que es dirección de Internet de la computadora que debe recibir el mensaje. Las direcciones de Internet se usan para guiar la información de una computadora a otra, pero, una vez el paquete llega a su destino, ?quién se supone que reciba la información? ?Cuál aplicación debe recibir la información?
Los paquetes de internet también deben especificar la aplicación que envía la información y la aplicación que debe recibirla. Podemos pensar que las direcciones de Internet son las direcciones de correo de una casa, y que las aplicaciones que envían y reciben la información son las personas que envían y reciben la correspondencia. Para enviar una carta por correo, hay que especificar a qué persona se le está enviando la carta. Esto corresponde a especificar la aplicación que recibe la información. Para identificar la aplicación fuente y la aplicación del destino, el protocolo de Internet usa lo que se conoce como números de puerto. De este modo, mirando la información del paquete, se puede identificar las direcciones y puertos de la fuente y del destino.
Por ejemplo, cuando la computadora que usas en un laboratorio se comunica con el servidor donde se encuentra el programa Moodle, los paquetes que llevan la información de tu computadora al servidor contienen la dirección de la fuente, que es la computadora del laboratorio, y la dirección del destinatario, que es el servidor de Moodle. El puerto fuente es el de tu buscador web y el puerto destinatario es el del servidor de Moodle.
Las direcciones de internet ocupan 4 bytes (32 bits) y usualmente se presentan al usuario como cadenas de 4 valores decimales. Cada valor decimal entre 0 y 255 es la representación decimal de uno de los 4 bytes:
“(0-255).(0-255).(0-255).(0-255)”. Algunos ejemplos de direcciones de IP son:
10.0.1.10
, 192.168.10.11
, 136.145.54.10
.
Para complicar las cosas un poco, cada tarjeta de red de computadoras tiene un identificador único que es usado para la comunicación entre tu computadora y el dispositivo de la red que enruta el tráfico de red de Internet y la red local a tu computadora y vice-versa (protocolo Ethernet). Este identificador único es conocido como la dirección de Hardware (también conocido como dirección MAC), es representado usando 6 bytes (48 bits), y es presentado a los usuarios como una cadena de caracteres de 6 pares de dígitos hexadecimales (cada par de dígitos hexadecimal corresponde a 1 byte). Por ejemplo, las siguientes son direcciones MAC: e0:f8:47:01:e9:90
y 70:ad:60:ff:fe:dd
.
Un sniffer de paquetes (también conocido como analizador de paquetes, analizador de protocolos, o analizador de redes) es un programa de computadora que puede interceptar y registrar el tráfico que pasa a través de una red digital, o dispositivo de red. Mientras los datos fluyen a través de la red, el sniffer captura cada paquete, y si es necesario lo descifra para obtener los datos crudos del paquete [1].
Cada paquete capturado por un sniffer tiene una estructura como la que ilustra la Figura 1.
Figura 1. Estructura de cada paquete de Ethernet capturado por un sniffer.
Dentro de la estructura estructura mostrada en la Figura 1 se encuentra:
Dentro del payload, el paquete de IP contiene varios campos, entre ellos:
En esta experiencia de laboratorio completarás un sniffer de paquetes sencillo que captura todos los paquetes de IP que fluyen a través de tu computadora de laboratorio, y alguna información adicional de los paquetes. Adicionalmente detecta las solicitudes no encriptadas de imágenes en la web, y despliega las imágenes en el GUI.
La aplicación que completarás hoy permite a los usuarios analizar el tráfico de red y monitorear las imágenes que están siendo transferidas a través de tu red.
Figura 2. Interface de la aplicación Simple Packet Sniffer.
La Figura 2 muestra una foto de la interfaz de la aplicación. Cada fila en la tabla es la información de un paquete capturado. La caja de texto bajo la tabla presenta un resumen del paquete seleccionado en la tabla. La lista en el lado derecho presenta las imágenes que han sido capturadas por el sniffer.
Para crear un sniffer de paquetes puedes usar la librería de pcap que provee una interfaz para accesar la data que está pasando a través de la tarjeta de red de tu computadora. Esta librería contiene una función que devuelve un torrente crudo de los bytes de cada paquete capturado.
La tarea del programador del sniffer es decodificar el torrente en crudo a información legible por humanos. Afortunadamente esta no va a ser tu tarea, pero tu puedes aprender a hacerlo, si quieres, leyendo el código fuente de este laboratorio. Tu tarea es seguir los ejercicios de abajo para que puedas proveerle al sniffer los objetos necesarios (Clases) para procesar los paquetes.
Descarga la carpeta Classes-SimpleSniffer
a tu computadora escribiendo git clone http://bitbucket.org/eip-uprrp/classes-SimpleSniffer
en el terminal.
Para cargar este proyecto necesitas correr Qt Creator
con privilegios de administrador (root). Para lograr esto, escribe lo siguiente en el terminal:
sudo qtcreator Documents/eip/Classes-SimpleSniffer/Classes-SimpleSniffer.pro
.
Configura el proyecto. El proyecto consiste de varios archivos. En esta experiencia de laboratorio trabajarás con los archivos ethernet_hdr.h
, ethernet_packet.h
, ethernet_packet.cpp
, ip_packet.h
y ip_packet.cpp
.
ethernet_packet
Estudia el archivo ethernet_hdr.h
. Este archivo contiene la siguiente definición de la estructura de datos que representa un encabezado de Ethernet:
#define ETHER_ADDR_LEN 6
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* direccion destino */
u_char ether_shost[ETHER_ADDR_LEN]; /* direccion fuente */
u_short ether_type; /* IP? ARP? RARP? etc */
};
El encabezado de Ethernet de arriba es usado para decodificar la parte Ethernet de los datos crudos en cada paquete. Este se compone de la dirección MAC fuente (ether_shost
, 6 bytes), la dirección MAC destino (ether_dhost
, 6 bytes), y el tipo de paquete de Ethernet (ether_type
, 2 bytes) que es usado para determinar si el paquete es un paquete de IP.
Como sabes, no es una buena idea enseñar este formato de información a un usuario regular. Tu primer tarea es definir los métodos de la clase de C++ que traducen la información de las direcciones MAC a cadenas de caracteres legibles por humanos.
El siguiente código es la definición de la clase ethernet_packet
, que se encuentra en el archivo ethernet_packet.h
:
class ethernet_packet
{
sniff_ethernet ethernet ;
// Devuelve una direccion de 6 bytes MAC en una cadena de caracteres.
string mac2string(u_char []) ;
public:
ethernet_packet(); // Constructor por defecto
// Ajusta la variable miembro ether_host a los valores
// recibidos en el arreglo
void setEtherDHost(u_char []) ;
// Ajusta la variable miembro ether_shost a los valores
// recibidos en el arreglo
void setEtherSHost(u_char []) ;
// Ajusta el ethernet type al valor recibido.
void setEtherType(u_short) ;
// Devuelve la representación en cadenas de caracteres de las direcciones
// Ethernet
string getEtherDHost() ;
string getEtherSHost() ;
// Devuelve el tipo de ethernet.
u_short getEtherType() ;
};
Nota que cada objeto de clase ethernet_packet
solo tiene el siguiente atributo:
sniff_ethernet
llamada ethernet
El resto son métodos que actúan como interfaz al atributo:
void setEtherDHost(u_char [])
: es un setter para el campo ether_dhost
del atributo ethernet
void setEtherSHost(u_char [])
: es un setter para el campo ether_shost
del atributo ethernet
void setEtherType(u_short)
: es un setter para el campo ether_type
del atributo ethernet
getEtherDHost()
y getEtherSHost()
son getters que devuelven los valores de ether_dhost
y ether_shost
en formato legible por humanos, i.e. 6 pares de dígitos hexadecimales (por ejemplo, e0:f8:47:01:e9:90
).
getEtherType()
es un getter que devuelve el valor de ether_type
como unsigned char.
el método privado string mac2string(u_char [])
recibe un unsigned character y devuelve el string correspondiente a su representación hexadecimal. Por ejemplo, si recibe 0x8A
debe devolver el string "8A"
.
Tu tarea en este ejercicio es implementar las siete funciones listadas arriba en el archivo ethetnet_packet.cpp
. Los encabezados de algunas de la funciones están provistos en el archivo.
ip_packet
Estudia las definiciones de las funciones de la clase ip_packet
que se encuentra en el archivo ip_packet.cpp
Tu tarea es crear la declaración de la clase ip_packet
en el archivo ip_packet.h
tomando como base los métodos que aparecen en el archivo ip_packet.cpp
. Los atributos de la clase ip_packet
deben ser:
string
para almacenar las direcciones de IP fuente y destinochar
) para almacenar el tipo de protocolo IPunsigned short
para almacenar el puerto fuente y destinostring
para almacenar la carga (payload) del paquete.En la declaración de la clase ip_packet
debes especificar que es una clase derivada de la clase ethernet_packet
.
ethernet_packet.cpp
y ip_packet.h
que completaste. Recuerda utilizar buenas prácticas de programación, incluir el nombre de los programadores y documentar tu programa.[1]http://en.wikipedia.org/wiki/Packet_analyzer
Before you get to the laboratory you should have:
1. Reviewed C++ classes and structures
2. Studied the concepts and instructions for this laboratory session.
3. Taken the Pre-Lab quiz in Moodle
Computers communicate with each other through the Internet Protocol (IP). When a computer sends information to another computer it is sent via Internet packets that contain the Internet address of the sender computer (source address), the source port of the application that is sending the message, the Internet address of the receiving computer(destination address), and the port of the application that will receive the message.
We can compare the Internet address to the address of a house, and the applications to the members of the house. When sending a letter from one house to another, the address on the letter identifies the destination house, and the name on the letter identifies the house member to who it is sent.
For instance when your lab computer is contacting the department’s web server, the packets that carry the information from your computer to the web server contains the source address of the lab computer and the destination address of the web server; and the source port of your web browser and the destination port of the web server.
Internet addresses are represented on 4 bytes (32 bits) normally presented to users as strings of 4 decimal values. Each decimal value is the decimal representation of one of the 4 bytes: “(0-255).(0-255).(0-255).(0-255)”. Examples of IP addresses are: 10.0.1.10, 192.168.10.11, 136.145.54.10, and so on.
Port numbers are composed of 2 bytes or 16 bits. Therefore port numbers range from 0-65535. There are ports numbers assigned to known application services such as number 22 for ssh, 23 for telnet, 25 smtp, 80 for http, and so on.
To complicate things a little bit, each computer network card has an unique identifier that is used for the communication between you computer and the network device that routes the network traffic from the Internet and local network to your computer and vice-versa (Ethernet protocol). This unique identifier is known as the Hardware address (a.k.a Multiple Access Controll (MAC) addres), is represented on 6 bytes (48 bits), and is presented to users as strings of 6 hexadecimal values. Each hex value is the hex representation of the 6 bytes: “(00-ff):(00-ff):(00-ff):(00-ff):(00-ff):(00-ff)”. Examples of MAC addresses are: e0:f8:47:01:e9:90, 70:ad:60:ff:fe:dd:79:d8 , and so on.
A packet sniffer (a.k.a packet analyzer, protocol analyzer, or network analyzer) is a computer program that can intercept and log traffic passing over a digital network, or network device. As data flow across the network, the sniffer captures each packet and, if needed decodes the packet’s raw data[1].
The packets captured by this program follow the following packet structure:
* first an Ethernet header which contains the source and destination MAC addresses
* second a IP header that contains the source and destination IP addresses
* third a header that contains the source and destination port numbers.
In this application we create a simple packet sniffer that captures all the IP packets that flow across your lab computer, and for each packet, decodes the IP addresses, the port numbers, and some additional information of the packets. Additionaly it detects the unencrypted request of images in the web, and displays the images in the GUI.
See the following snapshot of the application:
Each row in the table is the information of each captured packet, the text box under the table presents a ASCII summary of a selected packet from the table, and the list in the right presents the images that have been requested and are seen in you network card.
The application that you are about to complete gives the user the ability to analyze the network traffic and monitor the images that are being watched in your network.
To create a packet sniffer you can use the pcap library that provides an interface to access the data passing across your network card. This library contains a function that returns a raw stream of bytes of each packet captured. It is the task of the sniffer programmer to decode the raw stream into human readable information. Fortunately this is not your task, but you can learn how to do it, if you want, by reading the source code of this laboratory. Your task is to follow the exercises below so you provide the packet sniffer with the needed objects (Classes) to process the packets.
Instructions
1. To load this project you need to run qt creator with root privileges.
```sudo qtcreator Documents/eip/simplesniffer/SimpleSniffer.pro```
2.The project `SimpleSniffer` is in the directory `Documents/eip/simplesniffer` of your computer. You can also go to `http://bitbucket.org/eip-uprrp/classes-simplesniffer` to download the folder `classes-simplesniffer` to your computer.
2. Configure the project. The project consists of several files. In this laboratory you will be working with the files `ethernet_hdr.h`, `ethernet_packet.h`, `ethernet_packet.cpp`, `ip_packet.h` and `ip_packet.cpp`
Read the file ethernet_hdr.h
, it contains the definition of the data structure that represents an Ethernet header. It is also shown below:
#define ETHER_ADDR_LEN 6
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
The Ethernet header above is used to decode the ethernet part of the raw data in each packet. It is composed of the source MAC address (ether_shost, 6 bytes), the destiantion MAC address (ether_dhost, 6 bytes), and the type of Ethernet packet (ether_type, 2 bytes) which is used to determine if the packet is an IP packet.
As you can see, it is not a good idea to show this information format to a regular user. Your first task is to define the functions of the C++ class that defines the functions to translate the MAC address information into human readable strings.
The class header is in file ethernet_packet.h
and is also shown below:
class ethernet_packet
{
sniff_ethernet ethernet ;
// Returns a 6 bytes MAC address in string representation.
string mac2string(u_char []) ;
public:
ethernet_packet(); // Default constructor
// Set the ethernet variable member ether_dhost to the values
// received in the array
void setEtherDHost(u_char []) ;
// Same as above but to the ether_shost
void setEtherSHost(u_char []) ;
// Set the ethernet type to the value received.
void setEtherType(u_short) ;
// returns the string representation of the ethernet addresses
string getEtherDHost() ;
string getEtherSHost() ;
// Return the ethernet type
u_short getEtherType() ;
};
Define the functions in file ethetnet_packet.cpp
For Exercise 3 see the definitions of the functions of the class ip_packet found in file ip_packet.cpp
Your task is to define the class header following the functions inside the file. The member variables are:
string
s to store the source and destination IP addresseschar
) variable to store the IP protocolunsigned short
variables to store the source and destination portstring
to store the packet payload.This class header that you are defining inherits from the class that you defined in Exercise 2.
Use “Deliverables” in Moodle to upload the files ethernet_packet.cpp
y ip_packet.h
that you defined.