CI / test (pull_request) Failing after 1m19s
- README.md: full project overview, installation, quick start, CLI reference, output format descriptions, architecture overview, and dnstraverse comparison - GoDoc: package-level documentation for traverse, dns, config, output, and fingerprint packages - GoDoc: TraverserConfig and TraversalResult type comments in traverser.go Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: multica-agent <github@multica.ai>
247 lines
8.4 KiB
Markdown
247 lines
8.4 KiB
Markdown
# ExploreDNS
|
||
|
||
ExploreDNS is a comprehensive DNS traversal tool that explores every possible
|
||
resolution path for a domain — from the root servers all the way down — just
|
||
like a real iterative resolver, but without stopping at the first answer. It
|
||
follows every referral exhaustively, collates all results, and presents them in
|
||
a structured, human-readable (or JSON) report.
|
||
|
||
Inspired by the classic [dnstraverse](https://github.com/squish/dnstraverse)
|
||
Ruby tool, ExploreDNS is a modern Go rewrite that produces a self-contained
|
||
binary with no runtime dependencies.
|
||
|
||
---
|
||
|
||
## Features
|
||
|
||
- **Full iterative traversal** — queries root servers and follows every referral
|
||
branch, mirroring real resolver behaviour
|
||
- **All root servers** — optionally query all 13 root server sets in parallel
|
||
- **No-glue resolution** — automatically resolves nameserver addresses when
|
||
referrals lack glue records
|
||
- **DNS server fingerprinting** — identifies server software via `version.bind`
|
||
CHAOS queries
|
||
- **Multiple output formats** — coloured text tree and machine-readable JSON
|
||
- **Configurable transport** — UDP/TCP, EDNS0 buffer size, retries, timeouts
|
||
- **Fast mode** — shares glue across branches for speed; disable for independent
|
||
paths
|
||
- **CNAME tracking** — follows CNAME chains and detects loops
|
||
|
||
---
|
||
|
||
## Installation
|
||
|
||
### Pre-built binary
|
||
|
||
Download the latest release binary for your platform from the
|
||
[Releases page](https://gitea.hansenits.com.au/hits/ExploreDNS/releases).
|
||
|
||
### Build from source
|
||
|
||
Requires Go 1.21 or later.
|
||
|
||
```sh
|
||
git clone https://gitea.hansenits.com.au/hits/ExploreDNS.git
|
||
cd ExploreDNS
|
||
make build # produces bin/exploredns
|
||
```
|
||
|
||
### go install
|
||
|
||
```sh
|
||
go install github.com/hits/ExploreDNS/cmd/exploredns@latest
|
||
```
|
||
|
||
---
|
||
|
||
## Quick Start
|
||
|
||
```sh
|
||
# Basic A record traversal
|
||
exploredns www.example.com
|
||
|
||
# MX records for a domain
|
||
exploredns --type MX example.com
|
||
|
||
# Use all 13 root server sets
|
||
exploredns --all-root-servers www.example.com
|
||
|
||
# JSON output
|
||
exploredns --json www.example.com
|
||
|
||
# Quiet (results only)
|
||
exploredns --quiet www.example.com
|
||
|
||
# Debug mode
|
||
exploredns --debug www.example.com
|
||
|
||
# Library-level debug (very verbose)
|
||
exploredns --dd www.example.com
|
||
|
||
# Force TCP
|
||
exploredns --allow-tcp --always-tcp www.example.com
|
||
|
||
# Disable fast mode (independent paths per branch)
|
||
exploredns --fast=false www.example.com
|
||
|
||
# Increase traversal depth limit
|
||
exploredns --max-depth 30 www.example.com
|
||
```
|
||
|
||
---
|
||
|
||
## CLI Reference
|
||
|
||
```
|
||
Usage:
|
||
exploredns [flags] <domain>
|
||
|
||
Query Options:
|
||
--type <TYPE> Record type to query (default: A)
|
||
Supported: A, AAAA, NS, CNAME, MX, TXT, SOA, PTR, ANY
|
||
--root-server <IP> Override the root server IP address
|
||
--all-root-servers Query all 13 root server sets (default: false)
|
||
--root-aaaa Include IPv6 addresses for root servers (default: false)
|
||
--follow-aaaa Only follow AAAA addresses for referrals (default: false)
|
||
|
||
Transport Options:
|
||
--udp-size <N> EDNS0 UDP buffer size, 512–4096 (default: 2048)
|
||
--allow-tcp Fall back to TCP on truncation (default: true)
|
||
--always-tcp Always use TCP (requires --allow-tcp)
|
||
--retries <N> Per-server retry count, 0–10 (default: 2)
|
||
|
||
Traversal Options:
|
||
--max-depth <N> Maximum referral depth, 1–100 (default: 20)
|
||
--fast / --fast=false Share glue cache across branches (default: true)
|
||
|
||
Output Options:
|
||
--json Emit results as JSON instead of text
|
||
--verbose, -v Show extra detail in text output
|
||
--debug, -d Enable application debug messages (stderr)
|
||
--dd Enable library-level debug messages (very verbose)
|
||
--quiet, -q Suppress header and supplementary information
|
||
--show-progress Show live traversal progress (default: true)
|
||
--no-show-progress Hide traversal progress
|
||
--show-resolves Show glue-resolution steps (default: true)
|
||
--no-show-resolves Hide glue-resolution steps
|
||
--show-servers Show which servers were queried (default: true)
|
||
--no-show-servers Hide server list
|
||
--show-versions Show DNS server software versions (default: true)
|
||
--no-show-versions Hide server versions
|
||
--show-all-stats Show query statistics (default: true)
|
||
--no-show-all-stats Hide statistics
|
||
--show-results Show per-branch query results (default: true)
|
||
--no-show-results Hide per-branch results
|
||
--show-summary-results Show deduplicated summary section (default: true)
|
||
--no-show-summary-results Hide summary section
|
||
```
|
||
|
||
---
|
||
|
||
## Output Formats
|
||
|
||
### Text (default)
|
||
|
||
Coloured, hierarchical tree output showing each traversal branch, the servers
|
||
queried, referrals followed, and final answers. Disable colour by setting the
|
||
`NO_COLOR` environment variable.
|
||
|
||
### JSON (`--json`)
|
||
|
||
Structured JSON array of traversal results. Suitable for piping into `jq` or
|
||
ingesting into other tools. Each element contains the referral metadata, the
|
||
responding server, the response type, and the decoded DNS records.
|
||
|
||
---
|
||
|
||
## Comparison with dnstraverse
|
||
|
||
| Feature | dnstraverse (Ruby) | ExploreDNS (Go) |
|
||
|---|---|---|
|
||
| Language | Ruby | Go |
|
||
| Self-contained binary | No | Yes |
|
||
| All root servers | Yes | Yes |
|
||
| No-glue resolution | Yes | Yes |
|
||
| JSON output | No | Yes |
|
||
| Server fingerprinting | Yes | Yes |
|
||
| CNAME loop detection | Partial | Yes |
|
||
| Active development | Dormant | Active |
|
||
|
||
---
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
cmd/exploredns/ CLI entry point and flag parsing
|
||
internal/config/ Configuration types, validation, and usage text
|
||
internal/dns/ DNS query layer, root discovery, transport
|
||
internal/traverse/ Core traversal engine, referral resolution, caching
|
||
internal/fingerprint/ DNS server version fingerprinting (version.bind CHAOS)
|
||
internal/output/ Result formatting — text tree and JSON renderers
|
||
internal/integration/ End-to-end integration tests
|
||
```
|
||
|
||
---
|
||
|
||
## Development
|
||
|
||
```sh
|
||
make build # compile binary to bin/exploredns
|
||
make test # run all unit and integration tests
|
||
make lint # run go vet
|
||
make clean # remove build artefacts
|
||
```
|
||
|
||
Run a single package's tests:
|
||
|
||
```sh
|
||
go test ./internal/traverse/...
|
||
```
|
||
|
||
---
|
||
|
||
## Architecture Overview
|
||
|
||
```
|
||
main → config.Parse → traverse.NewTraverser → traverse.Traverse
|
||
│
|
||
┌─────────▼──────────┐
|
||
│ Stack (BFS/DFS) │
|
||
│ Referral queue │
|
||
└─────────┬──────────┘
|
||
│ per referral
|
||
┌─────────▼──────────┐
|
||
│ processReferral │
|
||
│ ├─ resolveGlue │ (no-glue NS resolution)
|
||
│ └─ queryServer │ (dns.Query)
|
||
└─────────┬──────────┘
|
||
│
|
||
┌─────────────▼──────────────┐
|
||
│ Response classifier │
|
||
│ Answer / Referral / │
|
||
│ CNAME / NXDOMAIN / │
|
||
│ SERVFAIL / Error │
|
||
└─────────────┬──────────────┘
|
||
│
|
||
┌─────────▼──────────┐
|
||
│ output.Formatter │
|
||
│ (text | JSON) │
|
||
└────────────────────┘
|
||
```
|
||
|
||
The traversal engine (`internal/traverse`) maintains a work stack of
|
||
`Referral` objects. Each referral represents a single query to a single set
|
||
of nameservers. When a response contains further referrals, child `Referral`
|
||
objects are pushed onto the stack and processed in turn.
|
||
|
||
The `InfoCache` is used to store glue records discovered during traversal. In
|
||
fast mode (default), a single root cache is shared across all branches so that
|
||
glue discovered early is reused. In non-fast mode, each branch gets its own
|
||
independent cache.
|
||
|
||
---
|
||
|
||
## License
|
||
|
||
MIT — see [LICENSE](LICENSE).
|