Logo

dig 명령어로 DNS 조회 및 진단하기

도메인을 구매한 후에 DNS 설정을 했는데 브라우저에서 해당 웹사이트에 접속이 안되면 어디서부터 디버깅을 해야 할지 상당히 난감할 수 있는데요.

이번 포스팅에서는 DNS 설정에 문제가 발생했을 때 정말로 유용하게 사용할 수 있는 도구인 dig 명령어에 대해서 알아보겠습니다.

명령어 소개

dig는 Domain Information Groper의 약자로, DNS 정보를 조회하고 진단하기 위한 커맨드 라인 도구인데요. dig라는 영단어가 “파다”, “파헤치다”, “파서 찾아내다” 라는 뜻이 있어서, 도구의 목적을 생각해보면 굉장히 쉽게 떠올릴 수 있는 이름입니다.

dig 명령어를 사용하면 nslookup 명령어로는 얻기 어려운 상세한 DNS 조회 결과를 얻을 수 있기 때문에 네트워크 관리자 뿐만 아니라 일반 개발자들도 알아두면 상당히 유용합니다. 특히 DNS 구성에 문제가 생겼을 때 원인을 찾는데 dig 명령어가 큰 역할을 할 수 있습니다.

명령어 설치

MacOS를 사용하신다면 dig는 이미 설치가 되어 있어서 바로 사용이 가능합니다.

우분투와 같은 데비안 계열의 리눅스를 쓰신다면 apt-get 명령어로 설치가 가능하고요.

$ apt-get install dnsutils

그 밖에 RPM 계열의 리눅스를 쓰시는 분들은 yum 명령어로 설치가 가능합니다.

$ yum install bind-utils

윈도우즈를 쓰신다면 ISC(Internet Systems Consortium) 사이트에서 다운받아 설치할 수 있습니다.

기본 사용법

터미널에서 dig 명령어 다음에 도메인 이름을 명시하면 해당 도메인 이름에 등록되어 있는 DNS 레코드가 조회됩니다.

$ dig <도메인 네임>

예를 들어, 제 블로그의 도메인 네임을 상대로 dig 명령어를 실행해보면 다음과 같은 결과를 얻을 수 있는데요.

$ dig daleseo.com

; <<>> DiG 9.10.6 <<>> daleseo.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42478
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;daleseo.com.			IN	A

;; ANSWER SECTION:
daleseo.com.		600	IN	A	185.199.111.153
daleseo.com.		600	IN	A	185.199.110.153
daleseo.com.		600	IN	A	185.199.108.153
daleseo.com.		600	IN	A	185.199.109.153

;; Query time: 31 msec
;; SERVER: 66.207.192.6#53(66.207.192.6)
;; WHEN: Mon Sep 18 18:09:43 EDT 2023
;; MSG SIZE  rcvd: 104

QUESTION SECTION에 질의한 내용이 나오고, ANSWER SECTION에 조회된 결과가 나옵니다. 위의 경우, daleseo.com 도메인 이름으로 A 유형의 레코드를 질의하고 있으며, 답변으로 4개의 A 유형의 레코드가 조회되었습니다.

레코드 유형 명시

도메인 네임 뒤에 추가로 레코드 유형을 붙이면 해당 레코드 유형의 레코드만을 조회할 수 있습니다.

예를 들어, NS를 명시하여 네임 서버(Name Server)에 대한 레코드만 조회해보겠습니다.

$ dig daleseo.com NS

; <<>> DiG 9.10.6 <<>> daleseo.com NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63269
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;daleseo.com.			IN	NS

;; ANSWER SECTION:
daleseo.com.		86400	IN	NS	curitiba.ns.porkbun.com.
daleseo.com.		86400	IN	NS	maceio.ns.porkbun.com.
daleseo.com.		86400	IN	NS	salvador.ns.porkbun.com.
daleseo.com.		86400	IN	NS	fortaleza.ns.porkbun.com.

;; Query time: 23 msec
;; SERVER: 66.207.192.6#53(66.207.192.6)
;; WHEN: Mon Sep 18 18:14:04 EDT 2023
;; MSG SIZE  rcvd: 142

