操作系统如何解析连接 0.0.0.0 的请求?

操作系统如何解析连接 0.0.0.0 的请求?

据我了解,0.0.0.0 表示该主机的所有网络接口(包括 127.0.0.1)。

假设我在某个主机(OS Linux)上有三个接口 192.0.2.40、203.0.113.150 和 127.0.0.1。

在 192.0.2.40:777 上,我有 ServerA。在 203.0.113.150:777 上,我有 ServerB。操作系统如何解析连接到 0.0.0.0 的请求?我的意思是,当同一端口 (777) 正在监听不同的接口时,我将在主机终端执行什么操作,以及为什么会连接哪个服务器(ServerA 或 serverB thistelnet 0.0.0.0 777

答案1

正式来说,它只是意味着作为源地址(即当捆绑本地接口的套接字)。作为目标地址,它没有这个含义——从技术上讲它是一个非法地址。

然而,BSD 最初似乎是这样处理的作为环回连接Linux 继续延续这一传统:

  • UNIX 系统管理员手册 – 4.3BSD 中的内核更改 –第 7.1 节(SMM:13-21)/usr/doc/smm/13.kchanges在 4.3BSD 源代码树中):

    在PCB中

    目标地址连接可以给出 INADDR_ANY (0) 作为“此主机”的简写符号。这简化了连接到本地服务器(例如将主机名转换为地址的名称域服务器)的过程。

net/ipv4/route.c在 Linux 中,全零的 IPv4 目标在路由查找时处理:

struct rtable *ip_route_output_key_hash_rcu(...) {
    ...
    if (!fl4->daddr) {
        fl4->daddr = fl4->saddr;
        if (!fl4->daddr)
            fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
        dev_out = net->loopback_dev;
        fl4->flowi4_oif = LOOPBACK_IFINDEX;
        res->type = RTN_LOCAL;
        flags |= RTCF_LOCAL;
        goto make_route;
    }
    ...
}

意思是“如果目的地为空,则填写 127.0.0.1 并通过接口路由lo”。操作系统会假装您尝试连接到本地主机。

IPv6 中的相同内容在协议级别处理(分别由 TCP 和 UDP 处理)。例如,net/ipv6/tcp_ipv6.c包含:

static int tcp_v6_connect(...) {
    ...
    /*
     *  connect() to INADDR_ANY means loopback (BSD'ism).
     */
    if (ipv6_addr_any(&usin->sin6_addr)) {
        if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
            ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
                           &usin->sin6_addr);
        else
            usin->sin6_addr = in6addr_loopback;
    }
    ...
}

同时在net/ipv6/udp.c

int udpv6_sendmsg(...) {
    ...
    if (!ipv6_addr_any(daddr))
        fl6.daddr = *daddr;
    else
        fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
    ...
}

答案2

假设我在某个主机(OS Linux)上有三个接口 192.0.2.40、203.0.113.150 和 127.0.0.1。

我创建了两个适配器,如以下命令,eth1为其中一个 IP 创建虚拟适配器:

sudo modprobe dummy
sudo ip link add eth1 type dummy
sudo ip addr add 203.0.113.150/24 dev eth1
sudo ip link set dev eth1 up

我的所有请求都0.0.0.0发给那些绑定的应用程序127.0.0.1。如果我停止它,那么我会看到Connection refused错误(即使 203.0.113.150 上的应用程序正在运行)。

我相信@user1686 的答案是正确的,并且它只路由到环回接口127.0.0.1

相关内容