.NET написание файлов PCAP
Все,
Я потратил значительную часть дня, рассматривая различные библиотеки PCAP, и прежде чем я решусь написать писателя PCAP, я бы хотел описать свой сценарий и запросить информацию.
У меня есть клиент, который попросил меня предоставить службу, которая читает файлы pcap и записывает пакеты в свою базу данных по своему выбору. Затем клиент может запросить базу данных (диапазон дат / времени), и в результате должен быть файл pcap, содержащий пакеты, которые соответствуют критериям этого диапазона.
До сих пор я обнаружил, что с библиотеками "дамп", то есть запись pcap, кажется доступным, только когда он связан с конкретным устройством захвата. Это не так для моего сценария.
Я использую PCAP.NET для чтения оригинальных файлов pcap и извлечения пакетов. Я сохраняю пакеты в базе данных, а затем могу прочитать данные из базы данных и воссоздать пакеты, но я не нахожу способ записать результаты запроса в файл pcap.
В простейшем случае рассмотрим структуру данных List типа Packet (настолько плохо знакомую с фактической записью в переполнение стека, что я не знаю, как написать List T с угловыми скобками, которые не фильтруются) - выполните любую из доступных библиотек Поддержка записи этой структуры в PCAP?
Учитывая, что это не является распространенным сценарием, я задаюсь вопросом о достоверности всего сценария. Я должен также отметить, что у меня есть в общей сложности два дня работы с данными PCAP, это должно было быть доказательством концептуального применения, и поэтому вполне возможно, что я упускаю часть знаний, которая делает это тривиальным.
Заранее благодарим вас за ваше драгоценное время, внимание и извинения, если мои попытки с Google и даже больше времени с поиском переполнения стека упустили очевидное.
Крис
2 ответа
Я считаю, что статический метод Pcap.Net PacketDumpFile.Dump() дает вам именно то, что вам нужно.
Вот простой инструмент на C#, который я написал для преобразования ETL в файлы PCAP, пример того, как вы можете написать файл PCAP. Это записывает файл с типом заголовка Link-Layer Ethernet. Обратитесь к http://www.tcpdump.org/linktypes.html для других типов.
Решение Visual Studio здесь https://github.com/chentiangemalc/EtlToCap
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace chentiangemalc
{
public static class NetworkRoutines
{
public static long ConvertEtlToPcap(string source, string destination, UInt32 maxPacketSize)
{
int result = 0;
using (BinaryWriter writer = new BinaryWriter(File.Open(destination, FileMode.Create)))
{
UInt32 magic_number = 0xa1b2c3d4;
UInt16 version_major = 2;
UInt16 version_minor = 4;
Int32 thiszone = 0;
UInt32 sigfigs = 0;
UInt32 snaplen = maxPacketSize;
UInt32 network = 1; // LINKTYPE_ETHERNET
writer.Write(magic_number);
writer.Write(version_major);
writer.Write(version_minor);
writer.Write(thiszone);
writer.Write(sigfigs);
writer.Write(snaplen);
writer.Write(network);
long c = 0;
long t = 0;
using (var reader = new EventLogReader(source, PathType.FilePath))
{
EventRecord record;
while ((record = reader.ReadEvent()) != null)
{
c++;
t++;
if (c == 100000)
{
Console.WriteLine(String.Format("Processed {0} events",t));
c = 0;
}
using (record)
{
if (record.Id == 1001 && record.ProviderName == "Microsoft-Windows-NDIS-PacketCapture")
{
result++;
DateTime timeCreated = (DateTime)record.TimeCreated;
UInt32 ts_sec = (UInt32)((timeCreated.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
UInt32 ts_usec = (UInt32)(((timeCreated.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds) - ((UInt32)((timeCreated.Subtract(new DateTime(1970, 1, 1))).TotalSeconds * 1000))) * 1000;
UInt32 incl_len = (UInt32)record.Properties[2].Value;
if (incl_len > maxPacketSize)
{
Console.WriteLine(String.Format("Packet size of {0} exceeded max packet size {1}, packet ignored",incl_len,maxPacketSize));
}
UInt32 orig_len = incl_len;
writer.Write(ts_sec);
writer.Write(ts_usec);
writer.Write(incl_len);
writer.Write(orig_len);
writer.Write((byte[])record.Properties[3].Value);
}
}
}
}
}
return result;
}
}
}