Documentation ¶
Overview ¶
Package core handles a majority of the main functionality of SubFinder. It's meant to be small and extensible.
Index ¶
- Variables
- func AggregateCustomResults(in chan *Result, custom func(r *Result) bool) <-chan *Result
- func AggregateFailedResults(in chan *Result) <-chan *Result
- func AggregateSuccessfulResults(in chan *Result) <-chan *Result
- func EnumerateSubdomains(ctx context.Context, domain string, options *EnumerationOptions) <-chan *Result
- func MergeResults(inputs ...<-chan *Result) <-chan *Result
- func NewMultiSubdomainExtractor(domain string) func([]byte) []string
- func NewSingleSubdomainExtractor(domain string) func([]byte) string
- func UniqResults(input <-chan *Result) <-chan *Result
- type EnumerationOptions
- type GeneralOptions
- type Result
- func (r *Result) GetFailure() error
- func (r *Result) GetSuccess() interface{}
- func (r *Result) GetTimestamp() time.Time
- func (r *Result) GetType() string
- func (r *Result) HasTimestamp() bool
- func (r *Result) HasType() bool
- func (r *Result) IsFailure() bool
- func (r *Result) IsPrintable() (bool, string)
- func (r *Result) IsSuccess() bool
- func (r *Result) JSON() ([]byte, error)
- func (r *Result) Print() error
- func (r *Result) Printable() string
- func (r *Result) SetFailure(err error)
- func (r *Result) SetSuccess(success interface{})
- func (r *Result) SetTimestamp(t time.Time)
- func (r *Result) SetType(t string)
- type Source
Examples ¶
- AggregateCustomResults
- AggregateFailedResults
- AggregateSuccessfulResults
- EnumerateSubdomains
- EnumerationOptions
- EnumerationOptions.HasSources
- GeneralOptions
- NewDefaultGeneralOptions
- NewResult
- Result
- Result.GetFailure
- Result.GetSuccess
- Result.GetTimestamp
- Result.GetType
- Result.HasTimestamp
- Result.HasType
- Result.IsFailure
- Result.IsPrintable
- Result.IsSuccess
- Result.JSON
- Result.Print
- Result.Printable
- Result.SetFailure
- Result.SetSuccess
- Result.SetTimestamp
- Result.SetType
Constants ¶
This section is empty.
Variables ¶
var HTTPClient = &http.Client{ Transport: &http.Transport{ Dial: func(network string, address string) (net.Conn, error) { separator := strings.LastIndex(address, ":") ip, err := dnsCache.FetchOneString(address[:separator]) if err != nil { return nil, err } return net.Dial("tcp", ip+address[separator:]) }, MaxIdleConns: 1024, MaxIdleConnsPerHost: 2, TLSHandshakeTimeout: 10 * time.Second, IdleConnTimeout: 10 * time.Second, ResponseHeaderTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, }, }
HTTPClient is a reusable component that can be used in sources.
Functions ¶
func AggregateCustomResults ¶
AggregateCustomResults takes a given results channel as input along with a custom filter function that will be executed with each Result.
Example ¶
fakeResults := []*Result{ &Result{Type: "color", Success: "red"}, &Result{Type: "color", Success: "green"}, &Result{Type: "color", Success: "blue"}, &Result{Type: "color", Failure: errors.New("no color")}, &Result{Type: "wiggle", Failure: errors.New("wiggle")}, &Result{Success: "example"}, &Result{Failure: errors.New("example1")}, &Result{Failure: errors.New("example2")}, } // imagine a function doing something useful fakeResultsChan := make(chan *Result) go func(fakeResults []*Result, fakeResultsChan chan *Result) { defer close(fakeResultsChan) for _, result := range fakeResults { fakeResultsChan <- result } }(fakeResults, fakeResultsChan) // consume aggregated results for result := range AggregateCustomResults(fakeResultsChan, func(r *Result) bool { return r.Type == "color" && r.IsSuccess() // only successful results of type "color" }) { fmt.Println(result.Success) }
Output: red green blue
func AggregateFailedResults ¶
AggregateFailedResults takes a given results channel as input and only sends failed results down the returned output channel.
Example ¶
fakeResults := []*Result{ &Result{Success: true}, &Result{Success: 0}, &Result{Success: "wiggle"}, &Result{Failure: errors.New("example1")}, &Result{Failure: errors.New("example2")}, } fakeResultsChan := make(chan *Result) go func(fakeResults []*Result, fakeResultsChan chan *Result) { defer close(fakeResultsChan) for _, result := range fakeResults { fakeResultsChan <- result } }(fakeResults, fakeResultsChan) counter := 0 for range AggregateFailedResults(fakeResultsChan) { counter++ } fmt.Println(counter)
Output: 2
func AggregateSuccessfulResults ¶
AggregateSuccessfulResults takes a given results channel as input and only sends successful results down the returned output channel.
Example ¶
fakeResults := []*Result{ &Result{Success: true}, &Result{Success: 0}, &Result{Success: "wiggle"}, &Result{Failure: errors.New("example1")}, &Result{Failure: errors.New("example2")}, } fakeResultsChan := make(chan *Result) go func(fakeResults []*Result, fakeResultsChan chan *Result) { defer close(fakeResultsChan) for _, result := range fakeResults { fakeResultsChan <- result } }(fakeResults, fakeResultsChan) counter := 0 for range AggregateSuccessfulResults(fakeResultsChan) { counter++ } fmt.Println(counter)
Output: 3
func EnumerateSubdomains ¶
func EnumerateSubdomains(ctx context.Context, domain string, options *EnumerationOptions) <-chan *Result
EnumerateSubdomains takes the given domain and with each Source from EnumerationOptions, it will spawn a go routine to start processing that Domain. The result channels from each source are merged into one results channel to be consumed.
____________________________ Source1.ProcessDomain ___________ _____ | | / \ | | | | | EnumerationOptions.Sources | -- Source2.ProcessDomain -- | Results | ---> | ? | |____________________________| \ / |___________| |_____| Source3.ProcessDomain
Example ¶
domain := "google.com" ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() sources := []Source{ &FakeSource1{}, &FakeSource2{}, } options := &EnumerationOptions{ Sources: sources, } counter := 0 for result := range EnumerateSubdomains(ctx, domain, options) { if result.Failure == nil { counter++ } } fmt.Println(counter)
Output: 6
func MergeResults ¶
MergeResults takes in N number of result channels and merges them into one resul channel.
func NewMultiSubdomainExtractor ¶
NewMultiSubdomainExtractor creates a new extractor that looks for as many subdomains as it can find.
func NewSingleSubdomainExtractor ¶
NewSingleSubdomainExtractor creates a new extractor that looks for only one subdomain.
func UniqResults ¶
UniqResults filters a given input stream for uniq outputs. Note: this will only be a filter for successful results.
Types ¶
type EnumerationOptions ¶
type EnumerationOptions struct { Sources []Source Context context.Context Recursive bool Debug bool Uniq bool }
EnumerationOptions provides all the data needed for subdomain enumeration. This includes all the sources which will be queried to find them.
Example ¶
opts := EnumerationOptions{} if opts.HasSources() { fmt.Println("sources found in options") } else { fmt.Println("sources not found in options") }
Output: sources not found in options
func (*EnumerationOptions) HasSources ¶
func (opts *EnumerationOptions) HasSources() bool
HasSources checks if the EnumerationOptions have any source defined.
Example ¶
opts := EnumerationOptions{} fmt.Println(opts.HasSources())
Output: false
type GeneralOptions ¶
type GeneralOptions struct { Verbose bool // Show verbose information. ColorSupport bool // Whether to use color or not. AvailableCores int // Number of logical CPUs usable by the current process. DefaultTimeout time.Duration // Timeout for requests to different sources. TargetDomains []string // The target domains. Recursive bool // Perform recursive subdomain discovery or not. PassiveOnly bool // Perform only passive subdomain discovery or not. IgnoreErrors bool // Ignore errors or not. OutputType string // Type of output wanted (json, plaintext, ect). Sources []Source // List of source types to use. OutputDir string // Directory to use for any output. Resolvers []string // List of DNS resolvers to use. }
GeneralOptions represents a set of global options an application may be aware of (thinking of a command-line app).
Example ¶
opts := GeneralOptions{} opts.Print()
Output: Verbose: 'false' ColorSupport: 'false' AvailableCores: '0' DefaultTimeout: '0s' TargetDomains: '[]' Recursive: 'false' PassiveOnly: 'false' IgnoreErrors: 'false' OutputType: '' Sources: '[]' OutputDir: '' Resolvers: '[]'
func NewDefaultGeneralOptions ¶
func NewDefaultGeneralOptions() *GeneralOptions
NewDefaultGeneralOptions create a new GeneralOptions with some sane defaults.
Example ¶
opts := NewDefaultGeneralOptions() opts.Print()
Output: Verbose: 'false' ColorSupport: 'true' AvailableCores: '8' DefaultTimeout: '5s' TargetDomains: '[]' Recursive: 'false' PassiveOnly: 'false' IgnoreErrors: 'false' OutputType: 'plaintext' Sources: '[]' OutputDir: '' Resolvers: '[1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 9.9.9.9 149.112.112.112 208.67.222.222 208.67.220.220]'
func (*GeneralOptions) Print ¶
func (opts *GeneralOptions) Print()
Print takes the Printable form of the GeneralOptions and outputs it to STDOUT.
func (*GeneralOptions) Printable ¶
func (opts *GeneralOptions) Printable() string
Printable returns a formatted string of the GeneralOptions.
type Result ¶
type Result struct { sync.RWMutex Timestamp time.Time Type string Success interface{} Failure error }
Result contains the information from any given source. Upon success, a Source source should provide a string as the found subdomain. Upon Failure, the source should provide an error.
Example ¶
result := Result{Type: "example", Success: "info.bing.com"} if result.Failure != nil { fmt.Println(result.Type, ":", result.Failure) } else { fmt.Println(result.Type, ":", result.Success) }
Output: example : info.bing.com
func NewResult ¶
NewResult wraps up the creation of a new Result. This function will set the Timestamp value of the Result to the current time in UTC format, which is always preferred.
Example ¶
result := NewResult("example", "info.google.com", nil) if result.IsFailure() { fmt.Println(result.Failure.Error()) } else { if result.Success.(string) == "info.google.com" { fmt.Println("found example in success") } }
Output: found example in success
func (*Result) GetFailure ¶
GetFailure safely gets the error value from a Result which could be shared by multiple go routines.
Example ¶
McErr := errors.New("whoa there") result := NewResult("", nil, McErr) fmt.Println(result.Failure)
Output: whoa there
func (*Result) GetSuccess ¶
func (r *Result) GetSuccess() interface{}
GetSuccess safely gets the Success value from a Result which could be shared by multiple go routines.
Example ¶
result := NewResult("bing", "info.bing.com", nil) s := result.GetSuccess() fmt.Println(s)
Output: info.bing.com
func (*Result) GetTimestamp ¶
GetTimestamp safely gets the Timestamp value from a Result which could be shared by multiple go routines.
Example ¶
result := NewResult("bing", "info.bing.com", nil) newTimestamp := time.Now().UTC() result.Timestamp = newTimestamp fmt.Println(result.GetTimestamp() == newTimestamp)
Output: true
func (*Result) GetType ¶
GetType safely gets the type value from a Result which could be shared by multiple go routines.
Example ¶
result := NewResult("bing", "info.bing.com", nil) t := result.GetType() fmt.Println(t)
Output: bing
func (*Result) HasTimestamp ¶
HasTimestamp checks if the Result has a timestamp set.
Example ¶
result := Result{} // no Timestamp set fmt.Println(result.HasTimestamp())
Output: false
func (*Result) HasType ¶
HasType checks if the Result has a type value set.
Example ¶
result := Result{Type: "example"} fmt.Println(result.HasType())
Output: true
func (*Result) IsFailure ¶
IsFailure checks if the Result has any Failure before determining if the result failed.
Example ¶
result := Result{Failure: errors.New("failed to party")} if result.IsFailure() { fmt.Println(result.Failure.Error()) }
Output: failed to party
func (*Result) IsPrintable ¶
IsPrintable checks if the underlying Result has any printable information.
Example ¶
result := NewResult("example", "ex.ample.com", nil) ok, _ := result.IsPrintable() fmt.Println(ok)
Output: true
func (*Result) IsSuccess ¶
IsSuccess checks if the Result has any Failure, or that the Success interface{} has actually been filled before determining if the result succeeded.
Example ¶
result := Result{Success: "wiggle.github.com"} if result.IsSuccess() { fmt.Println(result.Success) }
Output: wiggle.github.com
func (*Result) JSON ¶
JSON returns the Result as a JSON object within a slice of bytes.
Example ¶
result := NewResult("example", "ex.ample.com", nil) result.Timestamp = time.Time{} // set default timestamp bytes, _ := result.JSON() fmt.Println(string(bytes))
Output: {"Timestamp":"0001-01-01T00:00:00Z","Type":"example","Success":"ex.ample.com","Failure":null}
func (*Result) Print ¶
Print will print the Printable version of the Result to the screen or return an error if the underlying Result has any printable information. Useful for debugging.
Example ¶
result := NewResult("example", "ex.ample.com", nil) result.Timestamp = time.Time{} // set default timestamp result.Print()
Output: Type: example Success: ex.ample.com
func (*Result) Printable ¶
Printable turns a Result's information into a printable format (for STDOUT).
Example ¶
result := NewResult("example", "ex.ample.com", nil) result.Timestamp = time.Time{} // set default timestamp printable := result.Printable() fmt.Println(printable)
Output: Type: example Success: ex.ample.com
func (*Result) SetFailure ¶
SetFailure safely sets a new error value for a Result which could be shared by multiple go routines.
Example ¶
McErr := errors.New("whoa there") result := NewResult("thisis", "totally.fine.com", nil) result.SetFailure(McErr) if result.IsFailure() { fmt.Println(result.Failure, "we found our failure!") } if result.IsSuccess() { fmt.Println("this will never print because the failure was set") }
Output: whoa there we found our failure!
func (*Result) SetSuccess ¶
func (r *Result) SetSuccess(success interface{})
SetSuccess safely sets a new Success value for a Result which could be shared by multiple go routines.
Example ¶
result := NewResult("example", "", nil) // do work, possibly in multiple go routines result.SetSuccess([]string{"a.com", "b.com", "c.com"}) // check if success fmt.Println(result.IsSuccess())
Output: true
func (*Result) SetTimestamp ¶
SetTimestamp safely sets a new Timestamp value for a Result which could be shared by multiple go routines.
Example ¶
result := NewResult("bing", "info.bing.com", nil) newTimestamp := time.Now().UTC() result.SetTimestamp(newTimestamp) fmt.Println(result.Timestamp == newTimestamp)
Output: true