티스토리 뷰

IT/Network

[WinSock2] IP 주소 정보를 이용하여 도메인 이름 구하기 (getnameinfo, GetNameInfo)

주인장 진빼이

과거엔 gethostbyaddr() 함수를 호출했으나 이젠 depcated 되어 사용 시 다음과 같은 오류가 발생된다.

강제적으로 사용하고 싶다면 오류 내용에 적혀 있듯이 "_WINSOCK_DEPRECATED_NO_WARNINGS" 를 define 하자.

'gethostbyaddr': Use getnameinfo() or GetNameInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings

 

 

MS(Microsoft)에서 사용을 권하고 있는 getnameinfo(), GetNameInfo() 함수에 대해 알아볼 것이다.

두 함수는 IP 주소 정보(IP, Port)를 이용하여 FQDN을 구할 수 있다.

이 함수는 보안에 취약하고 신뢰성이 떨어지는 함수이다. 참고용으로만 사용하도록 하자.

 

getnameinfo() 함수는 DNS서버가 reverseDNS가 활성화 되어 있어야 한다.

하지만 오늘날의 DNS는 보안상의 이유로 reverse DNS를 활성화 하지 않는다.

그럼 도메인에 등록된 아이피는 어디서 확인하느냐 ? Whois에서 확인하도록 하자.

 

 

FQDN란 ?

 

 

prototype

#define WINSOCK_API_LINKAGE DECLSPEC_IMPORT
#define DECLSPEC_IMPORT __declspec(dllimport)

//==== ANSI ====//
WINSOCK_API_LINKAGE
INT
WSAAPI
getnameinfo(
    _In_reads_bytes_(SockaddrLength)    const SOCKADDR *    pSockaddr,
    _In_                                socklen_t           SockaddrLength,
    _Out_writes_opt_(NodeBufferSize)    PCHAR               pNodeBuffer,
    _In_                                DWORD               NodeBufferSize,
    _Out_writes_opt_(ServiceBufferSize) PCHAR               pServiceBuffer,
    _In_                                DWORD               ServiceBufferSize,
    _In_                                INT                 Flags
    );


//==== UNICODE ====//
WINSOCK_API_LINKAGE
INT
WSAAPI
GetNameInfoW(
    _In_reads_bytes_(SockaddrLength)    const SOCKADDR *    pSockaddr,
    _In_                                socklen_t           SockaddrLength,
    _Out_writes_opt_(NodeBufferSize)    PWCHAR              pNodeBuffer,
    _In_                                DWORD               NodeBufferSize,
    _Out_writes_opt_(ServiceBufferSize) PWCHAR              pServiceBuffer,
    _In_                                DWORD               ServiceBufferSize,
    _In_                                INT                 Flags
    );

 

 

매개변수와 반환 값

멤버 설명
[in]const SOCKADDR *pSockaddr 주소 정보 구조체에 대한 포인터 (sockaddr_in, sockaddr_in6)
[in]sockle_t SockaddrLength 주소 정보 구조체 길이
[out]PCHAR pNodeBuffer FQDN 이름을 저장할 버퍼 포인터
[in]NodeBufferSize FQDN 이름을 저장할 NULL 문자를 포함한 크기 (Byte)
[out]PCHAR pServiceBuffer 서비스 이름을 저장할 버퍼 포인터
[in]ServiceBufferSize 서비스 이름을 저장할 NULL 문자를 포함한 크기 (Byte)
[in]INT Flags 플래그 값
필요한 헤더: WS2tcpip.h

pNodeName에 "localhost"를 전달한다면 루프백 주소가 반환되고 Windows Server 2003 이상에서 "localmachine" 문자열을 전달하는 경우 로컬 컴퓨터에 등록된 모든 주소가 반환된다.

버퍼 사이즈 크기를 명시할 땐 상수를 이용할 수 있는데 서비스는 NI_MAXSERV를 이용하고, FQDN은 NI_MAXHOST를 이용하면 된다.

#define NI_MAXSERV 32
#define NI_MAXHOST 1025

 

Flags

OR 비트연산자를 이용하여 플래그적용시킬 수 있다.

플래그 목록과 설명은 다음과 같다.

플래그 설명
NI_NOFQDN 로컬 호스트의 상대 고유 이름(RDN)만 NodeBuffer에 반환됩니다.
NI_NAMEREQD DNS에서 확인할 수 없는 도메인 이름은 오류가 발생합니다
NI_NUMERICHOST IP주소의 숫자 형식이 반환됩니다. 
NI_NUMERICSERV 도메인 이름이 아니라 서비스의 포트 번호를 반환합니다. IP 주소 (예 : 127.0.0.2)의 호스트 이름을 찾을 수 없는 경우 호스트 이름을 IP 주소로 반환됩니다.
NI_DGRAM 서비스가 데이터 그램 서비스임을 나타냅니다. UDP 및 TCP 서비스에 다른 포트 번호를 제공하는 서비스에 필요합니다.

 

 

함수가 성공적으로 실행되어 반환됬다면 0을 반환하고 out 매개변수에 각 정보를 반환한다 그외 값은 오류코드(error_code)를 반환한다. gai_strerror() 함수를 호출하면 자세한 오류 내용을 알 수 있다. 함수를 호출할 때 반환받은 오류 코드를 전달해야 한다. gai_strerror() 함수는 스레드에 안전하지 않으므로 스레드에 안전한 WSAGetLastError() 함수를 호출하여 오류 내용을 확인하는 것이 더 좋다.

 

예제를 적어볼까 했지만 reverseDNS를 활성화 시킨 사이트는 찾기가 힘들었다.

간혹 NS(Name Server)가 활성화 되어 있긴 했다.

reverseDNS 문제 때문에 시간 엄청 낭비했다. (몰랐었다)

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함