그러면 4개의 NS 유형의 레코드가 조회되는데요. 이를 통해 daleseo.com 도메인 네임의 권한은 이 4개의 네임 서버에서 관리되고 있다는 것을 알 수 있습니다.

만약에 레코드 유형을 따지지 않고 모든 레코드를 조회하고 싶다면, 레코드 유형을 ANY라고 명시해주면 됩니다.

dig daleseo.com ANY

; <<>> DiG 9.10.6 <<>> daleseo.com ANY
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30080
;; flags: qr rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;daleseo.com.			IN	ANY

;; ANSWER SECTION:
daleseo.com.		592	IN	A	185.199.110.153
daleseo.com.		592	IN	A	185.199.108.153
daleseo.com.		592	IN	A	185.199.109.153
daleseo.com.		592	IN	A	185.199.111.153
daleseo.com.		85147	IN	NS	curitiba.ns.porkbun.com.
daleseo.com.		85147	IN	NS	maceio.ns.porkbun.com.
daleseo.com.		85147	IN	NS	salvador.ns.porkbun.com.
daleseo.com.		85147	IN	NS	fortaleza.ns.porkbun.com.

;; Query time: 5 msec
;; SERVER: 66.207.192.6#53(66.207.192.6)
;; WHEN: Mon Sep 18 18:34:57 EDT 2023
;; MSG SIZE  rcvd: 206

이번에는 A 유형과 NS 유형의 레코드가 한 번에 조회되는 것을 볼 수 있습니다.

DNS 서버 지정

전 세계에는 수 많은 DNS 서버가 있으며 그래서 DNS 설정을 변경하면 모든 서버에 전파되는데 시간이 걸리는데요. 만약에 특정 DNS 서버에 변경한 DNS 설정이 반영되었지 확인하고 싶다면 도메인 이름 앞에 해당 DNS 서버의 IP를 @ 기호와 함께 붙여줄 수 있습니다.

예를 들어서, 구글이 보유하고 있는 IP가 8.8.8.8인 DNS 서버를 상대로 dig 명령어를 사용해볼까요? 참고로 이 DNS 서버는 미국 캘리포니아에 위치하고 있습니다.

$ dig @8.8.8.8 daleseo.com

; <<>> DiG 9.10.6 <<>> @8.8.8.8 daleseo.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9338
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;daleseo.com.			IN	A

;; ANSWER SECTION:
daleseo.com.		600	IN	A	185.199.109.153
daleseo.com.		600	IN	A	185.199.111.153
daleseo.com.		600	IN	A	185.199.110.153
daleseo.com.		600	IN	A	185.199.108.153

;; Query time: 28 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Sep 18 18:19:54 EDT 2023
;; MSG SIZE  rcvd: 104

마지막에 SERVER 부분을 보시면 어느 DNS 서버에서 응답이 수신되었는지가 나오는데요. 8.8.8.8 IP의 53번 포트로 부터 응답이 오는 것을 확인할 수 있습니다.

이렇게 DNS 서버를 명시하지 않으면, 리눅스 계열의 운영 체제의 경우 /etc/resolv.conf 파일에, 윈도우즈에서는 ncpa.cpl 파일에 저장되어 있는 DNS 서버를 사용하게 됩니다.

역방향 DNS 조회

도메인 이름을 통해 IP 주소를 찾는 것이 아니라, 반대로 IP 주소로 도메인 이름을 찾고 싶을 때도 dig 명령어의 -x 옵션을 활용할 수 있습니다. 단, 역방향 DNS 조회 사용되는 PTR 유형의 레코드가 등록되어 있어야 합니다.

예를 들어서, 제 블로그의 도메인 네임의 A 레코드 중 하나의 IP를 한번 조회해보겠습니다.

$ dig -x 185.199.108.153

; <<>> DiG 9.10.6 <<>> -x 185.199.108.153
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9878
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;153.108.199.185.in-addr.arpa.	IN	PTR

