|
| 1 | +Title: Monitorando Ips Duplicados na Rede |
| 2 | +Slug: monitorando-ips-duplicados-na-rede |
| 3 | +Date: 2018-05-15 10:24:00 |
| 4 | +Category: Network |
| 5 | +Tags: python,tutorial,network,scapy,defaultdict |
| 6 | +Author: Silvio Ap Silva |
| 7 | + |
| 8 | +Github: kanazux |
| 9 | +Linkedin: SilvioApSilva |
| 10 | +Twitter: @kanazux |
| 11 | +Site: http://kanazuchi.com |
| 12 | + |
| 13 | +Muitos administradores de redes e sysadmins encontram problemas de conectividade nos ambientes que administram e por muitas vezes o problema é um simples IP duplicado causando todo mal estar. Agora veremos como usar o scapy e defaultdict da lib collections para monitorar esses IPs. |
| 14 | + |
| 15 | +### Scapy |
| 16 | + |
| 17 | +O Scapy é uma poderosa biblioteca de manipulação de pacotes interativa, com abrangencia a uma enorme quantidade de protocolos provenientes da suite TCP/IP. |
| 18 | +Mais informações sobre o scpay pode ser encontrada na [**documentação oficial**](http://scapy.readthedocs.io/en/latest/index.html). |
| 19 | +Nesse caso em especifico iremos utilizar do scapy a metaclasse *ARP* e a função *sniff*. |
| 20 | + |
| 21 | +```python |
| 22 | +from scapy.all import ARP, sniff |
| 23 | +``` |
| 24 | + |
| 25 | +#### sniff |
| 26 | + |
| 27 | +Vamos usar a função sniff para monitorar os pacotes que trafegam na rede usando o protocolo ARP. |
| 28 | +Pra isso vamos utilizar dela quatro parametros basicos: |
| 29 | + |
| 30 | +```python |
| 31 | +sniff(prn=pacotes, filter="arp", iface=interface, timeout=10) |
| 32 | +``` |
| 33 | + |
| 34 | +* prn, chama uma função para ser aplicada a cada pacote capturado pelo sniff. |
| 35 | + |
| 36 | +* filter, irá filtrar todos os pacotes que contiverem o protocolo ARP. |
| 37 | + |
| 38 | +* iface, determina a interface de rede que será monitorada. |
| 39 | + |
| 40 | +* timeout, irá determinar que nosso monitoramento da rede se dara por 60 segundos. |
| 41 | + |
| 42 | +#### ARP |
| 43 | + |
| 44 | +ARP é uma metaclasse de pacotes com dados sobre o protocolo arp pertencente a camada de enlace de dados. |
| 45 | +Iremos utilizar essa metaclasse para filtrar os pacotes com informações de pacotes com respostas a requisições arp. (opcode == 2 [is at]) |
| 46 | +As informações sobre o protocolo ARP podem serm encontradas na [rfc826](https://tools.ietf.org/html/rfc826) no site do IETF. |
| 47 | + |
| 48 | +### collections.defaultdict |
| 49 | + |
| 50 | +defaultdict é uma subclasse de dict que prove uma instancia de variavel para a chamada de uma chave inexistente. |
| 51 | + |
| 52 | +```python |
| 53 | +from collections import defaultdict |
| 54 | +list_ips = defaultdict(set) |
| 55 | +``` |
| 56 | + |
| 57 | +Basicamente nossa função irá monitorar por um certo tempo o trafego de pacotes pela rede adicionar a nossa variavel *list_ips* o endereço ou endereços MAC encontrados. |
| 58 | + |
| 59 | +### Definindo a função que será passada como parametro para o sniff. |
| 60 | + |
| 61 | +Para cada pacote capturado pela função sniff, será checado se o opcode corresponde a um response do protocolo arp. |
| 62 | +Caso seja, sera adicionado a nossa defaultdict. |
| 63 | + |
| 64 | +```python |
| 65 | +def pacotes(pacote): |
| 66 | + """Checa se o valor do opcode dentro do protocolo arp é igual a 2.""" |
| 67 | + if pacote[ARP].op == 2: |
| 68 | + # Se for adiciona o ip de origem e seu mac à dict list_ips |
| 69 | + list_ips[pacote[ARP].psrc].add(pacote[ARP].hwsrc) |
| 70 | +``` |
| 71 | + |
| 72 | +### Limpando a tabela arp |
| 73 | + |
| 74 | +Para que seja feita novas requisições arp, iremos limpar nossa tabela arp e iniciar o monitoramento da rede. |
| 75 | +Pra isso iremos usar o comando arp, dentro do shell do sistema. *(Como uso [FreeBSD](https://www.freebsd.org) vou definir uma função chamando um comando pelo csh)* |
| 76 | + |
| 77 | +```python |
| 78 | +import os |
| 79 | +os.system('which arp') |
| 80 | +/usr/sbin/arp |
| 81 | +``` |
| 82 | + |
| 83 | +Com posse do caminho do comando arp, irei definir uma função que limpe a tabela e inicie o monitore a rede por 60 segundos. |
| 84 | + |
| 85 | +```python |
| 86 | +def monitorar(interface): |
| 87 | + """ |
| 88 | + O comando arp no FreeBSD usa os parametros: |
| 89 | +
|
| 90 | + -d para deletar as entradas |
| 91 | + -i para declarar a interface |
| 92 | + -a para representar todas entradas a serem deletas. |
| 93 | + """ |
| 94 | + cmd = "/usr/sbin/arp -d -i {} -a".format(interface) |
| 95 | + os.system(cmd) |
| 96 | + sniff(prn=pacotes, filter="arp", iface=interface, timeout=10) |
| 97 | +``` |
| 98 | + |
| 99 | +E por ultimo chamar a função de monitoramento. |
| 100 | +No meu caso eu vou monitorar a interface **em0**. |
| 101 | + |
| 102 | +```python |
| 103 | +monitorar("em0") |
| 104 | +``` |
| 105 | + |
| 106 | +Agora só conferir as entradas em nossa dict. |
| 107 | + |
| 108 | +```python |
| 109 | +for ip in list_ips: |
| 110 | + print "IP: {} -> MACs: {}".format(ip, ", ".join(list(list_ips[ip]))) |
| 111 | + |
| 112 | +IP: 192.168.213.1 -> MACs: 00:90:0b:49:3d:0a |
| 113 | +IP: 192.168.213.10 -> MACs: 08:00:27:bf:52:6d, a0:f3:c1:03:74:6a |
| 114 | +``` |
| 115 | + |
| 116 | +Eu uso um script rodando nos switchs e gateway da rede que me enviam mensagens assim que ips duplicados são encontrados na rede. |
| 117 | +Também da pra usar o **arping** do scpay para fazer as requisições arp e coletar os responses. |
| 118 | + |
| 119 | +Abraços. |
0 commit comments