Pergunta

Estou procurando uma maneira (com python) para obter o layer II endereço de um dispositivo na minha rede local. Layer III Os endereços são conhecidos.

O objetivo é criar um script que pesquisará um banco de dados de endereços IP em intervalos regulares, garantindo que os endereços MAC não tenham mudado e, se houver, alertas por e -mail para mim.

Foi útil?

Solução

Responder à pergunta com Python depende da sua plataforma. Não tenho o Windows Handy, então a solução a seguir funciona na caixa Linux em que escrevi. Uma pequena mudança na expressão regular fará com que funcione no OS X.

Primeiro, você deve ping no alvo. Isso colocará o alvo - desde que esteja dentro da sua máscara de rede, que parece nessa situação que será - no cache ARP do seu sistema. Observar:

13:40 jsmith@undertow% ping 97.107.138.15
PING 97.107.138.15 (97.107.138.15) 56(84) bytes of data.
64 bytes from 97.107.138.15: icmp_seq=1 ttl=64 time=1.25 ms
^C

13:40 jsmith@undertow% arp -n 97.107.138.15
Address                  HWtype  HWaddress           Flags Mask            Iface
97.107.138.15            ether   fe:fd:61:6b:8a:0f   C                     eth0

Sabendo disso, você faz um pouco de magia do subprocesso - caso contrário, está escrevendo o cache do Cache ARP, e não quer fazer isso:

>>> from subprocess import Popen, PIPE
>>> import re
>>> IP = "1.2.3.4"

>>> # do_ping(IP)
>>> # The time between ping and arp check must be small, as ARP may not cache long

>>> pid = Popen(["arp", "-n", IP], stdout=PIPE)
>>> s = pid.communicate()[0]
>>> mac = re.search(r"(([a-f\d]{1,2}\:){5}[a-f\d]{1,2})", s).groups()[0]
>>> mac
"fe:fd:61:6b:8a:0f"

Outras dicas

Havia um pergunta semelhante respondeu há pouco tempo neste site. Conforme mencionado na resposta escolhida pelo pergunta dessa pergunta, o Python não tem uma maneira integrada de fazê-lo. Você deve chamar um comando do sistema como arp Para obter informações de ARP ou gerar seus próprios pacotes usando Scapy.

Editar: Um exemplo usando SCapy do site deles:

Aqui está outra ferramenta que monitorará constantemente todas as interfaces em uma máquina e imprimirá toda a solicitação ARP que vê, mesmo em quadros 802.11 de uma placa Wi-Fi no modo de monitor. Observe o parâmetro store = 0 para sniff () para evitar armazenar todos os pacotes na memória por nada.

#! /usr/bin/env python
from scapy import *

def arp_monitor_callback(pkt):
    if ARP in pkt and pkt[ARP].op in (1,2): #who-has or is-at
        return pkt.sprintf("%ARP.hwsrc% %ARP.psrc%")

sniff(prn=arp_monitor_callback, filter="arp", store=0)

Não é exatamente o que você está procurando, mas definitivamente no caminho certo. Apreciar!

Parece que você deseja monitorar os spoofers ARP? Nesse caso, tudo que você precisa é ARPWATCH, disponível em todas as distribuições Linux bem fornecidas perto de você. Baixar fontes aqui: http://ee.lbl.gov/

Para sistemas baseados no UNIX:

#!/usr/bin/env python2.7

import re
import subprocess
arp_out =subprocess.check_output(['arp','-lan'])

re.findall(r"((\w{2,2}\:{0,1}){6})",arp_out)

retornará a lista de tuplas com Macs. O SCAPY é uma ferramenta incrível, mas parece ser um exagero para este caso

Em algumas vezes, você sente falta da linha de comando Util "ARP". Uma imagem de ambiente incorporada do Yocto Linux, por exemplo.

Uma maneira alternativa sem a ferramenta "ARP" seria ler e analisar o arquivo/proc/net/arp:

root@raspberrypi:~# cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
192.168.1.1      0x1         0x2         xx:xx:xx:xx:xx:xx     *        wlan0
192.168.1.33     0x1         0x2         yy:yy:yy:yy:yy:yy     *        wlan0

Uma maneira mais fácil, se no Linux:

print os.system('arp -n ' + str(remoteIP))

você vai ter:

    Address        HWtype  HWaddress           Flags Mask            Iface
    192.168.....   ether   9B:39:15:f2:45:51   C                     wlan0

Uma solução simples usando SCAPY, para digitalizar a sub -rede 192.168.0.0/24 é a seguinte:

from scapy.all import *

ans,unans = arping("192.168.0.0/24", verbose=0)
for s,r in ans:
    print("{} {}".format(r[Ether].src,s[ARP].pdst))

Tente usar os Netifaces encontrados aqui. netifaces

Atualização geral para Python 3.7. Observação: a opção -n por arp Não fornece a lista ARP nos sistemas Windows, conforme fornecido com certas respostas para sistemas baseados em Linux. Use a opção -a Conforme declarado na resposta aqui.

from subprocess import Popen, PIPE

pid = Popen(['arp', '-a', ip], stdout=PIPE, stderr=PIPE)

IP, MAC, var = ((pid.communicate()[0].decode('utf-8').split('Type\r\n'))[1]).split('     ')
IP  =  IP.strip(' ')
MAC =  MAC.strip(' ')

if ip == IP:
    print ('Remote Host : %s\n        MAC : %s' % (IP, MAC))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top