### Install Subfinder via Go Source: https://github.com/projectdiscovery/subfinder/blob/dev/README.md Requires Go 1.24 or later to install the latest version of the tool. ```sh go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest ``` -------------------------------- ### Configure JSON Output Programmatically Source: https://context7.com/projectdiscovery/subfinder/llms.txt Enable JSON output and capture all sources by setting 'JSON' and 'CaptureSources' to true in the runner options. The output will be in JSONL format. ```go package main import ( "bytes" "context" "io" "log" "github.com/projectdiscovery/subfinder/v2/pkg/runner" ) func main() { options := &runner.Options{ Threads: 10, Timeout: 30, MaxEnumerationTime: 10, JSON: true, CaptureSources: true, } subfinder, err := runner.NewRunner(options) if err != nil { log.Fatalf("failed to create runner: %v", err) } output := &bytes.Buffer{} _, err = subfinder.EnumerateSingleDomainWithCtx( context.Background(), "example.com", []io.Writer{output}, ) if err != nil { log.Fatalf("enumeration failed: %v", err) } log.Println(output.String()) } ``` -------------------------------- ### Configure Wildcard Removal and Active Resolution Source: https://context7.com/projectdiscovery/subfinder/llms.txt Enable wildcard removal and active resolution by configuring the runner options. Ensure 'HostIP' is true when 'RemoveWildcard' is enabled for IP inclusion. ```go package main import ( "bytes" "context" "io" "log" "github.com/projectdiscovery/goflags" "github.com/projectdiscovery/subfinder/v2/pkg/runner" ) func main() { options := &runner.Options{ Threads: 20, Timeout: 30, MaxEnumerationTime: 15, RemoveWildcard: true, HostIP: true, Resolvers: goflags.StringSlice{ "8.8.8.8", "1.1.1.1", "9.9.9.9", }, } subfinder, err := runner.NewRunner(options) if err != nil { log.Fatalf("failed to create runner: %v", err) } output := &bytes.Buffer{} _, err = subfinder.EnumerateSingleDomainWithCtx( context.Background(), "hackerone.com", []io.Writer{output}, ) if err != nil { log.Fatalf("enumeration failed: %v", err) } log.Println(output.String()) } ``` -------------------------------- ### Configure Sources and Exclusions Source: https://context7.com/projectdiscovery/subfinder/llms.txt Customize the enumeration process by specifying allowed or excluded data sources. ```go package main import ( "bytes" "context" "io" "log" "github.com/projectdiscovery/goflags" "github.com/projectdiscovery/subfinder/v2/pkg/runner" ) func main() { options := &runner.Options{ Threads: 10, Timeout: 30, MaxEnumerationTime: 10, // Use only specific sources Sources: goflags.StringSlice{"crtsh", "hackertarget", "virustotal"}, // Or exclude specific sources // ExcludeSources: goflags.StringSlice{"alienvault", "dnsdumpster"}, // Use all sources (including slow ones) // All: true, // Use only recursive-capable sources // OnlyRecursive: true, } subfinder, err := runner.NewRunner(options) if err != nil { log.Fatalf("failed to create runner: %v", err) } output := &bytes.Buffer{} _, err = subfinder.EnumerateSingleDomainWithCtx( context.Background(), "example.com", []io.Writer{output}, ) if err != nil { log.Fatalf("enumeration failed: %v", err) } log.Println(output.String()) } ``` -------------------------------- ### Source Selection and Configuration Source: https://context7.com/projectdiscovery/subfinder/llms.txt Manage which passive sources are queried during the enumeration process. ```bash # Use specific sources only subfinder -d hackerone.com -s crtsh,github,virustotal # Exclude specific sources subfinder -d hackerone.com -es alienvault,zoomeyeapi # Use all available sources (slower but more comprehensive) subfinder -d hackerone.com -all # Use only recursive-capable sources subfinder -d hackerone.com -recursive # List all available sources subfinder -ls ``` -------------------------------- ### Proxy and Network Configuration Source: https://context7.com/projectdiscovery/subfinder/llms.txt Configure network settings such as HTTP proxies or IP exclusion. ```bash # Use HTTP proxy subfinder -d hackerone.com -proxy http://127.0.0.1:8080 # Exclude IP addresses from results subfinder -d hackerone.com -ei ``` -------------------------------- ### Process Results with Callbacks Source: https://context7.com/projectdiscovery/subfinder/llms.txt Use the ResultCallback option to handle discovered subdomains in real-time as they are found. ```go package main import ( "bytes" "context" "io" "log" "sync/atomic" "github.com/projectdiscovery/subfinder/v2/pkg/resolve" "github.com/projectdiscovery/subfinder/v2/pkg/runner" ) func main() { var count atomic.Int64 options := &runner.Options{ Threads: 10, Timeout: 30, MaxEnumerationTime: 10, // Callback executed for each unique subdomain found ResultCallback: func(result *resolve.HostEntry) { count.Add(1) log.Printf("[%d] Found: %s (source: %s)\n", count.Load(), result.Host, result.Source, ) }, } subfinder, err := runner.NewRunner(options) if err != nil { log.Fatalf("failed to create runner: %v", err) } output := &bytes.Buffer{} _, err = subfinder.EnumerateSingleDomainWithCtx( context.Background(), "hackerone.com", []io.Writer{output}, ) if err != nil { log.Fatalf("enumeration failed: %v", err) } log.Printf("Total subdomains found: %d\n", count.Load()) } ``` -------------------------------- ### Handle Context Cancellation and Timeout Source: https://context7.com/projectdiscovery/subfinder/llms.txt Implement context cancellation and timeout control for subdomain enumeration. Use 'context.WithTimeout' to set a deadline and check 'ctx.Err()' for timeout status. ```go package main import ( "bytes" "context" "io" "log" "time" "github.com/projectdiscovery/subfinder/v2/pkg/runner" ) func main() { options := &runner.Options{ Threads: 10, Timeout: 30, MaxEnumerationTime: 5, } subfinder, err := runner.NewRunner(options) if err != nil { log.Fatalf("failed to create runner: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() output := &bytes.Buffer{} _, err = subfinder.EnumerateSingleDomainWithCtx( ctx, "hackerone.com", []io.Writer{output}, ) if ctx.Err() == context.DeadlineExceeded { log.Println("Enumeration timed out, partial results:") } else if err != nil { log.Fatalf("enumeration failed: %v", err) } log.Println(output.String()) } ``` -------------------------------- ### Provider Configuration Source: https://context7.com/projectdiscovery/subfinder/llms.txt Configure API keys for external sources via YAML or environment variables. ```yaml # Example provider configuration bevigil: - your-bevigil-api-key censys: - your-censys-api-id:your-censys-api-secret chaos: - your-chaos-api-key fofa: - your-fofa-email:your-fofa-key github: - ghp_your_github_token_1 - ghp_your_github_token_2 securitytrails: - your-securitytrails-api-key shodan: - your-shodan-api-key virustotal: - your-virustotal-api-key whoisxmlapi: - your-whoisxmlapi-key ``` ```bash # Set API key via environment variable export SHODAN_API_KEY=your-shodan-api-key export GITHUB_API_KEY=ghp_your_github_token subfinder -d hackerone.com ``` -------------------------------- ### Basic Subdomain Enumeration Source: https://context7.com/projectdiscovery/subfinder/llms.txt Perform standard subdomain discovery using various input methods and output formats. ```bash # Basic enumeration for a single domain subfinder -d hackerone.com # Enumerate multiple domains subfinder -d hackerone.com,github.com # Read domains from a file subfinder -dL domains.txt # Pipe domains from stdin echo "hackerone.com" | subfinder # Output results to a file subfinder -d hackerone.com -o results.txt # Output in JSON format subfinder -d hackerone.com -oJ -o results.json ``` -------------------------------- ### Enumerate a Single Domain Source: https://context7.com/projectdiscovery/subfinder/llms.txt Use EnumerateSingleDomainWithCtx to perform subdomain discovery on a specific target domain. ```go package main import ( "bytes" "context" "io" "log" "github.com/projectdiscovery/subfinder/v2/pkg/runner" ) func main() { // Configure subfinder options options := &runner.Options{ Threads: 10, // Concurrent goroutines for resolution Timeout: 30, // Seconds to wait for sources MaxEnumerationTime: 10, // Minutes to wait for enumeration // ProviderConfig: "/path/to/provider-config.yaml", } // Disable log timestamps log.SetFlags(0) // Create the runner subfinder, err := runner.NewRunner(options) if err != nil { log.Fatalf("failed to create subfinder runner: %v", err) } // Create output buffer output := &bytes.Buffer{} // Enumerate subdomains for a single domain sourceMap, err := subfinder.EnumerateSingleDomainWithCtx( context.Background(), "hackerone.com", []io.Writer{output}, ) if err != nil { log.Fatalf("failed to enumerate domain: %v", err) } // Print discovered subdomains log.Println("Discovered subdomains:") log.Println(output.String()) // Access results with source information for subdomain, sources := range sourceMap { sourceList := make([]string, 0, len(sources)) for source := range sources { sourceList = append(sourceList, source) } log.Printf("%s found by: %v\n", subdomain, sourceList) } } ``` -------------------------------- ### Enumerate Multiple Domains Source: https://context7.com/projectdiscovery/subfinder/llms.txt Process lists of domains using an io.Reader, such as a string reader or a file handle. ```go package main import ( "bytes" "context" "io" "log" "os" "strings" "github.com/projectdiscovery/subfinder/v2/pkg/runner" ) func main() { options := &runner.Options{ Threads: 10, Timeout: 30, MaxEnumerationTime: 10, } subfinder, err := runner.NewRunner(options) if err != nil { log.Fatalf("failed to create runner: %v", err) } // Method 1: From a string reader domains := "hackerone.com\ngithub.com\nexample.com" reader := strings.NewReader(domains) output := &bytes.Buffer{} err = subfinder.EnumerateMultipleDomainsWithCtx( context.Background(), reader, []io.Writer{output}, ) if err != nil { log.Fatalf("enumeration failed: %v", err) } // Method 2: From a file file, err := os.Open("domains.txt") if err != nil { log.Fatalf("failed to open file: %v", err) } defer file.Close() fileOutput := &bytes.Buffer{} err = subfinder.EnumerateMultipleDomainsWithCtx( context.Background(), file, []io.Writer{fileOutput}, ) if err != nil { log.Fatalf("enumeration failed: %v", err) } log.Println(fileOutput.String()) } ``` -------------------------------- ### Output Filtering and Formatting Source: https://context7.com/projectdiscovery/subfinder/llms.txt Apply filters to results or customize the output format and verbosity. ```bash # Match specific subdomain patterns subfinder -d hackerone.com -m "api.*,dev.*" # Filter out specific patterns subfinder -d hackerone.com -f "www,mail" # Include all sources in JSON output subfinder -d hackerone.com -oJ -cs # Silent mode (subdomains only) subfinder -d hackerone.com -silent # Verbose output subfinder -d hackerone.com -v # Output to directory (one file per domain) subfinder -dL domains.txt -oD output_dir/ ``` -------------------------------- ### Rate Limiting and Performance Tuning Source: https://context7.com/projectdiscovery/subfinder/llms.txt Adjust performance parameters to manage request rates and execution time. ```bash # Set global rate limit (requests per second) subfinder -d hackerone.com -rl 10 # Set per-source rate limits subfinder -d hackerone.com -rls "hackertarget=10/m,shodan=15/s" # Set timeout for source responses (seconds) subfinder -d hackerone.com -timeout 60 # Set maximum enumeration time (minutes) subfinder -d hackerone.com -max-time 30 # Set number of concurrent threads for resolution subfinder -d hackerone.com -nW -t 20 ``` -------------------------------- ### Active Mode and DNS Resolution Source: https://context7.com/projectdiscovery/subfinder/llms.txt Enable active resolution to filter out wildcard subdomains and dead entries. ```bash # Enable active mode (resolves subdomains, removes wildcards) subfinder -d hackerone.com -nW # Active mode with IP addresses in output subfinder -d hackerone.com -nW -oI # Specify custom resolvers subfinder -d hackerone.com -nW -r 8.8.8.8,1.1.1.1 # Use resolvers from a file subfinder -d hackerone.com -nW -rL resolvers.txt ``` -------------------------------- ### Use Passive Enumeration Agent Directly Source: https://context7.com/projectdiscovery/subfinder/llms.txt Utilize the passive enumeration agent directly for more control over sources. You can specify exact sources, exclude sources, or use all available sources. ```go package main import ( "context" "log" "time" "github.com/projectdiscovery/subfinder/v2/pkg/passive" "github.com/projectdiscovery/subfinder/v2/pkg/subscraping" ) func main() { agent := passive.New( []string{"crtsh", "hackertarget", "certspotter"}, []string{}, false, false, ) ctx := context.Background() results := agent.EnumerateSubdomainsWithCtx( ctx, "hackerone.com", "", 0, 30, 10*time.Minute, ) subdomains := make(map[string]struct{}) for result := range results { switch result.Type { case subscraping.Subdomain: if _, exists := subdomains[result.Value]; !exists { subdomains[result.Value] = struct{}{} log.Printf("[%s] %s\n", result.Source, result.Value) } case subscraping.Error: log.Printf("Error from %s: %v\n", result.Source, result.Error) } } log.Printf("Total unique subdomains: %d\n", len(subdomains)) stats := agent.GetStatistics() for source, stat := range stats { log.Printf("%s: %d results, %d requests, %d errors, took %v\n", source, stat.Results, stat.Requests, stat.Errors, stat.TimeTaken) } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.