Las herramientas de red como wireshark, tcpdump, etc., son bastante populares para la detección de paquetes. Este artículo proporciona una descripción general básica de la biblioteca libpcap, que forma la base del rastreo de paquetes para muchas herramientas de monitoreo de red, incluidas wireshark, tcpdump, snort, etc.
¿Qué es la detección de paquetes y cómo funciona?
La detección de paquetes es una técnica a través de la cual los datos de la red hacia y desde su computadora pueden monitorearse fácilmente. Los datos viajan en la red en forma de paquetes y una herramienta de rastreo de paquetes puede capturar fácilmente estos paquetes. La mayoría de los rastreadores de paquetes son utilizados por administradores de red y desarrolladores que trabajan en herramientas de red. Sin embargo, los rastreadores de paquetes en general son útiles para depurar problemas relacionados con la red y pueden ser utilizados por cualquier persona que tenga los privilegios necesarios.
Los rastreadores de paquetes funcionan rastreando un dispositivo de interfaz como eth0, etc. Se puede obtener una lista de interfaces con el comando ifconfig. Una vez que se selecciona la interfaz, puede haber algunas opciones a través de las cuales se pueden filtrar los paquetes según el protocolo, el puerto de origen, el puerto de destino, etc. No es necesario elegir una opción de filtro. Acto seguido se inicia la captura de paquetes.
Para comprender la captura de paquetes y los filtros de visualización, consulte nuestro tutorial sobre wireshark. Para obtener información sobre la herramienta de línea de comandos, consulte tcpdump, que también detecta paquetes pero genera resultados en la línea de comandos.
La biblioteca libpcap
Libpcap es la biblioteca subyacente utilizada para la detección de paquetes por muchas de las herramientas populares de monitoreo de red. Para comprender el uso de esta biblioteca, se requiere una comprensión básica del lenguaje de programación C.
Así es como funciona libpcap:
- Elija el dispositivo de interfaz de red en el que se realizará el rastreo de paquetes. Por ejemplo, 'eth0', 'wlan0', etc. en Linux.
- Una vez elegido el dispositivo, inicialice la biblioteca pcap con este dispositivo.
- A continuación, podemos aplicar opciones de filtro para casos como si queremos rastrear solo paquetes TCP/IP o si queremos especificar que rastrear paquetes solo desde un puerto de origen o destino en particular, etc. Este filtro se compila y luego se aplica usando un conjunto de funciones de biblioteca libpcap.
- Luego, la biblioteca pcap entra en su ciclo de captura de paquetes donde captura la cantidad de paquetes establecida por el programa.
- Una vez que se captura un paquete, se llama a una función de devolución de llamada en la que todo el paquete está disponible para imprimir sus detalles o usarlo de otra manera
Los cuatro pasos mencionados anteriormente son los pasos básicos para iniciar una captura de paquetes a través de libpcap.
Un ejemplo
El siguiente código hace uso de las funciones libpcap para lograr una captura de paquetes básica. Después de capturar los paquetes, dentro de la función de devolución de llamada, la longitud de cada paquete se imprime en la salida estándar.
#include <pcap.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/if_ether.h> #include <netinet/tcp.h> #include <netinet/ip.h> #include <string.h> void callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char* packet) { static int count = 1; printf("\nPacket number [%d], length of this packet is: %d\n", count++, pkthdr->len); } int main(int argc,char **argv) { char *dev; char errbuf[PCAP_ERRBUF_SIZE]; pcap_t* descr; struct bpf_program fp; /* to hold compiled program */ bpf_u_int32 pMask; /* subnet mask */ bpf_u_int32 pNet; /* ip address*/ pcap_if_t *alldevs, *d; char dev_buff[64] = {0}; int i =0; // Check if sufficient arguments were supplied if(argc != 3) { printf("\nUsage: %s [protocol][number-of-packets]\n",argv[0]); return 0; } // Prepare a list of all the devices if (pcap_findalldevs(&alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } // Print the list to user // so that a choice can be // made printf("\nHere is a list of available devices on your system:\n\n"); for(d=alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (Sorry, No description available for this device)\n"); } // Ask user to provide the interface name printf("\nEnter the interface name on which you want to run the packet sniffer : "); fgets(dev_buff, sizeof(dev_buff)-1, stdin); // Clear off the trailing newline that // fgets sets dev_buff[strlen(dev_buff)-1] = ''; // Check if something was provided // by user if(strlen(dev_buff)) { dev = dev_buff; printf("\n ---You opted for device [%s] to capture [%d] packets---\n\n Starting capture...",dev, (atoi)(argv[2])); } // If something was not provided // return error. if(dev == NULL) { printf("\n[%s]\n", errbuf); return -1; } // fetch the network address and network mask pcap_lookupnet(dev, &pNet, &pMask, errbuf); // Now, open device for sniffing descr = pcap_open_live(dev, BUFSIZ, 0,-1, errbuf); if(descr == NULL) { printf("pcap_open_live() failed due to [%s]\n", errbuf); return -1; } // Compile the filter expression if(pcap_compile(descr, &fp, argv[1], 0, pNet) == -1) { printf("\npcap_compile() failed\n"); return -1; } // Set the filter compiled above if(pcap_setfilter(descr, &fp) == -1) { printf("\npcap_setfilter() failed\n"); exit(1); } // For every packet received, call the callback function // For now, maximum limit on number of packets is specified // by user. pcap_loop(descr,atoi(argv[2]), callback, NULL); printf("\nDone with packet sniffing!\n"); return 0; }
En el código de arriba:
- La función pcap_findalldevs() se utiliza para obtener una lista de todos los dispositivos de interfaz disponibles. Esta lista se puede mostrar al usuario para que se pueda seleccionar la interfaz deseada para rastrear paquetes. Tenga en cuenta que existe una función pcap_lookupdev() que también devuelve un dispositivo de interfaz, pero el problema con esta función es que devuelve el primer dispositivo sin bucle invertido disponible. Entonces, en caso de que esté usando una conexión de red inalámbrica y el dispositivo de interfaz para mi conexión sea 'wlan0', pero la función pcap_lookupdev() todavía devolvería 'eth0' ya que encuentra esta interfaz primero. Por lo tanto, usar pcap_findalldevs() es una mejor opción, ya que produce una lista de dispositivos de interfaz para elegir.
- La lista devuelta por la función pcap_findalldevs() se entrega al usuario y la entrada del usuario se toma de stdin.
- Luego, se utiliza la función pcap_lookupnet() para obtener la dirección IP y la máscara de red.
- A través de la función pcap_open_live(), la biblioteca pcap se inicializa con el dispositivo de interfaz seleccionado.
- A través de la función pcap_compile(), podemos compilar cualquier filtro en el protocolo, etc. establecido por el usuario.
- A través de pcap_setfilter(), se aplica este filtro.
- Finalmente, a través de la función pcap_loop(), la biblioteca inicia la captura de paquetes en el dispositivo seleccionado con el filtro aplicado y con cada paquete relevante capturado, se llama a la función de devolución de llamada.
Aquí está el resultado del programa anterior:
$ sudo ./pcap tcp 10 [sudo] password for himanshu: Here is a list of available devices on your system: 1. eth0 (Sorry, No description available for this device) 2. wlan0 (Sorry, No description available for this device) 3. usbmon1 (USB bus number 1) 4. usbmon2 (USB bus number 2) 5. usbmon3 (USB bus number 3) 6. usbmon4 (USB bus number 4) 7. usbmon5 (USB bus number 5) 8. usbmon6 (USB bus number 6) 9. usbmon7 (USB bus number 7) 10. any (Pseudo-device that captures on all interfaces) 11. lo (Sorry, No description available for this device) Enter the interface name on which you want to run the packet sniffer : wlan0 ---You opted for device [wlan0] to capture [10] packets--- Starting capture... Packet number [1], length of this packet is: 496 Packet number [2], length of this packet is: 66 Packet number [3], length of this packet is: 357 Packet number [4], length of this packet is: 66 Packet number [5], length of this packet is: 238 Packet number [6], length of this packet is: 66 Packet number [7], length of this packet is: 403 Packet number [8], length of this packet is: 66 Packet number [9], length of this packet is: 121 Packet number [10], length of this packet is: 66 Done with packet sniffing!
Si no está ejecutando el programa anterior como root, debe usar sudo para ejecutar el programa, ya que las acciones realizadas por la biblioteca libpcap requieren privilegios de superusuario.