Merge pull request 'docs: comprehensive documentation (HAN-387)' (#15) from feat/han-387-documentation into main
CI / test (push) Failing after 1m20s
CI / test (push) Failing after 1m20s
This commit was merged in pull request #15.
This commit is contained in:
@@ -1,44 +1,246 @@
|
|||||||
# ExploreDNS
|
# ExploreDNS
|
||||||
|
|
||||||
DNS reconnaissance and exploration tool.
|
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.
|
||||||
|
|
||||||
## Build
|
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
|
```sh
|
||||||
go build -o bin/exploredns ./cmd/exploredns
|
git clone https://gitea.hansenits.com.au/hits/ExploreDNS.git
|
||||||
|
cd ExploreDNS
|
||||||
|
make build # produces bin/exploredns
|
||||||
```
|
```
|
||||||
|
|
||||||
Or use the Makefile:
|
### go install
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make build
|
go install github.com/hits/ExploreDNS/cmd/exploredns@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
---
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./bin/exploredns <domain>
|
# 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
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development
|
---
|
||||||
|
|
||||||
|
## CLI Reference
|
||||||
|
|
||||||
```sh
|
|
||||||
make test # run tests
|
|
||||||
make lint # run go vet
|
|
||||||
make clean # remove build artifacts
|
|
||||||
```
|
```
|
||||||
|
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
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
cmd/exploredns/ CLI entry point
|
cmd/exploredns/ CLI entry point and flag parsing
|
||||||
internal/dns/ DNS query operations
|
internal/config/ Configuration types, validation, and usage text
|
||||||
internal/traverse/ DNS tree traversal
|
internal/dns/ DNS query layer, root discovery, transport
|
||||||
internal/fingerprint/ DNS server fingerprinting
|
internal/traverse/ Core traversal engine, referral resolution, caching
|
||||||
internal/output/ Result formatting and output
|
internal/fingerprint/ DNS server version fingerprinting (version.bind CHAOS)
|
||||||
internal/config/ Configuration management
|
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
|
## License
|
||||||
|
|
||||||
MIT
|
MIT — see [LICENSE](LICENSE).
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// Package config defines the configuration types and defaults for ExploreDNS,
|
||||||
|
// along with validation helpers and the CLI usage text.
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package dns provides the low-level DNS query primitives used by ExploreDNS.
|
||||||
|
//
|
||||||
|
// It wraps the github.com/miekg/dns library to provide retrying, TCP fallback,
|
||||||
|
// EDNS0 buffer size negotiation, and root server discovery. The package is
|
||||||
|
// intentionally narrow: it sends iterative (non-recursive) queries and returns
|
||||||
|
// the raw responses for the traversal engine to interpret.
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
|
// Package fingerprint identifies DNS server software by querying the
|
||||||
|
// version.bind name in the CHAOS class. Many authoritative and recursive DNS
|
||||||
|
// servers respond with a version string (e.g. "BIND 9.18.1-1") that can be
|
||||||
|
// used to identify the software and version in use.
|
||||||
|
//
|
||||||
|
// Queries are cached per server IP so that repeated lookups within a single
|
||||||
|
// traversal run do not incur extra network round-trips.
|
||||||
package fingerprint
|
package fingerprint
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
// Package output renders ExploreDNS traversal results for human consumption or
|
||||||
|
// machine processing.
|
||||||
|
//
|
||||||
|
// Two formats are supported:
|
||||||
|
//
|
||||||
|
// - FormatText — a coloured hierarchical tree (default)
|
||||||
|
// - FormatJSON — a JSON array of traversal results
|
||||||
|
//
|
||||||
|
// Create a Formatter via NewFormatter and call RunTraversal to drive the
|
||||||
|
// traversal engine and stream output incrementally.
|
||||||
package output
|
package output
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1 +1,27 @@
|
|||||||
|
// Package traverse implements the core DNS traversal engine for ExploreDNS.
|
||||||
|
//
|
||||||
|
// The traversal engine starts from the DNS root servers and iteratively
|
||||||
|
// follows every referral it receives, building a complete picture of the
|
||||||
|
// delegation path for a domain. Unlike a standard recursive resolver, which
|
||||||
|
// stops at the first authoritative answer, the traversal engine explores every
|
||||||
|
// branch so that delegation mismatches, lame delegations, or split authorities
|
||||||
|
// are all visible in the output.
|
||||||
|
//
|
||||||
|
// # Architecture
|
||||||
|
//
|
||||||
|
// A Traverser maintains a stack of Referral objects. Each Referral
|
||||||
|
// represents a pending query to a specific set of nameservers for a specific
|
||||||
|
// name and record type. The engine pops referrals one at a time, sends the
|
||||||
|
// query, classifies the response, and pushes any child referrals back onto the
|
||||||
|
// stack.
|
||||||
|
//
|
||||||
|
// When a referral contains nameserver names but no glue records (IP addresses),
|
||||||
|
// the engine resolves them via a secondary traversal before continuing.
|
||||||
|
//
|
||||||
|
// # Caching
|
||||||
|
//
|
||||||
|
// An InfoCache stores discovered glue records. In fast mode (default) a
|
||||||
|
// single root cache is shared across all branches so that glue discovered in
|
||||||
|
// one branch is immediately available to sibling branches. Disable fast mode
|
||||||
|
// (TraverserConfig.Fast = false) for fully independent branch resolution.
|
||||||
package traverse
|
package traverse
|
||||||
|
|||||||
@@ -11,12 +11,20 @@ import (
|
|||||||
miekgdns "github.com/miekg/dns"
|
miekgdns "github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TraverserConfig configures the behaviour of a Traverser.
|
||||||
type TraverserConfig struct {
|
type TraverserConfig struct {
|
||||||
|
// MaxDepth is the maximum referral depth before the traversal gives up.
|
||||||
MaxDepth int
|
MaxDepth int
|
||||||
|
// QueryType is the DNS record type to query (e.g. dns.TypeA).
|
||||||
QueryType uint16
|
QueryType uint16
|
||||||
|
// RootConfig controls how root servers are discovered.
|
||||||
RootConfig *dns.RootDiscoveryConfig
|
RootConfig *dns.RootDiscoveryConfig
|
||||||
|
// QueryConfig controls per-query transport parameters.
|
||||||
QueryConfig *dns.QueryConfig
|
QueryConfig *dns.QueryConfig
|
||||||
|
// RootAddrs is an optional pre-seeded list of root server IP addresses.
|
||||||
|
// When non-empty, root discovery via RootConfig is skipped.
|
||||||
RootAddrs []net.IP
|
RootAddrs []net.IP
|
||||||
|
// Hooks provides optional callbacks for traversal events.
|
||||||
Hooks *TraverserHooks
|
Hooks *TraverserHooks
|
||||||
// Fast controls cache sharing across branches. When true (default), child
|
// Fast controls cache sharing across branches. When true (default), child
|
||||||
// branches inherit glue discovered by earlier branches via the shared root
|
// branches inherit glue discovered by earlier branches via the shared root
|
||||||
@@ -37,11 +45,14 @@ func DefaultTraverserConfig() *TraverserConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TraversalResult pairs a Referral with the Response received when it was processed.
|
||||||
type TraversalResult struct {
|
type TraversalResult struct {
|
||||||
Referral *Referral
|
Referral *Referral
|
||||||
Response *Response
|
Response *Response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Traverser performs an exhaustive iterative DNS traversal starting from the
|
||||||
|
// root servers. Create one via NewTraverser and call Traverse to start a run.
|
||||||
type Traverser struct {
|
type Traverser struct {
|
||||||
config *TraverserConfig
|
config *TraverserConfig
|
||||||
exchange dns.ExchangeFunc
|
exchange dns.ExchangeFunc
|
||||||
|
|||||||
Reference in New Issue
Block a user