Subfinder

repository·dev·Indexed 12 days ago

https://github.com/projectdiscovery/subfinder

A fast, passive subdomain enumeration tool for security professionals, penetration testers, and bug bounty hunters. Subfinder uses curated passive online sources to discover valid subdomains and can be used as a standalone CLI binary or integrated into Go projects as a library via the pkg/runner package.

Tokens
2.7K
Snippets
7
Records
9
Agent score
93%

What's inside Subfinder

  1. Install Subfinder via Go

    dev

    To install the latest version of subfinder, ensure you have go1.24 installed and run the following command:

    go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
    go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
  2. Configure Subfinder via Environment Variables

    dev

    You can override the default configuration and provider configuration file paths using the following environment variables:

    • SUBFINDER_CONFIG: Path to the config.yaml file (overrides default $CONFIG/subfinder/config.yaml).
    • SUBFINDER_PROVIDER_CONFIG: Path to the provider-config.yaml file (overrides default $CONFIG/subfinder/provider-config.yaml).
  3. Run Subfinder via CLI

    dev

    Subfinder is a tool for subdomain enumeration. When run as a standalone binary, it parses command-line flags and configuration files to initialize a runner, which then executes the enumeration process. The CLI entrypoint uses runner.ParseOptions() to handle user input and runner.NewRunner(options) to initialize the engine.

    # Subfinder is typically used as a compiled binary from the command line.
    # Example usage (standard CLI behavior):
    subfinder -d example.com
  4. Use Subfinder CLI Flags

    dev

    Subfinder provides a wide range of flags to control input, sources, filtering, rate-limiting, and output formats. Use subfinder -h to view the full help menu.

    Usage:
      ./subfinder [flags]
    
    Flags:
    INPUT:
      -d, -domain string[]  domains to find subdomains for
      -dL, -list string     file containing list of domains for subdomain discovery
    
    SOURCE:
      -s, -sources string[]           specific sources to use for discovery (-s crtsh,github). Use -ls to display all available sources.
      -recursive                      use only sources that can handle subdomains recursively (e.g. subdomain.domain.tld vs domain.tld)
      -all                            use all sources for enumeration (slow)
      -es, -exclude-sources string[]  sources to exclude from enumeration (-es alienvault,zoomeyeapi)
    
    FILTER:
      -m, -match string[]   subdomain or list of subdomain to match (file or comma separated)
      -f, -filter string[]   subdomain or list of subdomain to filter (file or comma separated)
    
    RATE-LIMIT:
      -rl, -rate-limit int  maximum number of http requests to send per second
      -rls value            maximum number of http requests to send per second for providers in key=value format (-rls "hackertarget=10/s,shodan=15/s")
      -t int                number of concurrent goroutines for resolving (-active only) (default 10)
    
    UPDATE:
      -up, -update                 update subfinder to latest version
      -duc, -disable-update-check  disable automatic subfinder update check
    
    OUTPUT:
      -o, -output string       file to write output to
      -oJ, -json               write output in JSONL(ines) format
      -oD, -output-dir string  directory to write output (-dL only)
      -cs, -collect-sources    include all sources in the output (-json only)
      -oI, -ip                 include host IP in output (-active only)
    
    CONFIGURATION:
      -config string                flag config file (default "$CONFIG/subfinder/config.yaml")
      -pc, -provider-config string  provider config file (default "$CONFIG/subfinder/provider-config.yaml")
      -r string[]                   comma separated list of resolvers to use
      -rL, -rlist string            file containing list of resolvers to use
      -nW, -active                  display active subdomains only
      -proxy string                 http proxy to use with subfinder
      -ei, -exclude-ip              exclude IPs from the list of domains
      -mr, -max-results int         limit the number of results per source (0 = unlimited; honored by paginating sources)
    
    DEBUG:
      -silent             show only subdomains in output
      -version            show version of subfinder
      -v                  show verbose output
      -nc, -no-color      disable color in output
      -ls, -list-sources  list all available sources (-oJ for JSON)
    
    OPTIMIZATION:
      -timeout int                  seconds to wait before timing out (default 30)
      -max-time int                 minutes to wait for enumeration results (default 10)
      -rsr, -response-size-read int max response body size to read in bytes from passive sources (0 = unlimited)
  5. Initialize a new Resolver

    dev

    Use the New() function to create a new Resolver instance. By default, the Resolvers slice is initialized as empty, allowing you to provide your own list of DNS resolvers or use the DefaultResolvers provided by the package.

    import "github.com/projectdiscovery/subfinder/pkg/resolve"
    
    resolver := resolve.New()
  6. Use the Subfinder Go library

    dev

    Developers can integrate Subfinder's enumeration capabilities into their own Go applications by using the pkg/runner package. The core workflow involves:

    1. Parsing options using runner.ParseOptions().
    2. Initializing a new runner instance with runner.NewRunner(options).
    3. Executing the enumeration via newRunner.RunEnumeration().

    Note: The runner attempts to increase OS file descriptors automatically via the fdmax package to handle high concurrency.

    package main
    
    import (
    	"github.com/projectdiscovery/subfinder/v2/pkg/runner"
    	"github.com/projectdiscovery/gologger"
    )
    
    func main() {
    	// 1. Parse command line flags and config files
    	options := runner.ParseOptions()
    
    	// 2. Create a new runner instance
    	newRunner, err := runner.NewRunner(options)
    	if err != nil {
    		gologger.Fatal().Msgf("Could not create runner: %s\n", err)
    	}
    
    	// 3. Run the enumeration
    	err = newRunner.RunEnumeration()
    	if err != nil {
    		gologger.Fatal().Msgf("Could not run enumeration: %s\n", err)
    	}
    }
  7. Use DefaultResolvers for DNS resolution

    dev

    The DefaultResolvers variable provides a pre-defined list of reliable public DNS resolvers (including Cloudflare, Google, Quad9, Yandex, and OpenDNS) that can be assigned to a Resolver instance.

    var DefaultResolvers = []string{
    	"1.1.1.1:53",        // Cloudflare primary
    	"1.0.0.1:53",        // Cloudflare secondary
    	"8.8.8.8:53",        // Google primary
    	"8.8.4.4:53",        // Google secondary
    	"9.9.9.9:53",        // Quad9 Primary
    	"9.9.9.10:53",       // Quad9 Secondary
    	"77.88.8.8:53",      // Yandex Primary
    	"77.88.8.1:53",      // Yandex Secondary
    	"208.67.222.222:53", // OpenDNS Primary
    	"208.67.220.220:53", // OpenDNS Secondary
    }
  8. Use the Resolver struct

    dev

    The Resolver struct is used for resolving DNS names. It contains:

    • DNSClient: A pointer to a dnsx.DNSX instance used for the actual resolution logic.
    • Resolvers: A slice of strings representing the DNS server addresses (e.g., "1.1.1.1:53") to be used during resolution.
    type Resolver struct {
    	DNSClient *dnsx.DNSX
    	Resolvers []string
    }