
빠른 DNS 조회 라이브러리 및 CLI 도구
ZDNS는 고속 DNS 리졸버이자 대규모 DNS 측정을 수행하기 위한 명령줄 유틸리티입니다. ZDNS는 Go로 작성되었으며, 자체 재귀적 해석 코드와 다양한 이름 집합의 조회를 최적화하는 캐시를 포함하고 있습니다. 원시 DNS 패킷을 구성하고 파싱하기 위해 https://github.com/zmap/dns를 사용합니다. ZDNS의 아키텍처와 성능에 대한 자세한 내용은 ACM Internet Measurement Conference '22에 발표된 다음 논문을 참조하세요.
[!TIP] ZDNS 위키에는 ZDNS에 대한 추가 정보와 사용 사례 및 예제가 포함되어 있습니다.
ZDNS는 저장소를 클론하고 make install을 실행하여 설치할 수 있습니다.
git clone https://github.com/zmap/zdns.git
cd zdns
make install
ZDNS는 재귀적 리졸버 라이브러리와 CLI 래퍼로 구성됩니다.
라이브러리는 모든 조회에 대한 모든 설정 옵션을 포함하는 ResolverConfig 구조체로 구성됩니다. ResolverConfig는 모든 조회를 수행할 1개 이상의 Resolver 구조체를 생성하는 데 사용됩니다. Resolver는 한 번에 하나의 조회만 수행해야 하며(스레드 안전하지 않음), 병렬 처리를 위해 여러 Resolver 구조체를 사용해야 합니다. 라이브러리 사용 방법은 examples를 참조하세요. Modules는 조회의 동작을 정의하는 데 사용됩니다.
ZDNS는 여러 유형의 모듈을 제공합니다:
Raw DNS 모듈: dig와 유사하게 서버로부터의 원시 DNS 응답을 JSON 형태로 제공합니다. 거의 모든 DNS 레코드 유형에 대한 모듈이 있습니다.
조회 모듈: 여러 쿼리가 필요한 경우 더 유용한 응답을 제공합니다(예: NSLOOKUP에서 NS를 받은 경우 IP 주소에 대한 추가 A 조회 완료).
기타 모듈: 서버를 쿼리하는 다른 추가 수단을 제공합니다(예: bind.version).
아래에 모듈을 자세히 설명합니다:
A, AAAA, AFSDB, ANY, ATMA, AVC, AXFR, BINDVERSION, CAA, CDNSKEY, CDS, CERT, CNAME, CSYNC, DHCID, DMARC, DNSKEY, DS, EID, EUI48, EUI64, GID, GPOS, HINFO, HIP, HTTPS, ISDN, KEY, KX, L32, L64, LOC, LP, MB, MD, MF, MG, MR, MX, NAPTR, NID, NINFO, NS, NSAPPTR, NSEC, NSEC3, NSEC3PARAM, NSLOOKUP, NULL, NXT, OPENPGPKEY, PTR, PX, RP, RRSIG, RT, SVCBS, MIMEA, SOA, SPF, SRV, SSHFP, TALINK, TKEY, TLSA, TXT, UID, UINFO, UNSPEC, URI 모듈은 dig와 유사하게 JSON 형태의 원시 DNS 응답을 제공합니다.
예를 들어, 명령:
echo "censys.io" | zdns A
다음을 반환합니다:
{
"name": "censys.io",
"results": {
"A": {
"data": {
"additionals": [
{
"flags": "",
"type": "EDNS0",
"udpsize": 512,
"version": 0
}
],
"answers": [
{
"answer": "104.18.10.85",
"class": "IN",
"name": "censys.io",
"ttl": 300,
"type": "A"
},
{
"answer": "104.18.11.85",
"class": "IN",
"name": "censys.io",
"ttl": 300,
"type": "A"
}
],
"protocol": "udp",
"resolver": "[2603:6013:9d00:3302::1]:53"
},
"duration": 0.285295416,
"status": "NOERROR",
"timestamp": "2024-08-23T13:12:43-04:00"
}
}
}
원시 DNS 응답은 종종 사용자가 원하는 데이터를 제공하지 않습니다. 예를 들어, MX 응답에 연결된 A 레코드가 추가 섹션에 포함되지 않아 추가 조회가 필요할 수 있습니다. 이러한 문제를 해결하고 더 친숙한 인터페이스를 제공하기 위해 몇 가지 조회 모듈도 제공합니다: alookup, mxlookup, nslookup.
alookup은 nslookup과 유사하게 작동하며 CNAME 레코드를 따라갑니다.
mxlookup은 교환 레코드에 해당하는 IP 주소에 대해 추가로 A 조회를 수행합니다.
nslookup은 NS 레코드에 해당하는 IP 주소에 대해 추가로 A/AAAA 조회를 수행합니다.
예를 들어,
echo "censys.io" | zdns mxlookup --ipv4-lookup
다음을 반환합니다:
{
"name": "censys.io",
"results": {
"MXLOOKUP": {
"data": {
"exchanges": [
{
"class": "IN",
"ipv4_addresses": [
"209.85.202.27"
],
"name": "alt1.aspmx.l.google.com",
"preference": 5,
"ttl": 300,
"type": "MX"
},
{
"class": "IN",
"ipv4_addresses": [
"142.250.31.26"
],
"name": "aspmx.l.google.com",
"preference": 1,
"ttl": 300,
"type": "MX"
}
]
},
"duration": 0.154786958,
"status": "NOERROR",
"timestamp": "2024-08-23T13:10:11-04:00"
}
}
}
ZDNS는 특수 "디버그" DNS 쿼리도 지원합니다. 모듈에는 BINDVERSION이 포함됩니다.
ZDNS는 원하는 동작에 따라 다양한 형식의 입력을 지원합니다.
가장 기본적인 입력은 개행으로 구분된 이름 목록입니다. 예를 들어:
표준 입력에서:
echo "google.com\nyahoo.com" | zdns A
cat list_of_domains.txt | zdns A
파일에서
zdns A --input-file=list_of_domains.txt
도메인을 많이 해석할 필요가 없다면, dig와 마찬가지로 편의를 위해 CLI 인수로 도메인을 제공할 수 있습니다.
예를 들어:
zdns A google.com --name-servers=1.1.1.1
dig -t A google.com @1.1.1.1과 동일
일반적으로 ZDNS는 --name-servers에서 각 도메인 조회에 대해 무작위 네임서버를 선택합니다. 대신 도메인마다 다른 네임서버를 지정하려면 개행으로 구분된 domainName,nameServerIP 쌍을 제공하면 됩니다. 이렇게 하면 --name-servers로 제공된 모든 네임서버가 재정의됩니다.
예를 들어:
echo "google.com,1.1.1.1\nfacebook.com,8.8.8.8" | zdns A
출력에서 각 도메인에 대해 지정된 resolver를 확인할 수 있습니다(간결함을 위해 additionals/answers는 생략):
$ echo "google.com,1.1.1.1\nfacebook.com,8.8.8.8" | zdns A
{"name":"google.com","results":{"A":{"data":{"additionals":...,"answers":[...],"protocol":"udp","resolver":"1.1.1.1:53"},"duration":0.030490042,"status":"NOERROR","timestamp":"2024-09-13T09:51:34-04:00"}}}
{"name":"facebook.com","results":{"A":{"data":{"additionals":[...],"answers":[...],"protocol":"udp","resolver":"8.8.8.8:53"},"duration":0.061365459,"status":"NOERROR","timestamp":"2024-09-13T09:51:34-04:00"}}}
Zone 파일(ICANN CZDS 등에서 가져온)은 --zone-file 플래그와 함께 ZDNS의 입력 소스로 사용할 수 있습니다. 이렇게 하면 표준 입력(기본값) 또는 --input-file 플래그를 사용한 파일에서 zone 파일을 파싱할 수 있습니다.
기본적으로 ZDNS는 각 zone 파일 레코드에서 이름만 추출합니다. CNAME 또는 NS 레코드와 같은 레코드 유형의 응답 섹션에서 참조된 이름도 해석하려면 --zone-file-include-targets CLI 플래그를 사용할 수 있습니다.
예를 들어, --zone-file-include-targets와 이 DNS zone 파일 항목이 있는 경우:
example.com. 3600 IN NS ns1.example.com
example.com과 ns1.example.com이 모두 해석됩니다.
ZDNS는 입력 라인을 특정 모듈에 매핑하는 "트리거"를 입력 라인별로 전달하는 기능도 지원합니다. 이를 통해 특정 도메인이 특정 모듈로 조회되도록 지정할 수 있습니다.
입력 형식은 다음과 같습니다:
domain_name,name_server,trigger,trigger_2,etc 여기서 nameServer는 기본 네임서버를 사용하려면 비워둘 수 있으며, 1개 이상의 트리거를 지정할 수 있습니다.
예제 input.csv 파일:
example.com,,a-trigger
google.com,,a-trigger,cname-trigger
example.com,1.1.1.1,aaaa-trigger
yahoo.com
apnews.com,1.1.1.1
그리고 해당 multiple.ini 파일:
; 전역 옵션을 여기에 지정
[Application Options]
iterative=true
prefer-ipv6-iteration="true"
; 모듈 및 해당 모듈별 옵션을 여기에 나열합니다. 모듈은 한 번만 나열될 수 있습니다.
[A]
trigger = "a-trigger"
[AAAA]
trigger = "aaaa-trigger"
[CNAME]
trigger = "cname-trigger"
이렇게 하면 다음과 같이 조회됩니다:
example.com을 기본 네임서버를 사용하여 A 모듈로 조회google.com을 기본 네임서버를 사용하여 A + CNAME 모듈로 조회example.com을 Cloudflare의 1.1.1.1 리졸버를 사용하여 AAAA 모듈로 조회yahoo.com을 기본 네임서버를 사용하여 지정된 모든 모듈로 조회apnews.com을 Cloudflare의 1.1.1.1 리졸버를 사용하여 지정된 모든 모듈로 조회명령 실행:
zdns MULTIPLE --multi-config-file="./multiple.ini" --input-file="input.csv"
ZDNS는 재귀적 리졸버(예: 조직 DNS 서버)를 대상으로 작동하거나(기본 동작) 자체적으로 재귀를 수행할 수 있습니다. 소량(수백만 개)의 조회를 수행하고 10,000개 미만의 Go 루틴을 사용하는 경우 일반적으로 Cloudflare 또는 Google과 같은 일반적인 재귀적 리졸버를 사용하는 것이 가장 빠릅니다. Cloudflare는 거의 항상 Google보다 빠릅니다. 특히 인기 있는 이름을 조회하는 경우 캐시되어 단일 왕복으로 응답할 수 있기 때문입니다. 수만 개의 동시 스레드를 사용하는 경우 재귀적 리졸버에 DOS를 가하거나 속도 제한에 걸리지 않도록 내부적으로 반복을 수행하는 것이 좋습니다.
로컬 재귀를 수행하려면 --iterative 플래그와 함께 zdns를 실행하세요. 이 플래그를 사용하면 ZDNS는 게시된 루트 서버(예: 198.41.0.4) 사이를 라운드 로빈 방식으로 순회합니다. 반복 모드에서는 --cache-size를 지정하여 로컬 캐시의 크기를 제어하고, --iteration-timeout을 설정하여 개별 반복의 타임아웃을 제어할 수 있습니다. --timeout 플래그는 주어진 입력에 대한 전체 해석의 타임아웃(즉, 모든 반복 단계의 합)을 제어합니다.