;; ANSWER SECTION:
153.108.199.185.in-addr.arpa. 3591 IN	PTR	cdn-185-199-108-153.github.com.

;; Query time: 14 msec
;; SERVER: 66.207.192.6#53(66.207.192.6)
;; WHEN: Mon Sep 18 18:42:32 EDT 2023
;; MSG SIZE  rcvd: 101

해당 IP는 깃허브에서 보유하고 있는 CDN 서버인 cdn-185-199-108-153.github.com를 가리키고 있는 것을 알 수 있습니다. 이 것은 제가 자체 서버를 구축하고 있는 것이 아니라 GitHub Pages라는 호스팅 서비스를 사용하고 있기 때문입니다.

전체 경로 옵션

dig 명령어의 +trace 옵션을 사용하시면 해당 도메인 네임의 IP 주소가 결정되기 위해서 거치게 되는 모든 네임 서버를 추적할 수 있습니다. 즉, 13개의 루트(root) 네임 서버부터 시작해서, TLD(Top-level Domain) 네임 서버를 거쳐, 내 도메인 네임의 관리 권한을 가지는 Authoritative 네임 서버로 도달하는 전체 DNS 질의 경로를 확인할 수 있습니다.

주로 DNS 설정에 문제가 있을 때 정확히 어디에서 문제가 발생하고 있는지 파악하기 위해서 사용합니다.

$ dig daleseo.com +trace

; <<>> DiG 9.10.6 <<>> daleseo.com +trace
;; global options: +cmd
.			487326	IN	NS	e.root-servers.net.
.			487326	IN	NS	k.root-servers.net.
.			487326	IN	NS	j.root-servers.net.
.			487326	IN	NS	m.root-servers.net.
.			487326	IN	NS	d.root-servers.net.
.			487326	IN	NS	f.root-servers.net.
.			487326	IN	NS	g.root-servers.net.
.			487326	IN	NS	i.root-servers.net.
.			487326	IN	NS	l.root-servers.net.
.			487326	IN	NS	c.root-servers.net.
.			487326	IN	NS	a.root-servers.net.
.			487326	IN	NS	b.root-servers.net.
.			487326	IN	NS	h.root-servers.net.
;; Received 239 bytes from 66.207.192.6#53(66.207.192.6) in 14 ms

com.			172800	IN	NS	a.gtld-servers.net.
com.			172800	IN	NS	b.gtld-servers.net.
com.			172800	IN	NS	c.gtld-servers.net.
com.			172800	IN	NS	d.gtld-servers.net.
com.			172800	IN	NS	e.gtld-servers.net.
com.			172800	IN	NS	f.gtld-servers.net.
com.			172800	IN	NS	g.gtld-servers.net.
com.			172800	IN	NS	h.gtld-servers.net.
com.			172800	IN	NS	i.gtld-servers.net.
com.			172800	IN	NS	j.gtld-servers.net.
com.			172800	IN	NS	k.gtld-servers.net.
com.			172800	IN	NS	l.gtld-servers.net.
com.			172800	IN	NS	m.gtld-servers.net.
com.			86400	IN	DS	30909 8 2 E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CF C41A5766
com.			86400	IN	RRSIG	DS 8 1 86400 20231001210000 20230918200000 11019 . s566mxq51sSYoj42bvCcn7cZLgX1WVv/1gqRFs63kXjV/yRVe3J76UcH 4WpNCaX6QfuKxLsUlJnKFDA0qAm8pD79oBadFEZBfgz4EL74iTQGZPcQ +Nq7a5LTH6p1I+X3U50no9R/Dj9z9wIav6Clk9zBHkGcPKROLJr4PulV jKJrK7SVZ4dVRq2MAuKcSPuUXLdKMh1lxR5jJHB5gtqZ5tDol8rs4BWF 0kFXqAg6NI7gdNfXdyPAtuJFWMwoRA9OhGvgT0E9FT7XTiYvG0NNVht/ b6zuR2OmXUnVwL5UH8foeMnh1Wa4XT90HgOiz10tgLomBYfIdgAdTUQ8 qlvB0Q==
;; Received 1171 bytes from 193.0.14.129#53(k.root-servers.net) in 14 ms

