Отображение сетевого трафика

В общем. При переходе на Windows 10 (да, именно 10) обнаружилось, что моя любимая программа для мониторинга сетевого трафика BWMeter начала глючить. То скорость обрежет, то вообще интернет заблочит. Но если на Windows 10 её хоть как-то можно заставить работать, то на Windows 11 всё плохо. Вероятно, это сильно зависит от драйверов на сетевуху и у кого-то на его сетевухе будет нормально работать, но на моём ноутбуке - всё плохо. Пробовал ставить другие программы, но они все либо не удобные, либо функционал не тот, либо фаервола нет, либо рисуют график не так как я хочу. По сравнению с ними, BWMeter был идеален. Уже очень давно его юзаю.
Недавно я решил погулить, как же на винде осуществляется перехват трафика и что в этом такого сложного. Все примеры кода (если таковые и есть) используют WinPCap. Это что-то типа библиотеки для перехвата сетевых пакетов. На его сайте написано, что авторы забили на проект и, сорян, но обновлений больше не будет. Вероятно, есть ещё подобные библиотеки, но так ведь не интересно :grin:
Гулил дальше и нашел пример простейшего сниффера (без WinPCap):

Попробовал запустить - работает (и, вроде, даже правильно :grin: ). Конечно, так никакого фаервола не получится (для этого надо писать какой-то драйвер в режиме ядра), но даже так можно написать простую отображалку трафика.
Однако, остались непонятны две вещи:

  1. Как отличить входящий пакет от исходящего?
    При запуске предлагается выбрать интерфейс, который будем снифферить:

Initialising Winsock...Initialised
Creating RAW Socket...Created.
Host name : MIKROSHA

Available Network Interfaces :
Interface Number : 0 Address : 192.168.121.1
Interface Number : 1 Address : 26.37.131.105
Interface Number : 2 Address : 192.168.118.1
Interface Number : 3 Address : 192.168.88.250
Enter the interface number you would like to sniff :

Потом каждый пакет выводится в лог:

	fprintf(logfile," |-Source IP : %s\n",inet_ntoa(source.sin_addr));
	fprintf(logfile," |-Destination IP : %s\n",inet_ntoa(dest.sin_addr));

Source IP всегда равен IP-адресу интерфейса, который был выбран. Не пойму, почему так :thinking: А Destination IP отображается, видимо, правильно :man_shrugging:

  1. Вот у нас есть бесконечный цикл прослушивания сокета:

	do
	{
		mangobyte = recvfrom(sniffer , Buffer , 65536 , 0 , 0 , 0);

		if(mangobyte > 0)
		{
			ProcessPacket(Buffer, mangobyte); //тут обработка и выхлоп
		}
		else
		{
			printf( "recvfrom() failed.\n");
		}
	}
	while (mangobyte > 0);

Когда проект консольный - всё нормально. А как прикрутить это к окну? У окна же свой цикл. Если запустить цикл прослушивания - окно зависнет. Через потоки? А окно не задохнётся от синхронизации на каждый пакет?

Сейчас ещё потестил. Так только у TCP протокола. У UDP меняется. Как будто у TCP ловится только исходящий трафик :thinking: Но почему? :thinking:

Так они ж там и отослали к npcap.

А оно выводит и те, и те?

Ну можно не на каждый, а копить сколько-то времени.

Упс, не заметил.
В любом случае, написать простой сниффер (с целью отображения траффика), используя библиотеки, сможет даже восьмиклассник :grin: Скорее всего, я так и сделаю. И, скорее всего, не на C++, а на C#.
Но вопрос не в этом. Интересно, почему код по ссылке не работает :thinking:

Ну яж говорю - выводит вроде всё, только значение Source IP для TCP-пакетов всегда одно и то же :man_shrugging: Как будто он входящие TCP-пакеты не ловит :thinking:

Наткнулся я сегодня на вот такой вот сайт

где описана такая же проблема. Там рекомендуют добавить екзешник в исключения файрволла. И правда! RAW_SOCKET начинает ловить входящие пакеты.
:man_facepalming: Я бы сам никогда до этого не допёр :confusedparrot: