scan

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2026 License: GPL-3.0 Imports: 10 Imported by: 0

Documentation

Overview

Package scan runs a subdomain scan: it validates options, dispatches candidate names to a worker pool, filters wildcard answers and reports results and statistics as events.

Index

Constants

View Source
const (
	VerdictComplete   = "complete"   // every candidate got a definitive answer, or nearly so
	VerdictDegraded   = "degraded"   // usable, but some candidates are unknown
	VerdictUnreliable = "unreliable" // too many failures to trust the absence of a name
)

Run-quality verdicts, from best to worst (#70).

Variables

This section is empty.

Functions

func IsExcluded added in v0.9.0

func IsExcluded(patterns []string, name string) bool

IsExcluded reports whether name is out of scope under the -exclude patterns, using the same rules as a scan.

func RecursionCeiling added in v0.7.0

func RecursionCeiling(n, depth int) float64

RecursionCeiling returns the theoretical job count for a recursive scan: sum over d=1..depth of n^d, as a float so large wordlists do not overflow.

func Run

func Run(ctx context.Context, cfg Config, events chan<- Event)

Run executes the subdomain scan, sending events to the provided channel. The caller must close or cancel ctx to abort early. Run closes events when the scan completes.

func ValidateExcludes added in v0.9.0

func ValidateExcludes(patterns []string) error

ValidateExcludes checks that every pattern is a domain or *.domain.

func VerdictRank added in v0.9.0

func VerdictRank(v string) int

VerdictRank orders verdicts so the worst of several can be picked.

func Verify added in v0.9.0

func Verify(ctx context.Context, cfg Config, names []string) (map[string]dns.Outcome, int64)

Verify looks each name up once more and returns its outcome, with the number of DNS queries sent. -diff uses it to confirm that a name from a previous run is really gone before reporting it removed (#110): a name may be missing from this run only because it was not a candidate (a smaller wordlist, no -recursive or -permute) or because its lookup failed.

Lookups use the trusted resolver (never Pool) or the simulation, and honour Concurrency, Rate, Attempts, Timeout and Types. Names in Exclude are not looked up and are absent from the result. Wildcard answers are not filtered: a name under a wildcard still resolves, so it is never reported removed. Cancelled lookups report OutcomeCanceled.

Types

type Config

type Config struct {
	Domain      string
	Entries     []string
	Concurrency int
	Timeout     time.Duration
	DNSServer   string
	Simulate    bool
	HitRate     int
	Seed        uint64 // simulation seed: the same seed reproduces the same simulated results
	Attempts    int
	Force       bool
	Verbose     bool     // log every lookup; through Logf when set, else unsynchronized to stderr
	Logf        dns.Logf // receives verbose lines when Verbose is set
	Rate        int      // max DNS messages per second on the wire, all workers combined (0 = unlimited)
	Types       []string // record types to look up (A, AAAA, CNAME); empty = A,AAAA
	Recursive   bool     // enumerate subdomains of discovered subdomains
	Depth       int      // max recursion depth (1 = no recursion)
	NoAbort     bool     // keep scanning after the reliability guard fires
	MaxQueries  int      // cap on admitted candidate names (jobs), not wire queries (0 = unlimited)
	Exclude     []string // out-of-scope names and *.parent patterns; never queried (#87)

	// Resuming an interrupted scan (#73): ResumeFrom skips the wordlist
	// entries before it (Stats.RootDone of the interrupted run), and
	// ResumeParents are names found before the interrupt whose children a
	// recursive scan still has to expand.
	ResumeFrom    int
	ResumeParents []string
	Resolver      *net.Resolver // reused across lookups; nil means scan.Run constructs one
	// Pool, when set, spreads candidate lookups over several resolvers (#69).
	// Every pool hit is re-validated against Resolver (the trusted
	// -dns-server), whose answer is the one reported; preflight and wildcard
	// checks also use Resolver.
	Pool *dns.Pool
	// contains filtered or unexported fields
}

Config holds all parameters needed to run a subdomain scan.

type Event

type Event struct {
	Kind      EventKind
	Notice    NoticeKind   // EventNotice: what the notice is about
	Domain    string       // EventResult: the resolved subdomain
	Records   []dns.Record // EventResult: the resolved records (A/AAAA/CNAME)
	Takeover  string       // EventResult: subdomain-takeover hint, see dns.TakeoverHint (#71)
	Processed int64        // EventProgress
	Total     int64        // EventProgress
	Found     int64        // EventProgress / EventDone
	Message   string       // EventError / EventNotice
	Stats     Stats        // EventDone: per-outcome counters
}

Event is emitted on the events channel during a scan.

type EventKind

type EventKind int

EventKind categorises a scan event.

const (
	// EventResult reports a resolved subdomain.
	EventResult   EventKind = iota
	EventProgress           // progress update
	EventNotice             // informational notice; see Event.Notice
	EventError              // non-fatal error message
	EventDone               // scan finished
)

Event kinds.

type NoticeKind added in v0.9.0

type NoticeKind int

NoticeKind says what an EventNotice is about, so consumers can style or filter notices without parsing the message (#68).

const (
	// NoticeWildcard means wildcard DNS was detected, or its check failed
	// under -force.
	NoticeWildcard NoticeKind = iota + 1
	NoticeCap                 // -max-queries reached; candidates skipped
	NoticeCeiling             // recursive scan may generate very many queries
	NoticeSkip                // a recursive branch was not expanded
)

Notice kinds.

func (NoticeKind) String added in v0.9.0

func (k NoticeKind) String() string

String names a notice kind for structured output.

type Options added in v0.9.0

type Options struct {
	Domain      string
	Entries     []string
	Concurrency int
	TimeoutMs   int
	DNSServer   string
	Simulate    bool
	HitRate     int
	Seed        uint64
	Attempts    int
	Force       bool
	Types       []string
	Recursive   bool
	Depth       int
	Rate        int
	MaxQueries  int
	Exclude     []string
	Pool        *dns.Pool // -r resolver pool; DNSServer is then the trusted resolver
	// Resume point of an interrupted scan (#73); see Config.
	ResumeFrom    int
	ResumeParents []string
	NoAbort       bool
	Verbose       bool
	Logf          dns.Logf
}

Options are the user-facing scan settings. The CLI and the TUI each fill one in from their own inputs, then share Validate and Config, so the two front ends cannot drift apart in what they accept or how they scan (#80).

func (Options) Config added in v0.9.0

func (o Options) Config() Config

Config builds the scan.Config for these options.

func (Options) Validate added in v0.9.0

func (o Options) Validate() error

Validate checks the numeric ranges and the resolver address. Messages name the CLI flag too, so they read well in both front ends. The resolver is not checked in simulation mode, which sends no DNS traffic.

type Stats added in v0.7.0

type Stats struct {
	Found            int64
	NXDomain         int64
	Timeout          int64
	Refused          int64
	Other            int64
	WildcardFiltered int64

	// Run facts for the quality report (#70); not part of Sum.
	QueriesSent int64 // DNS queries dialed, retries included (0 when simulated)
	Skipped     int64 // candidates not tested because -max-queries was reached
	Excluded    int64 // candidates not tested because -exclude put them out of scope
	PoolHits    int64 // names a pool resolver said exist (-r)
	Confirmed   int64 // pool hits the trusted resolver confirmed
	Unconfirmed int64 // pool hits the trusted resolver said do not exist
	Takeover    int64 // results flagged as subdomain-takeover candidates
	// RootDone is the resume point: every wordlist entry before this index
	// has been fully looked up (#73). Entries at or after it may also be
	// done; resuming repeats at most a worker pool's worth of lookups.
	RootDone    int64
	Aborted     bool         // the reliability guard cancelled the scan
	Wildcard    bool         // the root domain is a wildcard (scanned under -force)
	Fingerprint []dns.Record // final wildcard fingerprint, empty when none
}

Stats is a snapshot of per-outcome query counters. Populated on EventDone.

func (Stats) Sum added in v0.7.0

func (s Stats) Sum() int64

Sum returns the number of classified queries (found + negatives + failures + wildcard-filtered).

func (Stats) Verdict added in v0.9.0

func (s Stats) Verdict(interrupted bool) (verdict, reason string)

Verdict grades a scan that reached EventDone. interrupted is set when the user stopped it (Ctrl+C, SIGTERM), which Stats cannot know.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL