#python #writer #dpkt #pcapy
#питон #писатель #дпкт #пкэпи
Вопрос:
У меня возникли некоторые проблемы с утилитой захвата пакетов, которую я пишу. В настоящее время я использую pcapy для открытия текущего байтового потока и dpkt для декодирования пакетов. Я хочу также записывать пакеты в файл .pcap, который работает с dpkt.Объект записи, однако временные метки, которые записываются в файл pcap, относятся к моменту, когда устройство записи записывает пакет в файл pcap, а не когда сетевой интерфейс или ядро получили сообщение.
Из документации я понимаю, что при записи вы можете указать ts для использования writer, однако я не понимаю, как извлечь его из заголовка полученного пакета. Из примеров, которые я могу найти, которые показывают, как печатать временную метку при чтении файла, может показаться, что я мог бы просто напечатать первое значение кортежа, которое я получаю из байтового потока, однако, когда я это делаю, я получаю следующую ошибку:
TypeError: аргумент int() должен быть строкой, байтоподобным объектом или числом, а не ‘Pkthdr’
Ошибка достаточно очевидна: мне, без сомнения, нужно найти атрибут timestamp в объекте Pkthdr, но я не могу найти никакой документации / примеров ни в проекте pcapy, ни в dpkt, которые объясняли бы, как анализировать «заголовок»
Я также пытался использовать библиотеку pypcap для записи в реальном времени, но результат тот же. Я также попытался использовать тот же код на python 2.7.5, поскольку прочитал, что dpkt может еще не полностью поддерживать python3, но тот же результат для любой версии
#!/usr/bin/env python3.6
import pcapy
import dpkt
cap = pcapy.open_live("eth0", 65435, True, 100)
writer = dpkt.pcap.Writer(open("test.pcap", 'wb '))
while True:
(header,packet) = cap.next()
writer.writepkt(packet, header)
print('packet printed')
Чтобы доказать, что временные метки в pcap относятся к моменту написания, я добавил период ожидания перед повторной записью того же пакета. Вы увидите, что они показывают разницу во временной метке заголовка ~ в 1 секунду:
#!/usr/bin/env python3.6
import pcapy
import dpkt
import time
cap = pcapy.open_live("em2", 65435, True, 100)
writer = dpkt.pcap.Writer(open("test.pcap", 'wb '))
while True:
(header,packet) = cap.next()
writer.writepkt(packet, )
time.sleep(1)
writer.writepkt(packet, )
print('packet printed')
Я не сильно зависим ни от pcapy, ни от dpkt, поэтому я готов отказаться от любой из этих библиотек, если есть лучший метод, однако у меня такое чувство, что кто-то с немного большим опытом мог бы показать мне, как копаться в объекте Pkthdr, извлекать временную метку в виде str и затем вставьте его в качестве аргумента ‘ts’ при записи в pcap:
ts = %unpack from header%
writer.writepkt(packet, ts)
редактировать: итак, я просмотрел исходный код объекта pkthdr в модуле pcapy и нашел кое-что полезное: похоже, что существует функция с именем ‘getts’ для получения временной метки из объекта:
static PyMethodDef p_methods[] = {
{"getts", (PyCFunction) p_getts, METH_VARARGS, "get timestamp tuple
(seconds, microseconds) since the Epoch"},
{"getcaplen", (PyCFunction) p_getcaplen, METH_VARARGS, "returns the length
of portion present"},
{"getlen", (PyCFunction) p_getlen, METH_VARARGS, "returns the length of
the packet (off wire)"},
{NULL, NULL} /* sentinel */
};
в моем коде Python я вызвал функцию следующим образом:
timestamp = header.getts()
И он вернул кортеж, содержащий секунды и микросекунды заголовка, например (1555710256, 942645). Следующий шаг — объединить это в одно число и ввести его в ts записи dpkt. Я опубликую рабочий пример, надеюсь, очень скоро
Ответ №1:
Хорошо, я адекватно решил свою проблему. точность временной метки выражается в микросекундах и одинакова для обеих копий в файле .pcap.
#!/usr/bin/env python3.6
import pcapy
import dpkt
import time
cap = pcapy.open_live("em2", 65435, True, 100)
(header,packet) = cap.next()
timestamp = header.getts()
print (timestamp)
writer = dpkt.pcap.Writer(open("test.pcap", 'wb '))
while True:
(header,packet) = cap.next()
ts = header.getts()
now = time.time()
print (ts)
timestamp = ts[0] (float(ts[1])/1000000))
writer.writepkt(packet, timestamp)
time.sleep(1)
writer.writepkt(packet, timestamp)
print('packet printed')