Как я понимаю, 0.0.0.0 означает все сетевые интерфейсы этого хоста (включая 127.0.0.1).

Предположим, у меня есть три интерфейса 192.0.2.40, 203.0.113.150 и 127.0.0.1 на некотором хосте (ОС Linux).

На 192.0.2.40:777 у меня есть ServerA. На 203.0.113.150:777 у меня есть ServerB. Как ОС разрешает запрос на подключение к 0.0.0.0? Я имею в виду, когда один и тот же порт (777) прослушивает на разных интерфейсах, какой сервер (ServerA или serverB) и почему будет подключен, когда я буду делать в терминале this хоста telnet 0.0.0.0 777

1 ответ1

4

Это только означает, что в качестве адреса источника (т.е. при привязке сокета к локальному интерфейсу). В качестве адреса назначения это значение не имеет - это технически недопустимый адрес.

Однако, похоже, что изначально BSD рассматривал это как петлевое соединение, и Linux продолжает его.

Для IPv4 назначение всех нулей обрабатывается в net/ipv4/route.c во время поиска маршрута:

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 ». ОС делает вид, что вы пытались подключиться к localhost.

То же самое в 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) */
    ...
}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .