컬 명령을 추적했습니다.
strace -s 2000 -f curl google.com
2개의 DNS 쿼리를 참조하세요.
recvfrom(3, "\302\325\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\34\0\1\6google\3com\0\0\34\0\1\0\0\0\362\0\20*\0\24P@\t\10\v\0\0\0\0\0\0 \16", 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.65.7")}, [28->16]) = 66
recvfrom(3, "X\320\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\1\0\1\6google\3com\0\0\1\0\1\0\0\1)\0\4\216\372\263\356", 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.65.7")}, [28->16]) = 54
그런 다음 Google의 IP인 142.250.179.238에 대한 connect() 시스템 호출을 봅니다.
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("142.250.179.238")}, 16) = 0
나는 2개의 recvfrom 호출 중 하나에 IP "142.250.179.238"이 포함되어 있다고 생각합니다. 그렇지 않으면 컬은 어떤 IP에 연결할지 알 수 없습니다.
내 질문: 2개의 recvfrom 문자열의 형식은 무엇입니까? 그리고 IP 주소를 얻기 위해 이를 구문 분석하는 방법은 무엇입니까?
"\302\325\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\34\0\1\6google\3com\0\0\34\0\1\0\0\0\362\0\20*\0\24P@\t\10\v\0\0\0\0\0\0 \16"
"X\320\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\1\0\1\6google\3com\0\0\1\0\1\0\0\1)\0\4\216\372\263\356"
답변1
recvfrom(2)
다음과 같이 문서화되어 있습니다(아래 Linux 매뉴얼 페이지 사용).
ssize_t recvfrom(int sockfd, void buf[restrict .len], size_t len, int flags, struct sockaddr *_Nullable restrict src_addr, socklen_t *_Nullable restrict addrlen);
또는 더 간단하게POSIX정의:
ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, socklen_t *restrict address_len);
출력을 이해하려면 strace
각 시스템 호출에 대한 매뉴얼 페이지를 읽어야 합니다.
버퍼/버퍼는 시스템 호출 성공 후 수신된 데이터를 제공하는 공간으로, strace
C와 유사한 방식으로 그 내용을 다시 표시합니다.
버퍼 공간은 C에서와 같이 인코딩된 바이트 시퀀스로 표시되며 에서 표시하는 버퍼나 문자열과 동일합니다 strace
. 그 뒤에 \
3자리 숫자가 오면8진수숫자는 간단한 ASCII 문자 또는 C 언어에서 정의된 미리 정의된 특수 기본 표시 형식( \n
아래 두 번째 명령에 사용되는 것과 같은 일부 특수 문자의 경우)으로 표시할 수 없는 바이트 값을 나타냅니다. printf
예시 보기위키피디아 참조이에:
\nnn
그 값은nnn
주어진 바이트로 해석 됩니다.8진수
우리가 찾고 있는 것이 무엇인지 알고 있으므로(8진수):
$ printf '\\%o' 142 250 179 238; printf '\n'
\216\372\263\356
이는 두 번째 데이터의 끝 부분에서 볼 수 있습니다 recvfrom()
.
물론 이것은 더 이상 시스템 호출에 관한 것이 아니라 DNS 프로토콜에 관한 것입니다. DNS 응답에 대해 자세히 알아보려면 특히 이에 대해 설명하는 RFC를 읽어보세요.RFC 1035: 도메인 이름 - 구현 및 사양 섹션 4.1.3. 리소스 레코드 형식:
Each resource record has the following format: 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / / / NAME / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| / RDATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
각 부분은 이 RFC에 설명되어 있습니다(여기서 RDLENGTH = 4이고 RDATA는 4바이트 IPv4 주소를 보유함).
FWIW, 수신된 첫 번째 응답은 IPv6 응답입니다. 여기서 \034
28은 AAAA
IPv6 레코드(RFC 3596 - 2.1 AAAA 레코드 유형A
) IPv4 레코드의 경우 1 대신 .