GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo realizar un rastreo de paquetes usando Libpcap con código de ejemplo C

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.


Linux
  1. Uso de Ansible para interactuar con puntos finales web

  2. CentOS / RHEL:Cómo montar sistemas de archivos usando UUID

  3. Cómo usar la memoria compartida con Linux en C

  4. ¿Cómo rellenar un archivo con FF usando dd?

  5. Cómo montar una partición con espacios en la ruta

Cómo realizar implementaciones Canary con Istio

Cómo realizar una búsqueda de patrones en archivos usando Grep

Cómo realizar una copia de seguridad remota de Linux mediante SSH

Cómo buscar LDAP usando ldapsearch (con ejemplos)

Cron Vs Anacron:Cómo configurar Anacron en Linux (con un ejemplo)

3 métodos para conectarse a MySQL desde PHP usando un código de ejemplo