Назад | Перейти на главную страницу

Почему Windows выбирала неправильный маршрут при попытке подключиться к TCP-серверу?

Я ранее задавал этот вопрос в Stack Overflow, и мне посоветовали переместить вопрос в Server Fault. И вот я здесь :)

Приложение, с которым я работаю, подключается к паре TCP-серверов, работающих на разных компьютерах.

На этот раз мы взяли новую установку Windows на сайт, установили наше приложение, подключили 2 соответствующие сети к клиентскому компьютеру, и в конечном итоге приложение не подключалось к одному из серверов, а другое подключалось просто хорошо. Это снимок экрана с выводом ipconfig:

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

Мы пробовали пинговать сервер, и это было успешно:

Tracert также добился успеха:

И, наконец, это результат вывода маршрута:

IPv4 Route Table 
=========================================================================== 
Active Routes: 
Network Destination        Netmask          Gateway       Interface  Metric 
          0.0.0.0          0.0.0.0     192.168.42.1   192.168.42.136    291 
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331 
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331 
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331 
     192.168.42.0    255.255.255.0         On-link    192.168.42.136    291 
   192.168.42.136  255.255.255.255         On-link    192.168.42.136    291 
   192.168.42.255  255.255.255.255         On-link    192.168.42.136    291 
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331 
        224.0.0.0        240.0.0.0         On-link    192.168.42.136    291 
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331 
  255.255.255.255  255.255.255.255         On-link    192.168.42.136    291 
=========================================================================== 
Persistent Routes: 
  Network Address          Netmask  Gateway Address  Metric 
      192.168.3.0    255.255.255.0      192.168.3.1       1 
          0.0.0.0          0.0.0.0     192.168.42.1  Default  
=========================================================================== 

мы заметили, что журнал клиентского приложения сбрасывал это при попытке подключения: IpUtility.CheckIPRouting IP address 192.168.3.2 incorrectly routed through 192.168.42.136.

Мы открыли исходный код приложения и заметили, что все, что он делает, это запрашивает интерфейс, используемый для конкретного удаленного IP-адреса (который я не особо понимаю):

Это отрывок из CheckIPRouting:

        public static void CheckIPRouting(IPAddress iPAddressTarget, IPAddress ipAddressGateway)
        {
            IPEndPoint remoteEndPoint = new IPEndPoint(iPAddressTarget, 0);
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress localEndPoint = QueryRoutingInterface(socket, remoteEndPoint);
            if (localEndPoint.Equals(ipAddressGateway))
            {
                log.Trace($"IP address {iPAddressTarget} correctly routed through {localEndPoint.MapToIPv4()}");
            }
            else
            {
                log.Debug($"IP address {iPAddressTarget} incorrectly routed through {localEndPoint.MapToIPv4()}");
            }
        }

А это QueryRoutingInterface:

        private static IPAddress QueryRoutingInterface(Socket socket, IPEndPoint remoteEndPoint)
        {
            SocketAddress address = remoteEndPoint.Serialize();

            byte[] remoteAddrBytes = new byte[address.Size];
            for (int i = 0; i < address.Size; i++)
            {
                remoteAddrBytes[i] = address[i];
            }

            byte[] outBytes = new byte[remoteAddrBytes.Length];
            socket.IOControl(IOControlCode.RoutingInterfaceQuery, remoteAddrBytes, outBytes);
            for (int i = 0; i < address.Size; i++)
            {
                address[i] = outBytes[i];
            }

            EndPoint ep = remoteEndPoint.Create(address);
            return ((IPEndPoint) ep).Address;
        }

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

            logger.Info("Creating tcpClient for {0} using address {1}", connectionResourceName, adapterAddress);
            IPEndPoint adapter = new IPEndPoint(adapterAddress, 0);
            tcpClient = new TcpClient(adapter);

Что было хорошо видно в журнале приложения:

Creating tcpClient for RESOURCE using address 192.168.3.1

В этот момент я был сбит с толку. Тогда я решил изменить конфигурацию приложения и вместо использования 192.168.3.1 интерфейс для установки соединения, я изменил адрес интерфейса на 0.0.0.0.

Тогда связь была установлена!

Печать маршрута в этой точке стала:

IPv4 Route Table 
=========================================================================== 
Active Routes: 
Network Destination        Netmask          Gateway       Interface  Metric 

          0.0.0.0          0.0.0.0     192.168.42.1   192.168.42.136    291 
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331 
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331 
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331 
      192.168.3.0    255.255.255.0         On-link       192.168.3.1      2 
      192.168.3.1  255.255.255.255         On-link       192.168.3.1    257 
    192.168.3.255  255.255.255.255         On-link       192.168.3.1    257 
     192.168.42.0    255.255.255.0         On-link    192.168.42.136    291 
   192.168.42.136  255.255.255.255         On-link    192.168.42.136    291 
   192.168.42.255  255.255.255.255         On-link    192.168.42.136    291 
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331 
        224.0.0.0        240.0.0.0         On-link    192.168.42.136    291 
        224.0.0.0        240.0.0.0         On-link       192.168.3.1    257 
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331 
  255.255.255.255  255.255.255.255         On-link    192.168.42.136    291 
  255.255.255.255  255.255.255.255         On-link       192.168.3.1    257 
=========================================================================== 
Persistent Routes: 
  Network Address          Netmask  Gateway Address  Metric 
      192.168.3.0    255.255.255.0      192.168.3.1       1 
          0.0.0.0          0.0.0.0     192.168.42.1  Default  
=========================================================================== 

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

Затем я сравнил 2 отпечатка маршрута (до и после). Я заметил следующие новые записи на втором:

      192.168.3.0    255.255.255.0         On-link       192.168.3.1      2 
      192.168.3.1  255.255.255.255         On-link       192.168.3.1    257 
    192.168.3.255  255.255.255.255         On-link       192.168.3.1    257 
        224.0.0.0        240.0.0.0         On-link       192.168.3.1    257
  255.255.255.255  255.255.255.255         On-link       192.168.3.1    257

Я предполагаю, что все это имеет значение. Но я думал, что постоянный маршрут с этим справится.

Наконец, я подхожу к вопросу:

Почему Windows проигнорировала постоянный маршрут и решила направлять TCP-пакеты через неправильный интерфейс? Как я могу сделать это надежным, чтобы Windows не приняла неправильное решение?

Для справки, это с Windows 10 IoT Enterprise.

Добавленный вами постоянный маршрут не нужен, возможно, неправильный.

Persistent Routes: 
Network Address          Netmask  Gateway Address  Metric 
      192.168.3.0    255.255.255.0      192.168.3.1       1 

Вы сказали Windows: «Отправляйте все сообщения, адресованные в подсеть 192.168.3.0/24, через шлюз 192.168.3.1».

192.168.3.0/24 напрямую подключена к сети. Вам не нужны никакие маршруты для общения.

Во-первых route print На выходе не было информации о том, как общаться с сетью 192.168.3.0/24. Это могло быть вызвано отключением интерфейса / отсоединением кабеля. Можете ли вы воспроизвести проблему на другой машине?