Socket только улавливает исходящие пакеты, а не входящие

Я основал пакетный снифер на этом (часто цитированном) примере проекта. После внедрения пакетов HTTP я заметил, что только HTTP-пакеты, которые я собираю, являются запросами, я не получаю никаких ответов.

Я просмотрел много разных источников, но поскольку используемый код очень часто то же самое, я склонен думать, что он может быть локальным для меня.

Когда я смотрю на свои журналы, я вижу, что каждый пакет имеет свой локальный IP как SourceIP, как для HTTP-пакетов, так и для пакетов, которые поступают в другие порты.

Я представил рабочий образец здесь, который вы можете скопировать-вставить в LINQPad и должен продемонстрировать проблему (добавьте сборки System.Net и System.Net.Socket). Не забудьте выполнить LINQPad как администратор, чтобы иметь доступ к сокету.

Это приводит к сотням/тысячам записей в диапазоне 192.168.0 с 3 исключениями IP-адресов, которые относятся к моему провайдеру хостинга (проверено с помощью nslookup).

private readonly byte[] _data = new byte[4096];   
private Socket _mainSocket;

public void Capture()
{
    _mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
    _mainSocket.Bind(new IPEndPoint(GetLocalIP(), 0));

    var byTrue = new byte[] {1, 0, 0, 0};
    var byOut = new byte[] {1, 0, 0, 0};

    _mainSocket.IOControl(IOControlCode.ReceiveAll, byTrue, byOut); 

    _mainSocket.EnableBroadcast = true;
    _mainSocket.BeginReceive(_data, 0, _data.Length, SocketFlags.None, OnReceive, null);
}

private void OnReceive(IAsyncResult ar)
{
    SocketError error;
    var received = _mainSocket.EndReceive(ar, out error);
    Parse(_data, received);
    _mainSocket.BeginReceive(_data, 0, _data.Length, SocketFlags.None, OnReceive, null);
}

private void Parse(byte[] data, int size)
{
     var packet = new IPHeader(data, size);
     Console.WriteLine (packet.SourceIP.ToString());
}
  • Windows 8.1
  • Гигабитный Ethernet-контроллер Killer e2200 (NDIS 6.30) - Последняя версия драйвера
    • Вчера была установлена ​​автономная сетевая карта, она ничего не меняла.

Сообщение, которое ближе всего к моей проблеме, имеет в качестве решения рабочий код, который у меня уже есть.

Почему я могу отслеживать исходящие пакеты?

Ответ 1

Как упоминалось как @Saibal и @Saverio: проблема с брандмауэром. В качестве временного решения на данный момент я отключу брандмауэр при запуске пакета папок и включении его обратно, когда он останавливается (не принимая неожиданный выход из учетной записи).

Если вы закончите с такой же проблемой, то ваш первый результат для "отключить брандмауэр С#" может быть этот блогпост. Это не сработало в моем случае и вместо этого выбрало NotImplementedException. Я предполагаю, что это возможно только в Windows XP как этот документ MSDN.

К счастью, существуют альтернативы для Vista и выше (тестируется только в Windows 8.1, но это, как предполагается, является преемником и упоминает об этом).

Мой код для отключения/включения брандмауэра:

private static readonly Type policyType = 
                          Type.GetTypeFromProgID("HNetCfg.FwPolicy2");
private static readonly INetFwPolicy2 firewall = 
                         (INetFwPolicy2) Activator.CreateInstance(policyType);

private void DisableFirewall()
{
    var firewallEnabled = firewall.get_FirewallEnabled(
                              NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE);
    if (firewallEnabled)
    {
          firewall.set_FirewallEnabled(
                       NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE, false);
    }
}

Альтернативный способ записи:

firewall.FirewallEnabled[NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE] = false;

К сожалению, MSDN предлагает только примеры кода в C/С++, но вы все равно можете отнять суть этого.

Имейте в виду, что вы должны добавить библиотеку Interop.NetFwTypeLib в свой проект. Вы можете найти его в C:\Windows\SysWOW64\FirewallAPI.dll или 32-битном эквиваленте.

Это очень рудиментарно. На более позднем этапе (эта публикация будет обновляться всякий раз, когда я это сделаю). Я рассмотрю просто добавление программы в список исключений из брандмауэра, но прямо сейчас этого будет достаточно.

Ответ 2

Вы пытались заглянуть в ваш брандмауэр OS/Standalone/Router? Его часто упускают из виду, но у брандмауэров разные правила для входящих и исходящих подключений, и это может быть причиной ваших проблем.

Ответ 3

Проверьте адрес, возвращенный вашим GetLocalIP(). Вы можете получить loopback ip, и в этом случае вы не сможете захватить входящие пакеты. Аналогичная проблема обсуждалась здесь.