Leitura de um dispositivo de rede promíscua
-
02-07-2019 - |
Pergunta
Eu quero escrever uma ferramenta de análise em tempo real para o tráfego sem fio.
Alguém sabe como ler a partir de um dispositivo promíscuo (ou sniffing) em C?
Eu sei que você precisa ter acesso root para fazê-lo. Eu queria saber se alguém sabe o que é necessário fazer isto funções. soquetes normais não parece fazer sentido aqui.
Solução
No Linux você usa um soquete PF_PACKET para ler dados de um dispositivo bruto, como uma interface ethernet em execução no modo promíscuo:
s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
Isto irá enviar cópias de cada pacote recebido até ao seu soquete. É bastante provável que você realmente não quer cada pacote, no entanto. O kernel pode realizar um primeiro nível de filtragem usando BPF, o Berkeley Packet Filter . BPF é essencialmente uma máquina virtual baseada em pilha: ele lida com um pequeno conjunto de instruções, tais como:
ldh = load halfword (from packet)
jeq = jump if equal
ret = return with exit code
código de saída de BPF diz ao kernel se para copiar o pacote para a tomada ou não. É possível escrever programas relativamente pequenos BPF diretamente, usando setsockopt (s, SOL_SOCKET, SO_ATTACH_FILTER,). (ATENÇÃO: O kernel toma um sock_fprog struct, não um bpf_program struct, não misture os para cima ou para seu programa não irá funcionar em algumas plataformas)
.Para qualquer coisa razoavelmente complexo, você realmente quer usar libpcap. BPF é limitado no que ele pode fazer, em particular no número de instruções que podem ser executadas por pacote. libcap vai cuidar de divisão de um filtro complexo-se em duas partes, com o kernel realizando um primeiro nível de filtragem e o código de espaço do usuário mais-capable soltando os pacotes que realmente não querem ver.
libpcap também abstrai a interface do kernel fora de seu código do aplicativo. Linux e BSD usar APIs semelhantes, mas Solaris requer DLPI e Windows usa outra coisa.
Outras dicas
Uma vez eu tive que escutar em quadros Ethernet crus e acabou criando um invólucro para isso. Ao chamar a função com o nome do dispositivo, ex eth0
eu tenho uma tomada em troca que estava em modo promíscuo.
O que você precisa fazer é criar um socket raw e, em seguida, colocá-lo em modo promíscuo. Aqui está como eu fiz isso.
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;
}
Então, quando você tem seu soquete você pode apenas usar seleccionar a pacotes punho que eles chegam.
Você pode usar a biblioteca pcap (ver http://www.tcpdump.org/pcap.htm ), que também é usado pelo tcpdump e Wireshark.
Por que você não usaria algo como WireShark ?
É open source, assim pelo menos você poderia aprender algumas coisas com ele se você não quer apenas usá-lo.
WireShark no linux tem a capacidade de capturar o PLCP (camada física protocolo de convergência) informações de cabeçalho.