2008-09-22 11 views
9

Quiero escribir una herramienta de análisis en tiempo real para el tráfico inalámbrico.Lectura desde un dispositivo de red promiscuo

¿Alguien sabe leer desde un dispositivo promiscuo (o sniffing) en C?

Sé que debe tener acceso de root para hacerlo. Me preguntaba si alguien sabe qué funciones son necesarias para hacer esto. Los enchufes normales no parecen tener sentido aquí.

+0

En Linux? Su publicación no indica el sistema operativo, pero ¿deberíamos suponer que con el uso de "raíz" quiere decir linux? – GEOCHET

+1

sí, también lo hace la etiqueta supongo – jbleners

Respuesta

16

En Linux utiliza un receptáculo de PF_PACKET para leer datos de un dispositivo en bruto, tales como una interfaz de Ethernet se ejecuta en modo promiscuo:

s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) 

Esto enviará copias de cada paquete recibido hasta el zócalo. Sin embargo, es bastante probable que en realidad no desee todos los paquetes. El kernel puede realizar un primer nivel de filtrado utilizando BPF, Berkeley Packet Filter. BPF es esencialmente una máquina virtual basado en la pila: se ocupa de un pequeño conjunto de instrucciones tales como:

ldh = load halfword (from packet) 
jeq = jump if equal 
ret = return with exit code 

código de salida de BPF le dice al núcleo si se debe copiar el paquete a la toma o no. Es posible escribir programas BPF relativamente pequeños directamente, usando setsockopt (s, SOL_SOCKET, SO_ATTACH_FILTER,). (ADVERTENCIA: El núcleo toma una estructura sock_fprog, no una struct bpf_program, no las mezcle o su programa no funcionará en algunas plataformas).

Para cualquier cosa razonablemente compleja, realmente desea usar libpcap. BPF está limitado en lo que puede hacer, en particular en la cantidad de instrucciones que puede ejecutar por paquete. libpcap se encargará de dividir un filtro complejo en dos partes, con el kernel realizando un primer nivel de filtrado y el código de espacio de usuario más capaz que arroja los paquetes que en realidad no quería ver.

libpcap también abstrae la interfaz del kernel de su código de aplicación. Linux y BSD usan API similares, pero Solaris requiere DLPI y Windows usa algo más.

+0

¡Gracias por la respuesta! – jbleners

+0

En realidad, no, libpcap no dividirá el filtro en dos partes. Pero, sí, libpcap es lo que quieres usar: sabe cómo poner una interfaz en modo promiscuo en diferentes plataformas (simplemente usar 'ETH_P_ALL' no es suficiente en Linux, por ejemplo, eso es" SAP promiscuo ", en el sentido de que obtener todos los paquetes independientemente del tipo de protocolo, pero no es "físicamente promiscuo", ya que el adaptador no entregará los paquetes de difusión única del host que no se envían al host). –

0

¿Por qué no usarías algo como WireShark?

Es de código abierto, por lo que al menos podrías aprender algunas cosas si no quieres usarlo.

+0

No estoy seguro si WireShark puede capturar el paquete inalámbrico completo. Creo que está configurado para MAC normal, no inalámbrico MAC. Necesito poder ver el tráfico de múltiples essids. – jbleners

+0

Una vez más, comenzaría mirando el código fuente de wireshark. – GEOCHET

+1

WireShark no funciona con tarjetas inalámbricas en Windows (punto). – leppie

7

Una vez tuve que escuchar en marcos de Ethernet sin procesar y terminé creando un contenedor para esto. Al llamar a la función con el nombre del dispositivo, ex eth0, obtuve un socket a cambio que estaba en modo promiscuo. Lo que necesita hacer es crear un socket sin formato y luego ponerlo en modo promiscuo. Así es como lo hice.

int raw_init (const char *device) 
{ 
    struct ifreq ifr; 
    int raw_socket; 

    memset (&ifr, 0, sizeof (struct ifreq)); 

    /* Open A Raw Socket */ 
    if ((raw_socket = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 1) 
    { 
     printf ("ERROR: Could not open socket, Got #?\n"); 
     exit (1); 
    } 

    /* Set the device to use */ 
    strcpy (ifr.ifr_name, device); 

    /* Get the current flags that the device might have */ 
    if (ioctl (raw_socket, SIOCGIFFLAGS, &ifr) == -1) 
    { 
     perror ("Error: Could not retrive the flags from the device.\n"); 
     exit (1); 
    } 

    /* Set the old flags plus the IFF_PROMISC flag */ 
    ifr.ifr_flags |= IFF_PROMISC; 
    if (ioctl (raw_socket, SIOCSIFFLAGS, &ifr) == -1) 
    { 
     perror ("Error: Could not set flag IFF_PROMISC"); 
     exit (1); 
    } 
    printf ("Entering promiscuous mode\n"); 

    /* Configure the device */ 

    if (ioctl (raw_socket, SIOCGIFINDEX, &ifr) < 0) 
    { 
     perror ("Error: Error getting the device index.\n"); 
     exit (1); 
    } 

    return raw_socket; 
} 

Luego, cuando tenga su zócalo, puede usar seleccionar para manejar los paquetes a medida que llegan.

0

WireShark en Linux tiene la capacidad de capturar la información del encabezado PLCP (protocolo de convergencia de capa física).

Cuestiones relacionadas