daleseo.com.		172800	IN	NS	maceio.ns.porkbun.com.
daleseo.com.		172800	IN	NS	salvador.ns.porkbun.com.
daleseo.com.		172800	IN	NS	fortaleza.ns.porkbun.com.
daleseo.com.		172800	IN	NS	curitiba.ns.porkbun.com.
CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - CK0Q2D6NI4I7EQH8NA30NS61O48UL8G5  NS SOA RRSIG DNSKEY NSEC3PARAM
CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20230923042441 20230916031441 4459 com. nlPnzJAnmCNotqaroLGR82BZ9mdG/qhx83hmzVTy7SqloBzZLwnZAUTn c7wRYZUH5TS1R1ElhQP8BpXYYgm/8/THSAK5SgfKwYEwYE+k+BqyDst6 V5nZx3+p8Jo/uKYU6lmlaOAPPGVA/jg7P3Q9qF9eaoo3aw5EYLyIhePB AuLZD+zmd53Iqsl89Mpav5pQq05pcoOFtIYZCNrekDU4Xw==
PDCMR6ANT0M45I8GNIFBJHQQG23D92QK.com. 86400 IN NSEC3 1 1 0 - PDCNAVKJ2PQTH27NDC7TV68USRTQSQE0  NS DS RRSIG
PDCMR6ANT0M45I8GNIFBJHQQG23D92QK.com. 86400 IN RRSIG NSEC3 8 2 86400 20230923063135 20230916052135 4459 com. Ztpn50X8i6UYbldylG0PM66IrMlA0Q0xni+asMa63zYfj4CooTGkXx9T CTn+H+WkLt0X+3tQ8Hva38O4V9phyZTiD9aOnp9VQXdolnQ8veg4+QCj WUmen6w3NrGcoqPtCQj1EGvpa5jZig4oAFBxYyBU2T3z/M8x16dhJKfq 1auKr6MqgbCfl9CNMszcBui9SaCpwi1/86x8HgZakwKKGA==
;; Received 867 bytes from 192.43.172.30#53(i.gtld-servers.net) in 24 ms

daleseo.com.		600	IN	A	185.199.109.153
daleseo.com.		600	IN	A	185.199.108.153
daleseo.com.		600	IN	A	185.199.110.153
daleseo.com.		600	IN	A	185.199.111.153
;; Received 104 bytes from 173.245.58.37#53(curitiba.ns.porkbun.com) in 7 ms

응답 부분만 출력

세부 사항은 제외하고 도메인 네임에 대한 최종 DNS 레코드만 확인하고 싶다면 +no[항목] 옵션을 사용하면 됩니다.

예를 들어, 질의 내용과 레코드 유형을 포함한 조회 결과만 출력해보겠습니다.

dig daleseo.com +nostats +nocomments +nocmd

; <<>> DiG 9.10.6 <<>> daleseo.com +nostats +nocomments +nocmd
;; global options: +cmd
;daleseo.com.			IN	A
daleseo.com.		464	IN	A	185.199.111.153
daleseo.com.		464	IN	A	185.199.110.153
daleseo.com.		464	IN	A	185.199.108.153
daleseo.com.		464	IN	A	185.199.109.153

+short 옵션을 사용하시면 최소한의 결과만 출력됩니다.

$ dig daleseo.com +short
185.199.108.153
185.199.109.153
185.199.111.153
185.199.110.153

마치면서

지금까지 dig 명령어를 사용하여 DNS 레코드를 조회하는 다양한 방법에 대해서 살펴보았습니다. 본 포스팅에서 다루지 않은 옵션에 대해서는 dig 명령어를 -h 옵션과 함께 실행한 결과를 참고 바랍니다.

$ dig -h
Usage:  dig [@global-server] [domain] [q-type] [q-class] {q-opt}
            {global-d-opt} host [@local-server] {local-d-opt}
            [ host [@local-server] {local-d-opt} [...]]
