Можно ли использовать mDNS для разрешения локального адреса? - PullRequest
3 голосов
/ 29 мая 2019

В более раннем обсуждении темы локальных адресов IPv6 я видел комментарий, в котором говорилось:

Некоторые утверждают, что использование адресов вместо имен хостов не рекомендуется для любых типов адресов. Использование mDNS для сопоставления с локальными адресами работает нормально.

Контекстом обсуждения было то, что вам нужно указать интерфейс при использовании локального адреса ссылки.

Я обнаружил, что приведенный выше комментарий удивляет, потому что я не ожидал, что mDNS будет предоставлять информацию о ссылках, поэтому я не ожидал, что он будет работать нормально. Я создал простой тест (ниже), чтобы проверить, содержит ли информация, предоставленная getaddrinfo, ссылку, и обнаружил следующее:

  • Передача адреса и ссылки (например, fe80::a:a:a:a%wlp3s0) в getaddrinfo привела к sockaddr_in6 с sin6_scope_id, установленным в 3 (индекс моей карты WLAN). Это показывает, что getaddrinfo может предоставить информацию о ссылке.

  • Передача имени хоста, разрешаемого только mDNS (который разрешается на тот же локальный адрес ссылки), привела к sockaddr_in6 с sin6_scope_id, установленным в 0, т.е. ссылка не была указана

  • Далее я подтвердил, что программы, в том числе SSH, использующие getaddrinfo для указания ссылки, не будут работать, когда mDNS разрешит локальный адрес канала. Но они будут успешными, если IP-адрес и ссылка указаны явно.


Был ли приведенный выше комментарий неправильным или я ошибся, когда я проверял это? Может ли mDNS разрешить локальный адрес и указать ссылку?

Для справки я тестирую на Debian Buster Linux версии 4.19.0-5-amd647

My nsswitch.conf содержит

hosts:          files mdns4_minimal [NOTFOUND=return] dns myhostname

Testcode.c:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>


int main(int arg_count, char ** args)
{
    struct addrinfo hints, *servinfo, *p;

    for (int i=1; i<arg_count; i++)
    {
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_INET6; // to force IPv6
        hints.ai_socktype = SOCK_STREAM;
        printf("Checking %s\n", args[i]);
        if (getaddrinfo(args[i], "https", &hints, &servinfo)) {
            perror("getaddrinfo");
            continue;
        }

        for(p = servinfo; p != NULL; p = p->ai_next) {
            struct sockaddr_in6 * address = ((struct sockaddr_in6 *)p->ai_addr);
            printf("family %d scope %d\n", address->sin6_family, address->sin6_scope_id);
        }
        freeaddrinfo(servinfo);
    }

    return 0;
}
...