localhost가 127.0.0.1 대신 ::1로 확인되는 이유는 무엇입니까?

localhost가 127.0.0.1 대신 ::1로 확인되는 이유는 무엇입니까?

그것으로 나는 그것을 기대했음에도 불구하고 getent hosts localhost방금 그것을 얻었습니다 . IPv6를 비활성화했기 때문에 더욱 놀랍습니다. 더욱 혼란스러운 것은 내가 언제 핑을 보내고 있는지 입니다. 누군가 이것을 설명할 수 있나요?::1127.0.0.1::1ping localhost127.0.0.1

~: getent hosts localhost
::1             localhost

~: grep 'hosts:' /etc/nsswitch.conf 
hosts: files mymachines myhostname resolve [!UNAVAIL=return] dns

~: cat /etc/sysctl.d/disable_ipv6.conf 
net.ipv6.conf.all.disable_ipv6=1

~: ping ::1
connect: Network is unreachable

~: ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.022 ms

~: ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.015 ms

편집: localhost/etc/hosts.

답변1

찾기가 쉽지는 않지만 재미있습니다 :)).

짧은 답변

gethostbyname2()는 루프백('lo') 인터페이스에 대해 일부 하드코딩된 값과 함께 __lookup_name()을 사용합니다. "getent ports" 명령에 "localhost"를 지정하면 IPv4를 시도하기 전에 IPv6의 기본값을 사용하게 되므로 ::1이 됩니다. 다음과 같이 getent의 코드를 변경하여 127.0.0.1을 얻을 수 있습니다.

  1. Getent 소스 코드 다운로드github에서
  2. getent.c 아래의hosts_keys()에서 다음 줄(#329)을 주석 처리합니다. //else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL)
  3. 소스에서 컴파일하고 실행합니다.

결과:

$make clean && make && ./getent hosts localhost
rm -f *.o
rm -f getent
gcc -g -Wall -std=gnu99 -w -c getent.c -o getent.o
gcc  getent.o -Wall -lm -o getent
127.0.0.1       localhost

자세한 내용은

getent 도구는 다음에서 사용됩니다.이슬람 도서관. 우리가 명령을 실행할 때

$getent hosts localhost

이 도구는 제공된 키를 확인하기 위해 getent.c 아래의 호스트_키() 함수를 호출합니다. 이 함수는 다음 4가지 방법으로 구문 분석을 시도합니다.

  1. IPv6용 gethostbyaddr(이 인스턴스에서는 실패)
  2. IPv4용 gethostbyaddr(이 경우 실패)
  3. IPv6용 gethostbyname2(하드코딩된 값으로 인해 localhost에 대해 항상 성공)
  4. IPv4용 gethostbyname2(#3에서 성공한 이후 시도되지 않음)

모든 musl 기능은 /src/network/ 아래에 구현됩니다.이봐. gethostbyname2()(gethostbyname2.c에서 구현됨)는 __lookup_name()(lookup_name.c에서)을 호출하는 gethostbyname2_r()(gethostbyname2_r.c에서 구현됨)을 호출합니다. __lookup_name()은 다시 호스트 이름을 확인하는 방법에 대한 여러 옵션 역할을 하며, 첫 번째 옵션은 name_from_null입니다(동일한 파일에 있음).

static int name_from_null(struct address buf[static 2], const char *name, int family, int flags)
{
    int cnt = 0;
    if (name) return 0;
    if (flags & AI_PASSIVE) {
            if (family != AF_INET6)
                    buf[cnt++] = (struct address){ .family = AF_INET };
            if (family != AF_INET)
                    buf[cnt++] = (struct address){ .family = AF_INET6 };
    } else {
            if (family != AF_INET6)
                    buf[cnt++] = (struct address){ .family = AF_INET, .addr = { 127,0,0,1 } };
            if (family != AF_INET)
                    buf[cnt++] = (struct address){ .family = AF_INET6, .addr = { [15] = 1 } };
    }
    return cnt;
}

마지막으로 family == AF_INET6일 때 하드코딩된 값::1을 얻는다는 것을 알 수 있습니다. getent는 IPv4보다 먼저 IPv6을 시도하므로 이것이 반환 값이 됩니다. 위에서 보여드린 것처럼 getent에서 IPv4로 강제 해석하면 위 함수에서 하드코딩된 127.0.0.1 값이 생성됩니다.

로컬 호스트의 IPv4 주소를 반환하도록 기능을 변경하려는 경우 가장 좋은 방법은 먼저 getent에 수정 사항을 제출/요청하여 IPv4를 검색하는 것입니다.

도움이 되었기를 바랍니다!

관련 정보