Where:  domain	  is in the Domain Name System
        q-class  is one of (in,hs,ch,...) [default: in]
        q-type   is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]
                 (Use ixfr=version for type ixfr)
        q-opt    is one of:
                 -4                  (use IPv4 query transport only)
                 -6                  (use IPv6 query transport only)
                 -b address[#port]   (bind to source address/port)
                 -c class            (specify query class)
                 -f filename         (batch mode)
                 -i                  (use IP6.INT for IPv6 reverse lookups)
                 -k keyfile          (specify tsig key file)
                 -m                  (enable memory usage debugging)
                 -p port             (specify port number)
                 -q name             (specify query name)
                 -t type             (specify query type)
                 -u                  (display times in usec instead of msec)
                 -x dot-notation     (shortcut for reverse lookups)
                 -y [hmac:]name:key  (specify named base64 tsig key)
        d-opt    is of the form +keyword[=value], where keyword is:
                 +[no]aaonly         (Set AA flag in query (+[no]aaflag))
                 +[no]additional     (Control display of additional section)
                 +[no]adflag         (Set AD flag in query (default on))
                 +[no]all            (Set or clear all display flags)
                 +[no]answer         (Control display of answer section)
                 +[no]authority      (Control display of authority section)
                 +[no]besteffort     (Try to parse even illegal messages)
                 +bufsize=###        (Set EDNS0 Max UDP packet size)
                 +[no]cdflag         (Set checking disabled flag in query)
                 +[no]cl             (Control display of class in records)
                 +[no]cmd            (Control display of command line)
                 +[no]comments       (Control display of comment lines)
                 +[no]crypto         (Control display of cryptographic fields in records)
                 +[no]defname        (Use search list (+[no]search))
                 +[no]dnssec         (Request DNSSEC records)
                 +domain=###         (Set default domainname)
                 +[no]edns[=###]     (Set EDNS version) [0]
                 +ednsflags=###      (Set EDNS flag bits)
                 +[no]ednsnegotiation (Set EDNS version negotiation)
                 +ednsopt=###[:value] (Send specified EDNS option)
                 +noednsopt          (Clear list of +ednsopt options)
                 +[no]expire         (Request time to expire)
                 +[no]fail           (Don't try next server on SERVFAIL)
                 +[no]identify       (ID responders in short answers)
                 +[no]idnout         (convert IDN response)
                 +[no]ignore         (Don't revert to TCP for TC responses.)
                 +[no]keepopen       (Keep the TCP socket open between queries)
                 +[no]multiline      (Print records in an expanded format)
                 +ndots=###          (Set search NDOTS value)
                 +[no]nsid           (Request Name Server ID)
                 +[no]nssearch       (Search all authoritative nameservers)
                 +[no]onesoa         (AXFR prints only one soa record)
                 +[no]opcode=###     (Set the opcode of the request)
                 +[no]qr             (Print question before sending)
                 +[no]question       (Control display of question section)
                 +[no]recurse        (Recursive mode)
                 +retry=###          (Set number of UDP retries) [2]
                 +[no]rrcomments     (Control display of per-record comments)
                 +[no]search         (Set whether to use searchlist)
                 +[no]short          (Display nothing except short
                                      form of answer)
                 +[no]showsearch     (Search with intermediate results)
                 +[no]split=##       (Split hex/base64 fields into chunks)
                 +[no]stats          (Control display of statistics)
                 +subnet=addr        (Set edns-client-subnet option)
                 +[no]tcp            (TCP mode (+[no]vc))
                 +time=###           (Set query timeout) [5]
                 +[no]trace          (Trace delegation down from root [+dnssec])
                 +tries=###          (Set number of UDP attempts) [3]
                 +[no]ttlid          (Control display of ttls in records)
                 +[no]vc             (TCP mode (+[no]tcp))
        global d-opts and servers (before host name) affect all queries.
        local d-opts and servers (after host name) affect only that lookup.
        -h                           (print help and exit)
        -v                           (print version and exit)