Различия между результатами пакета libpcap и данными bsd-сокета с использованием переполнения стека

У меня относительно ограниченный опыт сетевого программирования, и я надеялся, что кто-нибудь может мне помочь с вопросом, возможно, заранее, спасибо за любую помощь! 🙂

У меня есть две программы на C ++, работающие отдельно. Одним из них является простой анализатор пакетов, написанный с помощью библиотеки libpcap, которая фильтрует так, что она прослушивает только пакеты, полученные на конкретном порту, а затем анализирует пакет так, что записывает длину полезной нагрузки и содержимое полезной нагрузки в двоичный файл.

Другая программа представляет собой простую серверную программу bsd socket, которая настроена на прием сообщений на этот конкретный порт с помощью функции recv (), а затем аналогичным образом записывает полученную длину сообщения и содержимое сообщения в двоичный файл.

Кажется, все работает нормально, поэтому, когда я проверяю двоичные выходные файлы, я ожидаю, что их содержимое будет таким же … но, к сожалению, я обнаруживаю, что они только несколько похожи. Кажется, что анализатор пакетов перехватывает те же данные, что и сервер, но он также записывает дополнительные пакеты с 6-байтовыми полезными нагрузками, которые, очевидно, не принимаются серверной программой.

Таким образом, либо анализатор пакетов собирает пакеты, о которых сервер не должен знать, либо серверная программа пропускает пакеты, которые она должна получать. Однако я чувствую некоторую уверенность в том, что серверная программа работает правильно и получает правильные сообщения, поэтому эти дополнительные пакеты, обнаруживаемые анализатором пакетов, сбивают меня с толку. Кто-нибудь знает, что это за дополнительные пакеты и как я могу их отфильтровать?

Заметки:

Клиент, который отправляет данные в порты, которые я слушаю, — это старый компьютер с Windows NT в небольшой сети, он в основном передает двоичные данные в серверную программу для обработки.

К сожалению, я не могу загрузить код благодаря правилам на рабочем месте. Однако примеры того, на что похож мой код, можно найти здесь:
http://www.tcpdump.org/pcap.html
http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html

Еще раз спасибо!

0

Решение

Одним из них является простой анализатор пакетов, написанный с помощью библиотеки libpcap, которая фильтрует так, что она прослушивает только пакеты, полученные на конкретном порту, а затем анализирует пакет так, что записывает длину полезной нагрузки и содержимое полезной нагрузки в двоичный файл.

TCP-порт или UDP-порт?

Если это порт TCP, ваша программа может получать 3-сторонние пакеты рукопожатия и пакеты только для ACK.

Как вы рассчитываете длину полезной нагрузки? Вы должны сделать это, взяв общую длину IP-пакета, вычтя из него длину IP-заголовка (не 20 байтов, а длину из поля длины версии / заголовка), чтобы обработать параметры IP; если эта длина равна < 5, т.е. < 20 байтов, просто отбросьте пакет, это фальшивка), чтобы получить общую длину пакета TCP, а затем вычесть из тот длина заголовка TCP (не 20 байтов, а поле «Смещение данных»), поэтому вы можете обрабатывать параметры TCP; если эта длина равна < 5, т.е. < 20 байтов, просто отбросьте пакет, это фиктивно), чтобы получить длину полезной нагрузки TCP.

Это должно обрабатывать параметры, на которые ссылается mfontanini, а также IP опции.

Если это порт UDP, вы все равно должны обработать параметры IP и получить общую длину пакета UDP, а затем:

  • если это меньше, чем длина в заголовке UDP, отбросьте пакет, это фальшивка;
  • если длина в заголовке UDP < 8, откажитесь от пакета, это фальшивка;
  • в противном случае используйте длину в заголовке UDP, минус 8, в качестве длины полезной нагрузки.

Другая программа представляет собой простую серверную программу bsd socket, которая настроена на прием сообщений на этот конкретный порт с помощью функции recv (), а затем аналогичным образом записывает полученную длину сообщения и содержимое сообщения в двоичный файл.

Это не будет видеть начальное рукопожатие или пакеты только для ACK.

0

Другие решения

Мой магический шар указывает, что эти полезные данные длиной 6 байт могут быть просто опциями TCP. Вам следует пропустить эти опции, если вы хотите работать только с полезной нагрузкой. Обратите внимание, что некоторые пакеты могут содержать как полезную нагрузку, так и некоторые параметры.

Поле смещения данных в пакете TCP указывает, с какой точки начинается полезная нагрузка. Вы можете посмотреть на это Вот в разделе 3.1.

В любом случае, я бы порекомендовал вам использовать какую-то библиотеку более высокого уровня, которая занимается этими вещами внутри. С помощью libtins Вы можете выполнить эту задачу, используя короткий фрагмент, такой как:

#include <tins/tins.h>

using namespace Tins;

bool callback(const PDU &pdu) {
const RawPDU &raw = pdu.rfind_pdu<RawPDU>();
// raw.payload() returns a std::vector<uint8_t>
process_payload(raw.payload());
return true;
}

int main() {
Sniffer some_sniffer(
"eth0",
Sniffer::NON_PROMISC,
"some pcap filter");
some_sniffer.sniff_loop(callback);
}
0

По вопросам рекламы [email protected]