Как замариновать скапи пакет?

Мне нужно замариновать scapy пакет. В большинстве случаев это работает, но иногда сборщик жалуется на объект функции. Эмпирическое правило: пакеты ARP хорошо травятся. Некоторые пакеты UDP вызывают проблемы.


person Helmut Grohne    schedule 11.11.2010    source источник
comment
Фон используется вместе с модулем multiprocessing. Он требует, чтобы объекты были доступны для обработки, если вы хотите передать их через Queue.   -  person Helmut Grohne    schedule 16.11.2010
comment
Может ли кто-нибудь ответить на этот вопрос, чтобы я мог присудить награду?   -  person Helmut Grohne    schedule 23.11.2010


Ответы (6)


Мое решение (вдохновленное списком рассылки scapy) выглядит следующим образом:

class PicklablePacket:
    """A container for scapy packets that can be pickled (in contrast
    to scapy packets themselves)."""
    def __init__(self, pkt):
        self.contents = bytes(pkt)
        self.time = pkt.time

    def __call__(self):
        """Get the original scapy packet."""
        pkt = scapy.Ether(self.contents)
        pkt.time = self.time
        return pkt

Везде, где я хочу передать scapy Packet через Queue, я просто оборачиваю его в PicklablePacket, а затем __call__. Я не знаю данных, которые не сохраняются таким образом. Однако этот подход работает только с пакетами Ethernet. (Все пакеты, перехваченные на обычном сетевом адаптере (не WLAN), являются Ethernet.) Вероятно, его можно было бы расширить для работы и с другими типами.

person Helmut Grohne    schedule 30.11.2010
comment
Спасибо за обратную связь. Хотя мне не нужно было ваше точное решение, оно помогло мне найти свое собственное. - person Mr. Shickadance; 24.03.2011

Если под pickle вы подразумеваете общую сериализацию, вы всегда можете использовать методы импорта/экспорта pcap: rdpcap и вркап.

wrpcap("pkt.pcap",pkt)
pkt = rdpcap("pkt.pcap")

Или вы можете запустить свой процесс и получить пакеты в другом процессе. Если есть какой-то шаблон, который вы можете сопоставить, скажем, известный порт или исходный IP-адрес, tcpdump будет работать:

tcpdump -i eth0 -w FOO.pcap host 172.20.33.12 and \(udp or arp\)

Затем вы можете прочитать сгенерированный pcap, как указано выше:

pkts = rdpcap('FOO.pcap')
person Paul Rubel    schedule 11.11.2010
comment
1) Я говорю о 500 пакетах в секунду. - person Helmut Grohne; 16.11.2010
comment
2) Этот метод фактически теряет данные. Например, метка времени округлена. Это не обязательно проблема, но это необходимо учитывать. - person Helmut Grohne; 16.11.2010
comment
Может ли scapy выдавать даже 500 пакетов в секунду? Я обнаружил, что при отправке пакетов это намного меньше. Вы всегда можете запустить tcpdump в другом терминале. - person Paul Rubel; 18.11.2010
comment
Скай может. См. комментарий к другому ответу. - person Helmut Grohne; 23.11.2010
comment
Вы можете передать ссылку на файл в очереди. струны травленые. - person Paul Rubel; 24.11.2010
comment
Извините, создание файла для каждого пакета — плохая шутка с точки зрения производительности. Если бы меня не заботила производительность, я мог бы использовать threading вместо multiprocessing и вообще не пришлось бы травить. - person Helmut Grohne; 07.12.2010

(Это больше для справки, поэтому голосов не ожидается)

Список Scapy [email protected] хорошо контролируется и, как правило, очень отзывчив. Если вы не получили ответы здесь, попробуйте и там.

person Gregg Lind    schedule 11.11.2010
comment
О, вот где общение продолжается? Трекер проблем кажется довольно неактивным. По крайней мере один из моих багов пролежал там полгода без ответа. - person Helmut Grohne; 16.11.2010
comment
в качестве примечания, 500 пакетов в секунду также могут быть больше, чем обрабатывает Scapy. Он разработан для гибкости, а не для скорости :) Спросите в списке. Я не очень им пользуюсь, так что я не эксперт. - person Gregg Lind; 17.11.2010
comment
На самом деле я могу подтвердить, что scapy очень хорошо обрабатывает 500 пакетов в секунду. Конечно, я использую более одного потока и (после этого вопроса) более одного процесса. - person Helmut Grohne; 23.11.2010

Вдохновленный этим вопросом, можно использовать dill (или другие, такие как sPickle и т. д. — см. pypi search pickle), чтобы сохранить scapy-пакеты. Например. Установите укроп с помощью sudo easy_install dill или sudo pip install dill. Вот базовый сценарий использования:

import dill as pickle
# E.g. Dump an array of packets stored in variable mypackets to a file
pickle.dump(mypackets, open('mypackets.dill-pickle', 'w'))
# Restore them from the file
mypackets = pickle.load(open('mypackets.dill-pickle', 'rb'))

Также можно, конечно, просто использовать собственные функции scapy для сброса пакетов в файл pcap (доступный для чтения tcpdump/wireshark и т. д.) - если у вас просто есть массив пакетов:

wrpcap("packets_array.pcap",packets_array)
person Pierz    schedule 16.06.2014

Вы можете изменить класс Packet и внедрить методы __getstate__ и __setstate__, которые преобразуют функцию в объекте из и в доступное для выбора представление. Подробнее см. здесь.

def packet_getstate(self):
    # todo

def packet_setstate(self, state):
    # todo

from scapy.packet import Packet
Packet.__getstate__ = packet_getstate
Packet.__setstate__ = packet_setstate
person piro    schedule 23.11.2010
comment
Это как-то очевидно для меня. Неочевидная часть — это часть задач. - person Helmut Grohne; 23.11.2010
comment
Интерактивная проверка объекта Packet, который не прошел травление (pprint.pprint(packet.__dict__)), легко покажет, что это за функция, будь то лямбда, функция или метод экземпляра. Вы уже знаете, что это за функция? - person piro; 24.11.2010
comment
Полная трассировка слишком длинная для комментария, но вы можете легко воспроизвести ее самостоятельно. Последняя строка: pickle.PicklingError: Не удается распарить ‹функция ‹лямбда› по адресу 0x8bb2bc4›: она не найдена как scapy.layers.inet.‹лямбда› - person Helmut Grohne; 25.11.2010

Чтобы заставить класс PicklabePacket работать с scapy 3.0.0, вы можете использовать это определение класса:

class PicklablePacket:
"""A container for scapy packets that can be pickled (in contrast
to scapy packets themselves).
This works for python 3.5.1 and scapy 3.0.0 """

def __init__(self, pkt):
    self.__contents = pkt.__bytes__()
    self.__time = pkt.time

def __call__(self):
    """Get the original scapy packet."""
    pkt = scapy.all.Ether(self.__contents)
    pkt.time = self.__time
    return pkt
person Hephestos    schedule 28.05.2016