2012-01-04 3 views
16

Я пытаюсь отправить ранее записанный трафик (записанный в формате pcap) с помощью scapy. В настоящее время я застрял в чередующемся исходном слое эфира. Трафик был захвачен на другом хосте, и мне в основном нужно изменить как IP, так и Ether-уровень src и dst. Мне удалось заменить уровень IP и пересчитать контрольные суммы, но уровень Ether дает мне проблемы.Отправка пакетов из pcap с измененным src/dst в scapy

У кого-нибудь есть опыт повторного отправки пакетов из файла захвата с внесенными изменениями на IP и Ether-уровень (src и dst)? Кроме того, захват - это довольно большая пара Gb, как насчет скошенной производительности с таким количеством трафика?

+1

'scapy' это хороший инструмент, но вы должны сделать это с' scapy'? Существуют и другие решения, которые могут быть оптимизированы для этого ... –

+1

Майк, какие «другие инструменты» вы могли бы порекомендовать? Мне показалось, что Scapy был естественным выбором для этой задачи. –

+0

смотрите на [tcpreplay] (http://tcpreplay.synfin.net/) –

ответ

5

Ну, с scapy я придумал следующее (извините за мой Python). Надеюсь, это поможет кому-то. Был более простой сценарий, когда все пакеты из файла pcap считываются в память, но это может привести к проблемам с большими файлами захвата.

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

проверки этот пример

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 

комментарии:

  • использование rdpcap, wrpcap методы scapy для чтения и записи из PCAP отформатированный файл
  • вы можете использовать sniff(offline="filename") для чтения пакетов и вы можете использовать параметр prn, подобный этому sniff(offline="filename",prn=My_Function), в этом случае My_Functions будут применены к каждому pkt sniffed
  • правильный способ написать свой новый ip или mac - это рассмотреть его как строку ex: ip="1.1.1.1" и так далее, как показано выше.
  • в примере: sendp метод включен в цикл, который медленнее, чем делают другой цикл для отправки пакетов
  • Кончик
  • производительности: в питоне, используя для петель слишком медленно использовать map вместо этого, если вы хотите, скорость, как для цикла в C, Ref
  • rdpcap, как указано выше, считывает файл сразу, если доступная память при чтении говорит о 1,5 Гб, и вы читаете файл 2,3, .. Gb, он не сработает.
  • если проблема производительности имеет решающее значение для вас может использовать winpcap, но вы должны написать более сложный код в C, делая ту же задачу с помощью питона/scapy довольно легко простой, но не быстрее, чем с
  • это зависит какой из них нужно использовать на уровне производительности, необходимо
  • Если я правильно понял, вы отправляете пакеты видеопотоков, в этом случае я бы использовал winpcap, если я отправляю 1 мегапиксельное видео или scapy в других случаях (более низкий размер за кадр)
  • В случае использования C/winpcap вы получите отличную производительность при чтении pcaps и изменении данных и повторной отправке, но вы должны знать об одной и той же проблеме (большие файлы), вам нужно создать буфер с пр размер оператора, чтобы использовать его для чтения, отправляя пакеты в довольно высокой производительности
  • , если размер пакета постоянный (что редко бывает в большинстве случаев, я думаю), у вас может быть преимущество получить большую часть доступной памяти
  • if вы хотите использовать python/scapy для всего «проекта/программы», вы можете создавать высокопроизводительные функции в C/Wincap и компилировать как dll, тогда вы можете импортировать эту DLL в свою программу python, и вы можете использовать ее внутри программы python.Таким образом, вы получаете преимущества замечательного простого python/Scapy, и вы записываете только определенные функции в c, чтобы вы могли быстрее выполнять свою работу, а ваш код был сфокусированным и поддерживаемым.
+1

Спасибо за советы, Абдурахман, особенно те, которые касаются проблем с производительностью! Scapy - отличный инструмент, но он не подходит для сильного моделирования трафика (по крайней мере, «из коробки»). –

+0

О ваших предложениях по использованию встроенной «карты» я бы не был уверен, что это улучшит производительность, учитывая, что методы scapy send/sendp получают список пакетов в качестве параметра и внутри самих функций они имеют ' for' loop ('__gen_send'). Таким образом, возможно, что вы получаете, вызывая «map» по-пакету вместо передачи списка пакетов напрямую для send/sendp, теряется с внутренними циклами 'for'. – newlog

5

Если бы я был вами, я бы позволил Скопируйте сделку с слоем Ether и используйте функцию send(). Например:

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

Работал для меня, единственная проблема, с которой я столкнулся, была неправильная контрольная сумма IP, которую легко было установить, добавив del p.chksum перед отправкой (p) – AliA

+0

Вы правы, я забыл это! Благодаря! – Pierre

0

Для правильной контрольной суммы, я также необходимо добавить del p[UDP].chksum

Смежные вопросы