为什么 Windows 在尝试连接 TCP 服务器时选择了错误的路由?

为什么 Windows 在尝试连接 TCP 服务器时选择了错误的路由?

我之前在 Stack Overflow 上问过这个问题,有人建议我将这个问题转到 Server Fault。所以我就在这里 :)

我正在使用的应用程序连接到在不同计算机上运行的几个 TCP 服务器。

有一次,我们将全新的 Windows 安装带到现场,安装了我们的应用程序,将 2 个相关网络插入客户端计算机,最终应用程序无法连接到其中一个服务器,而另一个服务器可以正常连接。这是 ipconfig 输出的屏幕截图:

在此处输入图片描述

我们无法连接的服务器有 IP 地址192.168.3.2。运行应用程序的客户端有 IP 地址192.168.3.1

我们尝试 ping 服务器,并且成功了: 在此处输入图片描述

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。

答案1

您添加的持久路线是不必要的,可能是错误的。

持久路线:
网络地址 网络掩码 网关地址 度量
      192.168.3.0 255.255.255.0 192.168.3.1 1

您对 Windows 说:“通过 192.168.3.1 网关发送所有发往 192.168.3.0/24 子网的通信。”

192.168.3.0/24 是直连网络。无需任何路由即可进行通信。

在第一个route print输出中,没有关于如何与 192.168.3.0/24 网络通信的信息。这可能是由于接口关闭/电缆断开造成的。您可以在不同的机器上重现此问题吗?

相关内容