Windows отправляет TCP-соединение к хосту в локальной сети на шлюз по умолчанию - PullRequest
0 голосов
/ 28 марта 2019

Я исследую странную проблему с Windows, и я понятия не имею, что происходит.

У меня есть хост Windows, работающий под Windows 10. Этот хост подключен к двум сетям, нашей локальной сети и беспроводной локальной сети.,Программа в этой системе обменивается данными через WLAN со встроенной системой, подключенной к той же сети WLAN.Связь обычно работает нормально и использует HTTP и некоторый пользовательский протокол TCP.

Когда во встроенной системе выполняется обновление программного обеспечения, необходимо выполнить перезагрузку.Программа Windows отправляет команду во встроенную систему через HTTP.Эта HTTP-транзакция завершается без каких-либо проблем, и встроенная система выполняет перезагрузку.

После завершения HTTP-транзакции программа Windows ждет 10 секунд, начиная опрос встроенного устройства, выполняя TCP-соединения.Время ожидания составляет одну секунду, и повторное подключение TCP повторяется в течение 120 секунд.

Трассировка сети показывает, что после 27 неудачных попыток установить соединение TCP система Windows внезапно прекращает отправку SYN TCPкадры на интерфейсе WLAN, но он начинает отправлять их на маршрутизатор по умолчанию на интерфейсе локальной сети.

Я должен понять, почему Windows внезапно использует маршрутизатор по умолчанию, пытающийся связаться с узлом в локальной сети.: - (

Через некоторое время окна снова начинают использовать интерфейс WLAN. Кажется, это вызвано тайм-аутом записи ARP для встроенной системы. Windows отправляет ответ ARP на интерфейсе WLAN,встроенная система отправляет ответ ARP, а затем Windows снова использует интерфейс WLAN для кадров TCP SYN. ​​К сожалению, к этому времени истек период повторения 120 с.

Кто-нибудь знает, что вызывает такое странное поведениеWindows, где я могу найти документацию об этом и как я могу остановить Windows от этого?

Заранее большое спасибо,

Марио

Обновление

Сегодня я проверил проблему в Windows 7, и Windows 7 ведет себя так же, как в Windows 10. Я также заметил, что запросы HTTP-соединения, исходящие от Internet Explorer, отправляются на шлюз по умолчанию вместо правильного интерфейса. Я проверил маршрутизациютаблица и таблица ARP во время неправильного поведения и обнаружили, что таблица маршрутизации является правильной, ноВ таблице ARP отсутствует запись для встроенной системы.

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

Следующее обновление

Кажется, что это предполагаемое поведение (минимум согласно https://superuser.com/a/743329/941271 и https://superuser.com/a/743329/941271.

Я узнал, что команда arp -a windows не показывает полную таблицу ARP на windows :-(.При использовании netsh interface ipv4 show neighbors я вижу запись для моего целевого IP-адреса, помеченную как недоступную.

Я еще не нашел никакой документации об этой «функции» в документации Microsoft.

Еще одно обновление

Я до сих пор не нашел описания этого поведения от Microsoft, но нашел API для управления соседней таблицей: GetIpNetTable2 () и DeleteIpNetEntry2 ().Вызов DeleteIpNetEntry2 () перед попыткой подключения целевого устройства решает мою проблему.

Вот мой код:

#pragma comment(lib, "iphlpapi.lib")
static void PurgeUnreachableEntry(const boost::asio::ip::address &Addr)
{
    int AF;
    if      (Addr.is_v4()) AF=AF_INET;
    else if (Addr.is_v6()) AF=AF_INET6;
    else                   return;

    PMIB_IPNET_TABLE2 pipTable = NULL;
    unsigned long status = GetIpNetTable2(AF, &pipTable);
    if (status != NO_ERROR) 
    {
        printf("PurgeUnreachableEntry: GetIpNetTable() failed: %s\n", 
            boost::system::error_code(status, boost::system::system_category()).message().c_str());
        return;
    }
    boost::shared_ptr<MIB_IPNET_TABLE2> IpTable(pipTable, FreeMibTable);

    for (unsigned i= 0; i < pipTable->NumEntries; i++) {
        MIB_IPNET_ROW2 &Entry=pipTable->Table[i];

        if (!Entry.IsUnreachable) continue;

        boost::asio::ip::address EntryAddr;
        switch (Entry.Address.si_family)
        {
        case AF_INET:
            EntryAddr = boost::asio::ip::address_v4(*(boost::asio::ip::address_v4::bytes_type*)&Entry.Address.Ipv4.sin_addr);
            break;
        case AF_INET6:
            EntryAddr = boost::asio::ip::address_v6(*(boost::asio::ip::address_v6::bytes_type*)&Entry.Address.Ipv6.sin6_addr, Entry.Address.Ipv6.sin6_scope_id);
            break;
        default:
            continue;
        }

        if (Addr != EntryAddr) continue;

        DeleteIpNetEntry2(&Entry);
    }
}
...