docs: comprehensive documentation for ExploreDNS
CI / test (pull_request) Failing after 2m13s

- Rewrite README.md with overview, features, installation (go install +
  build from source), quick start, full CLI flag reference table,
  output section descriptions, project structure, and development guide

- Add package-level doc comments to all five internal packages:
  config, dns, fingerprint, output, traverse (via doc.go or existing
  package-declaration files)

- Add GoDoc comments on every exported type, constant, function, and
  method across all packages:
  - internal/config: Config struct fields, all Parse*/Default/Validate
  - internal/dns: QueryConfig, Resolver, BasicResolver, CachingResolver,
    ExchangeFunc, RootServer, RootDiscoveryConfig, DecodedResponse,
    ResponseClassification, all exported helpers
  - internal/fingerprint: Fingerprinter, New, NewWithTimeout, Query,
    FingerprintAll
  - internal/traverse: Traverser, TraverserConfig, TraversalResult,
    Referral, ResolutionState, Response, ResponseType, InfoCache,
    Stack, TraverserHooks, EventStage, TraversalEvent, EventHandler,
    CircularReferralError, UnresolvableNameserverError
  - internal/output: Format, Config, Formatter, SummaryStats,
    NewFormatter, AttachHooks, RunTraversal, DefaultConfig,
    ComputeSummary

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
Gary Hansen
2026-06-08 04:01:51 +10:00
co-authored by Copilot multica-agent
parent fe1afe2a97
commit 9aa85d8e5d
21 changed files with 675 additions and 91 deletions
+54 -13
View File
@@ -10,6 +10,7 @@ import (
"github.com/miekg/dns"
)
// Sentinel errors returned by validation and parsing functions.
var (
ErrInvalidQueryType = errors.New("invalid query type")
ErrInvalidUDPSize = errors.New("UDP size must be between 512 and 4096")
@@ -20,22 +21,41 @@ var (
ErrInvalidRootServer = errors.New("invalid root server IP address")
)
// Config holds all runtime settings for ExploreDNS.
// Populate it from CLI flags, then call Validate before use.
type Config struct {
QueryType string
RootServer string
// QueryType is the DNS record type to query (e.g. "A", "MX", "TXT").
QueryType string
// RootServer overrides the root server IP used to begin traversal.
// Empty string means auto-discover via the system resolver.
RootServer string
// AllRootServers queries all 13 DNS root servers instead of one.
AllRootServers bool
RootAAAA bool
FollowAAAA bool
UDPSize int
AllowTCP bool
AlwaysTCP bool
MaxDepth int
Retries int
Fast bool
Verbose bool
Debug int
Quiet bool
// RootAAAA includes IPv6 addresses of root servers when true.
RootAAAA bool
// FollowAAAA restricts referral following to AAAA glue records only.
FollowAAAA bool
// UDPSize is the EDNS0 advertised UDP payload size (512–4096 bytes).
UDPSize int
// AllowTCP enables TCP fallback when a UDP response is truncated.
AllowTCP bool
// AlwaysTCP forces all queries over TCP (requires AllowTCP = true).
AlwaysTCP bool
// MaxDepth limits the traversal depth (1–100).
MaxDepth int
// Retries is the number of times a failed query is retried (0–10).
Retries int
// Fast enables the shared-cache fast mode. When true, sibling branches
// inherit glue discovered by earlier branches, trading accuracy for speed.
Fast bool
// Verbose enables verbose output lines.
Verbose bool
// Debug controls debug verbosity: 0 = off, 1 = app debug, 2 = library debug.
Debug int
// Quiet suppresses supplementary informational output.
Quiet bool
// Output visibility flags — each controls a section of the output.
ShowProgress bool
ShowResolves bool
ShowServers bool
@@ -45,6 +65,8 @@ type Config struct {
ShowSummaryResults bool
}
// ParseQueryType converts a case-insensitive query type string (e.g. "A", "MX")
// to its numeric DNS type constant. Returns ErrInvalidQueryType for unknown types.
func ParseQueryType(s string) (uint16, error) {
s = strings.ToUpper(s)
switch s {
@@ -71,6 +93,8 @@ func ParseQueryType(s string) (uint16, error) {
}
}
// ParseUDPSize parses a string as a UDP buffer size.
// Returns ErrInvalidUDPSize if the string is not an integer or is outside 512–4096.
func ParseUDPSize(s string) (int, error) {
var size int
if _, err := fmt.Sscanf(s, "%d", &size); err != nil {
@@ -82,6 +106,8 @@ func ParseUDPSize(s string) (int, error) {
return size, nil
}
// ParseMaxDepth parses a string as a traversal depth.
// Returns ErrInvalidMaxDepth if the string is not an integer or is outside 1–100.
func ParseMaxDepth(s string) (int, error) {
var depth int
if _, err := fmt.Sscanf(s, "%d", &depth); err != nil {
@@ -93,6 +119,8 @@ func ParseMaxDepth(s string) (int, error) {
return depth, nil
}
// ParseRetries parses a string as a retry count.
// Returns ErrInvalidRetries if the string is not an integer or is outside 0–10.
func ParseRetries(s string) (int, error) {
var retries int
if _, err := fmt.Sscanf(s, "%d", &retries); err != nil {
@@ -104,6 +132,9 @@ func ParseRetries(s string) (int, error) {
return retries, nil
}
// Validate checks that all Config fields are within their accepted ranges and
// that flag combinations are valid (e.g. AlwaysTCP requires AllowTCP).
// Returns the first validation error encountered, or nil.
func (c *Config) Validate() error {
if _, err := ParseQueryType(c.QueryType); err != nil {
return err
@@ -128,6 +159,8 @@ func (c *Config) Validate() error {
return nil
}
// GetDomain returns the domain name from the positional CLI arguments.
// Returns ErrMissingDomain when args is empty.
func (c *Config) GetDomain(args []string) (string, error) {
if len(args) == 0 {
return "", ErrMissingDomain
@@ -135,6 +168,9 @@ func (c *Config) GetDomain(args []string) (string, error) {
return args[0], nil
}
// ParseRootServer parses the RootServer field as an IP address.
// Returns nil, nil when RootServer is empty (auto-discover mode).
// Returns ErrInvalidRootServer when the string is non-empty but not a valid IP.
func (c *Config) ParseRootServer() (net.IP, error) {
if c.RootServer == "" {
return nil, nil
@@ -158,6 +194,8 @@ func ParseDebugLevel(d, dd bool) int {
return 0
}
// PrintUsage writes a grouped help message to stderr, listing every flag with
// its description. It is registered as flag.Usage by main.
func PrintUsage() {
fmt.Fprintf(os.Stderr, "ExploreDNS - DNS reconnaissance and exploration tool\n\n")
fmt.Fprintf(os.Stderr, "Usage:\n")
@@ -211,6 +249,9 @@ func PrintUsage() {
}
}
// DefaultConfig returns a Config populated with sensible defaults:
// query type A, UDP size 2048, max depth 20, 2 retries, fast mode on,
// TCP fallback allowed, and all output sections visible.
func DefaultConfig() *Config {
return &Config{
QueryType: "A",