
DNS 측정, 문제 해결 및 보안 감사 도구 세트
[](https://pypi.python.org/pypi/dnsdiag/) []() [](https://pepy.tech/project/dnsdiag) [](https://pepy.tech/project/dnsdiag) []() [](https://hub.docker.com/r/farrokhi/dnsdiag) [](https://github.com/farrokhi/dnsdiag/stargazers)
DNS 측정, 문제 해결 및 보안 감사 도구 모음
===============================================================
ISP가 [DNS 트래픽을 가로채고 있는지](https://medium.com/decentralize-today/is-your-isp-hijacking-your-dns-traffic-f3eb7ccb0ee7) 궁금한 적이 있으신가요?
DNS 응답에서 이상한 동작을 발견하거나 잘못된 주소로 리디렉션되어 DNS에 문제가 있다고 의심한 적이 있으신가요? 우리는 DNS 요청과 응답에 대한 기본 감사를 수행하여 DNS가 예상대로 작동하는지 확인할 수 있도록 도와주는 도구 모음을 제공합니다.
`dnsping`을 사용하면 임의의 쿼리에 대해 모든 DNS 서버의 응답 시간을 측정할 수 있습니다. 일반 ping 유틸리티와 유사하게, dnsping은 DNS 요청에 대해 비슷한 기능을 제공하여 서버 응답성을 모니터링할 수 있도록 도와줍니다.
또한 `dnstraceroute`를 사용하여 DNS 요청이 목적지까지 가는 경로를 추적하여 리디렉션되거나 가로채지고 있지 않은지 확인할 수 있습니다. 동일한 서버로 전송된 DNS 쿼리를 비교함으로써, `dnstraceroute`는 경로상의 차이를 관찰할 수 있게 하여 잠재적인 문제를 경고합니다.
`dnseval`은 여러 DNS 리졸버를 평가하여 네트워크에 가장 적합한 DNS 리졸버를 선택할 수 있도록 도와줍니다. 타사 DNS 리졸버에 의존하지 않으려면 자체 DNS 리졸버를 사용하는 것이 권장되지만, 필요할 때 `dnseval`은 최적의 DNS 리졸버를 선택하는 데 도움을 줄 수 있습니다. 성능(지연 시간)과 신뢰성(패킷 손실)을 기준으로 DNS 서버를 비교할 수 있어 정보에 기반한 의사 결정을 위한 포괄적인 뷰를 제공합니다.
# 설치
이 도구 모음을 사용하는 방법에는 여러 가지가 있지만, 최적의 유연성과 제어를 위해 소스 코드에서 직접 실행하는 것을 권장합니다. 소스에서 실행하거나 pip로 설치하려면 Python 3.11 이상이 필요합니다.
## 소스 코드
1. git 저장소를 체크아웃하고 종속성을 설치합니다:
```
git clone https://github.com/farrokhi/dnsdiag.git
cd dnsdiag
pip3 install -r requirements.txt
```
2. 또는 pip를 사용하여 패키지를 설치할 수 있습니다:
```
pip3 install dnsdiag
```
## uv 사용 (권장)
[uv](https://docs.astral.sh/uv/)는 설치 없이 도구를 직접 실행할 수 있는 빠른 Python 패키지 관리자입니다:
```bash
# 설치 없이 dnsping 직접 실행
uvx --from dnsdiag dnsping google.com
# 특정 옵션으로 실행
uvx --from dnsdiag dnsping -c 5 --tls -s 8.8.8.8 example.com
# dnstraceroute 실행
uvx --from dnsdiag dnstraceroute cloudflare.com
# dnseval 실행
uvx --from dnsdiag dnseval -f public-servers.txt github.com
```
dnsdiag를 영구적으로 설치하려면:
```bash
# dnsdiag 도구 설치
uv tool install dnsdiag
# 최신 버전으로 업그레이드
uv tool upgrade dnsdiag
```
## 바이너리 패키지
때때로 Windows, Mac OS X 및 Linux용 바이너리 패키지가 릴리스됩니다. 최신 릴리스는 [릴리스 페이지](https://github.com/farrokhi/dnsdiag/releases)에서 받을 수 있습니다.
### 지원 플랫폼
미리 빌드된 바이너리는 다음에서 사용할 수 있습니다:
- Linux (x86_64, ARM64)
- macOS (Intel, Apple Silicon)
- Windows (x86_64)
Windows ARM64는 현재 지원되지 않습니다. 이는 기본 컴파일 툴체인이 필요하지만 쉽게 사용할 수 없는 빌드 종속성 때문입니다. ARM에서 Windows를 사용하는 경우 WSL2(Windows Subsystem for Linux)를 통해 dnsdiag를 실행하거나 소스에서 직접 설치할 수 있습니다.
## Docker
로컬 머신에 `dnsdiag`를 설치하고 싶지 않다면, Docker 이미지를 사용하여 컨테이너화된 환경에서 도구를 실행할 수 있습니다. 예를 들어:
```
docker run --network host -it --rm farrokhi/dnsdiag dnsping.py
```
# dnsping
`dnsping`을 사용하면 임의의 DNS 쿼리를 여러 번 전송하여 DNS 리졸버를 "ping"할 수 있습니다. 지원되는 명령줄 옵션의 전체 목록은 `--help`를 사용하세요. 다음은 몇 가지 주요 플래그입니다:
- `--tcp`, `--tls`, `--doh`, `--quic` 또는 `--http3`를 사용하여 전송 프로토콜을 선택합니다 (기본값은 UDP). 이 옵션들은 상호 배타적이며, 명령당 하나의 프로토콜만 지정할 수 있습니다.
- `--flags`를 사용하여 각 응답에 대한 응답 플래그(EDNS 플래그 포함)를 표시합니다.
- `--dnssec`를 사용하여 사용 가능한 경우 DNSSEC 검증을 요청합니다.
- 확장 DNS 오류 메시지([RFC 8914](https://www.rfc-editor.org/rfc/rfc8914))는 존재할 경우 자동으로 표시됩니다.
- `--nsid`를 사용하여 사용 가능한 경우 NSID(Name Server Identifier)를 표시합니다 ([RFC 5001](https://www.rfc-editor.org/rfc/rfc5001)).
- `--ecs`를 사용하여 지리적 라우팅 최적화를 위한 EDNS Client Subnet 정보를 포함합니다.
- `--cookie`를 사용하여 응답에 존재할 경우 DNS 쿠키([RFC 7873](https://www.rfc-editor.org/rfc/rfc7873))를 표시합니다.
```shell
./dnsping.py -c 5 --dnssec --flags --tls -t AAAA -s 8.8.8.8 brokendnssec.net
```
```
dnsping.py DNS: 8.8.8.8:853, hostname: brokendnssec.net, proto: TLS, class: IN, type: AAAA, flags: [RD]
75 bytes from 8.8.8.8: seq=1 time=73.703 ms SERVFAIL [QR RD RA -- DO] [EDE:10("For brokendnssec.net/soa")]
75 bytes from 8.8.8.8: seq=2 time=69.523 ms SERVFAIL [QR RD RA -- DO] [EDE:10("For brokendnssec.net/soa")]
75 bytes from 8.8.8.8: seq=3 time=58.058 ms SERVFAIL [QR RD RA -- DO] [EDE:10("For brokendnssec.net/soa")]
75 bytes from 8.8.8.8: seq=4 time=54.235 ms SERVFAIL [QR RD RA -- DO] [EDE:10("For brokendnssec.net/soa")]
75 bytes from 8.8.8.8: seq=5 time=57.806 ms SERVFAIL [QR RD RA -- DO] [EDE:10("For brokendnssec.net/soa")]
--- 8.8.8.8 dnsping statistics ---
5 requests transmitted, 5 responses received, 0% lost
min=54.235 ms, avg=22.665 ms, max=69.523 ms, stddev=38.202 ms
```
`dnsping`은 최소, 최대, 평균 응답 시간과 함께 지터(표준 편차) 및 패킷 손실과 같은 통계도 제공합니다.
다음은 `dnsping`의 몇 가지 흥미로운 사용 사례입니다:
- 다양한 전송 프로토콜(예: UDP vs. DoH) 간의 응답 시간 비교.
- 지터와 패킷 손실을 측정하여 DNS 서버의 신뢰성 평가.
- `--dnssec` 플래그를 사용하여 DNSSEC가 활성화된 상태에서 응답 시간 측정.
- 지리적 위치 인식 응답을 위한 EDNS Client Subnet 동작 테스트:
```shell
./dnsping.py -c 3 --ecs 203.0.113.0/24 -s 94.140.14.14 google.com
```
```
dnsping.py DNS: 94.140.14.14:53, hostname: google.com, proto: UDP, class: IN, type: A, flags: [RD]
66 bytes from 94.140.14.14: seq=1 time=31.407 ms NOERROR [ECS:203.0.113.0/24/24]
66 bytes from 94.140.14.14: seq=2 time=29.156 ms NOERROR [ECS:203.0.113.0/24/24]
66 bytes from 94.140.14.14: seq=3 time=30.892 ms NOERROR [ECS:203.0.113.0/24/24]
--- 94.140.14.14 dnsping statistics ---
3 requests transmitted, 3 responses received, 0% lost
min=29.156 ms, avg=30.485 ms, max=31.407 ms, stddev=1.176 ms
```
- NSID 옵션을 사용하여 DNS 서버 식별:
```shell
./dnsping.py -c 2 --nsid -s 8.8.8.8 google.com
```
```
dnsping.py DNS: 8.8.8.8:53, hostname: google.com, proto: UDP, class: IN, type: A, flags: [RD]
68 bytes from 8.8.8.8: seq=1 time=36.399 ms NOERROR [NSID:gpdns-ams]
68 bytes from 8.8.8.8: seq=2 time=32.156 ms NOERROR [NSID:gpdns-ams]
--- 8.8.8.8 dnsping statistics ---
2 requests transmitted, 2 responses received, 0% lost
min=32.156 ms, avg=34.278 ms, max=36.399 ms, stddev=2.122 ms
```
- 향상된 보안 및 캐시 최적화를 위한 DNS 쿠키 테스트:
```shell
./dnsping.py -c 2 --cookie -s anyns.pch.net quad9.net
```
```
dnsping.py DNS: anyns.pch.net:53, hostname: quad9.net, proto: UDP, class: IN, type: A, flags: [RD]
82 bytes from anyns.pch.net: seq=1 time=30.552 ms NOERROR [COOKIE:27f609c017bb2ec4ea70de5c68eec3fc39f6a53ee49c55f8]
82 bytes from anyns.pch.net: seq=2 time=24.794 ms NOERROR [COOKIE:719631dd9fcce722d3ac859b68eec3fd2e5430b5c8a7f8cf]
--- anyns.pch.net dnsping statistics ---
2 requests transmitted, 2 responses received, 0% lost
min=24.794 ms, avg=27.673 ms, max=30.552 ms, stddev=4.072 ms
```
## DNSSEC 및 보안 관련 플래그 해석
`--dnssec`와 `--flags`를 사용할 때, `dnsping`은 DNS 보안 검증과 직접적으로 관련된 DNS 프로토콜 필드를 노출합니다. 이 값들은 리졸버가 DNSSEC를 검증할 수 있는지, 그리고 응답이 성공적으로 검증되었는지를 나타냅니다.
일반적인 플래그:
- **DO (DNSSEC OK)**
클라이언트가 DNSSEC 관련 레코드를 요청하고 있음을 나타냅니다. 이 플래그의 존재는 리졸버가 DNSSEC 쿼리를 지원함을 보여줍니다.
- **AD (Authenticated Data)**
응답이 DNSSEC를 사용하여 암호학적으로 검증되었을 때 검증 리졸버에 의해 설정됩니다. 이는 DNSSEC 검증이 활성화되어 있고 성공적이라는 강력한 신호입니다.
일반적인 패턴:
| 결과 | 의미 |
|-------|--------|
| `AD` 플래그가 있는 `NOERROR` | DNSSEC 검증 성공 |
| `DO` 플래그가 있는 `SERVFAIL` | DNSSEC 검증 실패 (종종 서명 손상 또는 잘못된 구성으로 인해) |
| `AD` 플래그 없음 | 리졸버가 DNSSEC 검증을 수행하지 않음 |
확장 DNS 오류(EDE, RFC 8914)는 DNSSEC 검증이 실패할 때 추가적인 진단 정보를 제공합니다. 예를 들어:
- **EDE:10** – *DNSSEC Bogus* (유효하지 않거나 손상된 DNSSEC 데이터)
- **EDE:6** – *DNSSEC Signature Expired*
- **EDE:7** – *DNSSEC Signature Not Yet Valid*
이러한 지표들은 `dnsping`을 성능 테스트뿐만 아니라 리졸버가 DNSSEC를 올바르게 적용하는지 검증하고 DNSSEC 배포 문제를 진단하는 데 유용하게 만듭니다.
# dnstraceroute
`dnstraceroute`는 DNS 요청이 목적지까지 가는 경로를 추적하는 유틸리티입니다. 실제 네트워크 traceroute와 비교하여 DNS 트래픽이 원치 않는 경로로 라우팅되지 않는지 확인할 수 있습니다.
`dnstraceroute`는 여러 전송 프로토콜을 지원합니다 (상호 배타적):
- UDP (기본값) - 전통적인 DNS 쿼리
- TCP (`--tcp`) - DNS over TCP
- DoQ (`--quic`) - DNS over QUIC (AdGuard DNS에서 지원)
- DoH3 (`--http3`) - DNS over HTTP/3 (Google DNS 및 Cloudflare에서 지원)
```shell
./dnstraceroute.py --expert --asn -C -t A -s 8.8.4.4 facebook.com
```
최신 DNS 프로토콜도 테스트할 수 있습니다:
```shell
# AdGuard DNS로 DNS over QUIC 테스트
./dnstraceroute.py --quic -s 94.140.14.14 -c 3 google.com
# Google DNS로 DNS over HTTP/3 테스트
./dnstraceroute.py --http3 -s 8.8.8.8 -c 3 google.com
```
```
dnstraceroute.py DNS: 8.8.4.4:53, hostname: facebook.com, rdatatype: A
1 192.168.0.1 (192.168.0.1) 1 ms
2 192.168.28.177 (192.168.28.177) 4 ms
3 192.168.0.1 (192.168.0.1) 693 ms
4 172.19.4.17 (172.19.4.17) 3 ms
5 dns.google (8.8.4.4) [AS15169 GOOGLE, US] 8 ms
=== Expert Hints ===
[*] public DNS server is next to a private IP address (possible hijacking)
```
`dnstraceroute`와 함께 `--expert` 플래그를 사용하면 잠재적인 DNS 트래픽 하이재킹에 대한 경고를 포함한 전문가 힌트를 표시할 수 있습니다.
# dnseval
`dnseval`은 지정된 DNS 서버 목록에 임의의 DNS 쿼리를 전송하여 응답 시간을 동시에 비교할 수 있는 대량 ping 유틸리티입니다.
`dnseval`을 사용하여 UDP(기본값), TCP, DoT(DNS over TLS), DoH(DNS over HTTPS), DoQ(DNS over QUIC), DoH3(DNS over HTTP/3) 등 다양한 전송 프로토콜의 응답 시간을 각각 `--tcp`, `--tls`, `--doh`, `--quic`, `--http3` 플래그를 사용하여 평가할 수 있습니다. 이러한 프로토콜 옵션은 상호 배타적이며, 명령당 하나만 지정할 수 있습니다.
## 프로토콜 지원 요약
| 도구 | UDP | TCP | TLS (DoT) | DoH | DoQ | DoH3 |
|------|-----|-----|-----------|-----|-----|------|
| `dnsping` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| `dnstraceroute` | ✓ | ✓ | - | - | ✓ | ✓ |
| `dnseval` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
*DoQ: DNS over QUIC, DoH3: DNS over HTTP/3*
```shell
./dnseval.py --skip-warmup --dnssec -c10 -f public-servers.txt ripe.net
```
```
server avg(ms) min(ms) max(ms) stddev(ms) lost(%) ttl flags response
---------------------------------------------------------------------------------------------------------------------
1.0.0.1 29.01 14.15 45.36 8.60 %0 300 QR -- -- RD RA AD -- DO NOERROR
1.1.1.1 23.90 18.14 42.07 7.83 %0 300 QR -- -- RD RA AD -- DO NOERROR
1.0.0.2 25.90 21.36 31.58 4.26 %0 300 QR -- -- RD RA AD -- DO NOERROR
1.1.1.2 22.68 18.36 32.15 3.96 %0 300 QR -- -- RD RA AD -- DO NOERROR
1.0.0.3 22.53 18.98 32.52 3.94 %0 300 QR -- -- RD RA AD -- DO NOERROR
1.1.1.3 21.70 20.25 22.97 0.77 %0 299 QR -- -- RD RA AD -- DO NOERROR
2606:4700:4700::1001 21.70 19.13 27.50 2.28 %0 299 QR -- -- RD RA AD -- DO NOERROR
2606:4700:4700::1111 22.63 20.42 30.18 3.13 %0 299 QR -- -- RD RA AD -- DO NOERROR
2606:4700:4700::1002 24.97 20.89 44.63 7.16 %0 299 QR -- -- RD RA AD -- DO NOERROR
2606:4700:4700::1112 23.24 21.37 25.87 1.48 %0 298 QR -- -- RD RA AD -- DO NOERROR
2606:4700:4700::1003 21.68 19.28 24.88 1.65 %0 298 QR -- -- RD RA AD -- DO NOERROR
2606:4700:4700::1113 22.61 19.86 26.09 1.73 %0 299 QR -- -- RD RA AD -- DO NOERROR
195.46.39.39 25.56 16.42 55.37 15.37 %0 300 QR -- -- RD RA -- -- -- NOERROR
195.46.39.40 19.08 16.51 23.86 2.24 %0 300 QR -- -- RD RA -- -- -- NOERROR
2a05:d014:939:3300::39 0.00 0.00 0.00 0.00 %100 N/A -- -- -- -- -- -- -- -- No Response
2a05:d014:939:3300::40 0.00 0.00 0.00 0.00 %100 N/A -- -- -- -- -- -- -- -- No Response
208.67.220.220 30.60 14.54 120.64 31.88 %0 300 QR -- -- RD RA AD -- DO NOERROR
208.67.222.222 21.78 17.42 36.45 6.06 %0 50 QR -- -- RD RA AD -- DO NOERROR
2620:0:ccc::2 29.48 19.23 98.29 24.22 %0 299 QR -- -- RD RA AD -- DO NOERROR
2620:0:ccd::2 22.36 17.90 30.18 3.98 %0 299 QR -- -- RD RA AD -- DO NOERROR
216.146.35.35 172.53 114.46 360.87 71.47 %0 299 QR -- -- RD RA AD -- DO NOERROR
216.146.36.36 187.36 118.21 324.32 59.08 %0 110 QR -- -- RD RA AD -- DO NOERROR
209.244.0.3 46.49 25.23 115.86 28.19 %0 300 QR -- -- RD RA -- -- DO NOERROR
209.244.0.4 58.33 28.09 109.18 29.20 %0 299 QR -- -- RD RA -- -- DO NOERROR
4.2.2.1 64.58 30.21 86.79 30.19 %25 299 QR -- -- RD RA -- -- DO NOERROR
4.2.2.2 40.54 22.69 74.80 20.76 %0 70 QR -- -- RD RA -- -- DO NOERROR
4.2.2.3 90.62 90.62 90.62 0.00 %50 70 QR -- -- RD RA -- -- DO NOERROR
4.2.2.4 31.53 23.80 70.93 14.51 %0 294 QR -- -- RD RA -- -- DO NOERROR
4.2.2.5 24.11 24.05 24.18 0.09 %33 294 QR -- -- RD RA -- -- DO NOERROR
80.80.80.80 0.00 0.00 0.00 0.00 %100 N/A -- -- -- -- -- -- -- -- No Response
80.80.81.81 0.00 0.00 0.00 0.00 %100 N/A -- -- -- -- -- -- -- -- No Response
8.8.4.4 28.35 20.85 39.14 7.24 %0 300 QR -- -- RD RA AD -- DO NOERROR
8.8.8.8 21.22 16.22 24.93 2.39 %0 299 QR -- -- RD RA AD -- DO NOERROR
```
추가 처리를 위해 결과를 JSONL 형식으로 저장할 수도 있습니다. 출력 파일의 각 줄은 하나의 DNS 서버에 대한 전체 측정 결과를 포함하는 유효한 JSON 객체입니다.
```shell
./dnseval.py -c 5 -j results.jsonl -f public-servers.txt example.com
```
출력은 `jq`와 같은 표준 JSON 도구로 줄 단위로 파싱할 수 있습니다.
```shell
cat results.jsonl | jq -r 'select(.data.r_lost_percent == 0) | .data.resolver'
```
### 작성자
Babak Farrokhi
- github: [github.com/farrokhi](https://github.com/farrokhi/)
- website: [farrokhi.net](https://farrokhi.net/)
- mastodon: [@[email protected]](https://unix.family/@farrokhi)
- twitter: [@farrokhi](https://twitter.com/farrokhi)
### 라이선스
dnsdiag는 2-clause BSD 라이선스로 배포됩니다.