Como o SO resolve um pedido para se conectar a 0.0.0.0?

0

Pelo que entendi, 0.0.0.0 significa todas as interfaces de rede deste host (incluindo 127.0.0.1).

Suponha que eu tenha três interfaces 192.0.2.40, 203.0.113.150 e 127.0.0.1 em algum host (OS Linux).

Em 192.0.2.40:777, eu tenho ServerA. Em 203.0.113.150:777, eu tenho ServerB. Como o SO resolve um pedido para se conectar a 0.0.0.0? Quero dizer, quando a mesma porta (777) está escutando em diferentes interfaces qual servidor (ServerA ou serverB) e por que será conectado quando eu vou fazer no terminal de this host telnet 0.0.0.0 777

    
por Pavel 23.03.2018 / 08:18

1 resposta

4

Significa apenas isso como um endereço de origem (ou seja, quando vincula um soquete a uma interface local). Como endereço de destino, não tem esse significado - é tecnicamente um endereço ilegal.

No entanto, parece que originalmente o BSD tratou como uma conexão de loopback e o Linux o utiliza.

Para o IPv4, um destino de todos os zeros é tratado em net/ipv4/route.c no tempo de pesquisa da rota:

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;
    }
    ...
}

Que se traduz em "Se o destino estiver vazio, preencha-o com 127.0.0.1 e direcione via interface lo ". O SO finge que você tentou se conectar ao host local.

O mesmo no IPv6 é tratado no nível do protocolo (individualmente pelo TCP e pelo UDP). Por exemplo, net/ipv6/tcp_ipv6.c contém:

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;
    }
    ...
}

Enquanto isso, em 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) */
    ...
}
    
por 23.03.2018 / 08:39