2012-01-04 10 views
16

Sto tentando di inviare un traffico precedentemente registrato (acquisito in formato pcap) con scapy. Attualmente sono bloccato nello striping Ether layer originale. Il traffico è stato catturato su un altro host e fondamentalmente ho bisogno di cambiare sia il livello IP che Ether src e dst. Sono riuscito a sostituire il livello IP e ricalcolare il checksum, ma il livello Ether mi dà problemi.Invio di pacchetti da pcap con modificato src/dst in scapy

Chiunque ha esperienza nel reinvio dei pacchetti dal file di acquisizione con le modifiche applicate al livello IP e Ether (src e dst)? Inoltre, l'acquisizione è una coppia piuttosto grande di Gb, che ne dici delle prestazioni di scapy con tali quantità di traffico?

+1

'scapy' è un buon strumento, ma avete a che fare questo con' scapy'? Ci sono altre soluzioni che possono essere ottimizzate per questo ... –

+1

Mike, quali "altri strumenti" potresti raccomandare? Mi sembrava che Scapy fosse una scelta naturale per questo compito. –

+0

guarda [tcpreplay] (http://tcpreplay.synfin.net/) –

risposta

5

Bene, con lo scapy ho trovato il seguente (mi dispiace per il mio Python). Spero che possa aiutare qualcuno. C'è stato uno scenario più semplice in cui tutti i pacchetti del file pcap vengono letti in memoria, ma ciò potrebbe causare problemi con i file di acquisizione di grandi dimensioni.

from scapy.all import * 
global src_ip, dst_ip 
src_ip = 1.1.1.1 
dst_ip = 2.2.2.2 
infile = "dump.pcap" 

try: 
    my_reader = PcapReader(infile) 
    my_send(my_reader) 
except IOError: 
    print "Failed reading file %s contents" % infile 
    sys.exit(1) 

def my_send(rd, count=100): 
    pkt_cnt = 0 
    p_out = [] 

    for p in rd: 
     pkt_cnt += 1 
     np = p.payload 
     np[IP].dst = dst_ip 
     np[IP].src = src_ip 
     del np[IP].chksum 
     p_out.append(np) 
     if pkt_cnt % count == 0: 
      send(PacketList(p_out)) 
      p_out = [] 

    # Send remaining in final batch 
    send(PacketList(p_out)) 
    print "Total packets sent %d" % pkt_cn 
22

controllo questo esempio

from scapy.all import * 
from scapy.utils import rdpcap 

pkts=rdpcap("FileName.pcap") # could be used like this rdpcap("filename",500) fetches first 500 pkts 
for pkt in pkts: 
    pkt[Ether].src= new_src_mac # i.e new_src_mac="00:11:22:33:44:55" 
    pkt[Ether].dst= new_dst_mac 
    pkt[IP].src= new_src_ip # i.e new_src_ip="255.255.255.255" 
    pkt[IP].dst= new_dst_ip 
    sendp(pkt) #sending packet at layer 2 

commenti:

  • uso rdpcap, metodi Scapy wrpcap a leggere e scrivere da pcap file formattato
  • è possibile utilizzare sniff(offline="filename") per leggere i pacchetti e si può usare il parametro prn come questo sniff(offline="filename",prn=My_Function) in questo caso, My_Functions verrà applicato a ogni pkt sniffato
  • il modo corretto di scrivere il tuo nuovo IP o Mac è considerarlo come una stringa ex: ip="1.1.1.1" e così via come illustrato sopra.
  • nell'esempio: Metodo sendp incluso nel ciclo for, che è più lento di fare altro ciclo per inviare pacchetti
  • punta
  • prestazioni: in Python utilizzando cicli for è l'uso troppo lento map invece se si desidera una velocità come un ciclo for in C, Ref
  • il rdpcap come usato in precedenza legge il file in una volta, se la memoria disponibile durante la lettura dice 1.5 Gb e stai leggendo un file 2,3, .. Gb, fallirà.
  • se il problema di prestazioni è fondamentale per voi può utilizzare winpcap ma è necessario scrivere codice più complesso in C, facendo la stessa operazione utilizzando python/Scapy è abbastanza facile una semplice, ma non è più veloce di c
  • Dipende quale utilizzare per il livello di prestazioni necessario
  • se la mia ipotesi è corretta, si stanno inviando pacchetti di flusso video in questo caso io userei un WinPcap se invio un video da 1 mega pixel o scapy in altri casi (dimensione inferiore per frame)
  • in caso di utilizzo di C/winpcap otterrete grandi prestazioni nella lettura di pcaps e cambiare i dati e inviare nuovamente ma dovete essere consapevoli dello stesso problema (file di grandi dimensioni) è necessario creare un buffer con un pr oper size per usarlo per leggere l'invio dei pacchetti in una discreta performance
  • se la dimensione del pacchetto è costante (il che è raro nella maggior parte dei casi, immagino) si può avere un vantaggio ottenere il massimo dalla memoria disponibile
  • se vuoi usare python/scapy per l'intero "progetto/programma" puoi creare le funzioni ad alte prestazioni in C/Wincap e compilare come dll, quindi puoi importare questa dll nel tuo programma python e puoi usarla all'interno di un programma python.In questo modo si ottiene benefici della meravigliosa facile python/Scapy e si scrive solo funzioni specifiche in c in modo da poter ottenere il vostro lavoro più velocemente e il codice da mettere a fuoco e mantenibile
+1

Grazie per i suggerimenti, Abdurahman, specialmente quelli riguardanti i problemi di prestazioni! Scapy è uno strumento piacevole, ma potrebbe non essere adatto alla simulazione del traffico pesante (almeno "out of the box"). –

+0

Per quanto riguarda i suggerimenti per l'uso di 'map', non sarei sicuro se ciò migliorerebbe le prestazioni, dato che i metodi send/sendp di scapy ricevono un elenco di pacchetti come parametro e all'interno delle funzioni stesse hanno un' for' loop (funzione '__gen_send'). Quindi forse ciò che si guadagna chiamando 'map' pacchetto-per-pacchetto invece di passare l'elenco dei pacchetti direttamente a send/sendp va perso con i cicli interni' for'. – newlog

5

Se fossi in te, vorrei lasciare Scapy si occupa del livello Ether e usa la funzione send(). Per esempio:

ip_map = {"1.2.3.4": "10.0.0.1", "1.2.3.5": "10.0.0.2"} 
for p in PcapReader("filename.cap"): 
    if IP not in p: 
     continue 
    p = p[IP] 
    # if you want to use a constant map, only let the following line 
    p.src = "10.0.0.1" 
    p.dst = "10.0.0.2" 
    # if you want to use the original src/dst if you don't find it in ip_map 
    p.src = ip_map.get(p.src, p.src) 
    p.dst = ip_map.get(p.dst, p.dst) 
    # if you want to drop the packet if you don't find both src and dst in ip_map 
    if p.src not in ip_map or p.dst not in ip_map: 
     continue 
    p.src = ip_map[p.src] 
    p.dst = ip_map[p.dst] 
    # as suggested by @AliA, we need to let Scapy compute the correct checksum 
    del(p.chksum) 
    # then send the packet 
    send(p) 
+2

Ha funzionato per me, l'unico problema che ho avuto è stato il checksum IP errato che è stato facilmente risolto aggiungendo del p.chksum prima di inviare (p) – AliA

+0

Hai ragione, l'avevo dimenticato! Grazie! – Pierre

0

Per un corretto checksum, ho anche bisogno di aggiungere del p[UDP].chksum