그것으로 나는 그것을 기대했음에도 불구하고 getent hosts localhost
방금 그것을 얻었습니다 . IPv6를 비활성화했기 때문에 더욱 놀랍습니다. 더욱 혼란스러운 것은 내가 언제 핑을 보내고 있는지 입니다. 누군가 이것을 설명할 수 있나요?::1
127.0.0.1
::1
ping localhost
127.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을 얻을 수 있습니다.
- Getent 소스 코드 다운로드github에서
- getent.c 아래의hosts_keys()에서 다음 줄(#329)을 주석 처리합니다. //else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL)
- 소스에서 컴파일하고 실행합니다.
결과:
$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가지 방법으로 구문 분석을 시도합니다.
- IPv6용 gethostbyaddr(이 인스턴스에서는 실패)
- IPv4용 gethostbyaddr(이 경우 실패)
- IPv6용 gethostbyname2(하드코딩된 값으로 인해 localhost에 대해 항상 성공)
- 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를 검색하는 것입니다.
도움이 되었기를 바랍니다!