boost::asio::connect 在错误的子网上报告成功

boost::asio::connect reports success on wrong subnet

使用 Boost v1.74:

int main()
{
    auto ctx = boost::asio::io_context{};
    auto socket = boost::asio::ip::tcp::socket{ctx};
    auto ep = boost::asio::ip::tcp::endpoint{
                     boost::asio::ip::make_address_v4("192.168.0.52"),
                     80};
    boost::asio::connect(socket, std::array{std::move(ep)});

    std::cout << "Success!" << std::endl;
}

我的机器在本地网络上的 IP 地址是 192.168.0.31/24,因此尝试使用上述代码连接到同一子网中不存在的地址会得到:

10:24:55: Starting /home/cmannett85/workspace/build-scratch-Desktop-Debug/scratch ...
terminate called after throwing an instance of 'boost::wrapexcept<boost::system::system_error>'
  what():  connect: No route to host
10:24:59: The program has unexpectedly finished.

这都是预料之中的。如果我更改地址中子网的底部八位字节(例如 192.168.1.52),那么该应用程序只会等待几分钟 - 大概 因为它向任何路由器发送了消息查看他们是否拥有请求的子网。我的网络上没有任何路由器,因此最终超时:

10:27:39: Starting /home/cmannett85/workspace/build-scratch-Desktop-Debug/scratch ...
terminate called after throwing an instance of 'boost::wrapexcept<boost::system::system_error>'
  what():  connect: Connection timed out
10:29:49: The program has unexpectedly finished.

同样,如预期的那样。如果我改为更改 next 八位字节(例如 192.167.0.52),我希望它的行为与前一个完全相同,因为它是一个同样未知的子网。但它成功了!

10:31:22: Starting /home/cmannett85/workspace/build-scratch-Desktop-Debug/scratch ...
Success!

这个地址绝对不在我的网络上:

$ ping 192.167.0.52
PING 192.167.0.52 (192.167.0.52) 56(84) bytes of data.
^C
--- 192.167.0.52 ping statistics ---
17 packets transmitted, 0 received, 100% packet loss, time 16368ms

那么为什么代码报告它已连接?为什么更改第二个八位字节与第三个不同?

这与我的 VPN 有关。我不认为它是相关的,因为隧道地址是 10.17.0.60/16,但禁用它会使上面的代码按预期工作。

感谢@dewaffled 的建议,Curl 显示此连接的另一端有 某物 正在完成 TCP 握手,但在几个超时之后分钟关闭连接。

$ curl -v http://192.167.0.52
*   Trying 192.167.0.52:80...
* Connected to 192.167.0.52 (192.167.0.52) port 80 (#0)
> GET / HTTP/1.1
> Host: 192.167.0.52
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Recv failure: Connection reset by peer
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer

我对 VPN 的工作原理一无所知,但我怀疑这是我的特定提供商的实施细节。希望这个 'answer' 会减少其他人的困惑!

192.168.xx.xx 形式的任何 IP 地址都是不可通过 Internet 路由的网络。这意味着没有互联网路由器会路由它。因此,数据包从您的子网路由出去的唯一方法是在您自己的路由器或主机上配置路由。 192.167.xx.xx 是一个 Internet 可路由网络,可以推测 Internet 上有一台主机使用您指定的地址。因此,如果您可以将您的主机连接到互联网,一些互联网路由器会将您的数据包发送到指定的地址。