Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var CacheFac = func(ctx common.Context, opts Options) *cache.DNSCache { dnsCache := cache.NewDNSCache(opts.Caching.Capacity) ctx.Go(dnsCache.Start) return dnsCache }
CacheFac is the factory method initializing the DNS cache. Overwrite it if you want to modify or use a custom DNS cache.
var ClientFac = func(ctx common.Context, localIPv4 net.IP, localIPv6 net.IP, opts Options, log zerolog.Logger) client.DNSClient { return new(builder.Builder). WithRateLimiting(int64(opts.MaxInflightPerIP), int64(opts.MaxQueriesPerSecondPerIP), opts.RateLimitingTimeout()). WithTCPPoolSize(opts.TCP.PoolSize). WithTCPEphemeralConns(opts.TCP.EphemeralConns). WithTCPTimeout(opts.TCP.Timeout()). WithTCPDialTimeout(opts.TCP.DialTimeout()). WithUDPTimeout(opts.UDPTimeout()). WithEDNSBufferSize(opts.UDP.BufferSize). UseTCPKeepAlive(opts.TCP.UseKeepAlive). WithTCPIdlePeriod(opts.TCP.IdlePeriod()). WithUDPPoolSize(opts.UDP.PoolSize). WithLocalIPs(localIPv4, localIPv6). WithLogger(log). Build(ctx) }
ClientFac is the factory method initializing the DNS client. Overwrite it if you want to modify or change the DNS client that is used.
var DefaultOptions = Options{ Input: InputConfig{ Path: "", Format: "csv", CSVColumnIndex: 1, CSVSeparator: ",", Offset: 0, Len: math.MaxUint, BatchSize: 1, PSLPath: "", }, Output: OutputConfig{ Path: "../out", FileSize: 100, Zip: "", Format: "json", ParallelFiles: 1, }, Retry: RetryConfig{ MaxRetries: 2, Backoff: "Exponential", }, Caching: CachingConfig{ Capacity: math.MaxUint64, InfraCapacity: math.MaxUint64, InfraTTLInSeconds: 300, InfraDumpFile: "", }, ResolutionTimeoutInSeconds: 3600, MaxQueriesPerResolution: 10_000_000, MemoryLimitInGB: -1, Loglevel: "info", Logfile: "", MaxQueriesPerSecondPerIP: 50, MaxInflightPerIP: 10, RateLimitingTimeoutInSeconds: 60, IPV6Only: false, IPV4Only: false, UDP: UDPConfig{ Disable: false, TimeoutInMs: 5000, BufferSize: 1232, PoolSize: 300, }, TCP: TCPConfig{ Disable: false, PoolSize: 300, EphemeralConns: 100, IdlePeriodInMs: 30000, TimeoutInMs: 5000, DialTimeoutInMs: 5000, UseKeepAlive: false, }, MaxParallelism: 400, MaxBatchParallelism: 150, DoNotScanList: "", DoNotScanListReloadIntervalInSeconds: 600, EnableICMP: false, ICMPOutPath: "", WarmUp: false, GatherDNSSEC: true, MaxCNAMEDepth: 64, TrustedZoneNSCount: 2, RootServers: []resolver.NameServerSeed{ { Name: "a.root-servers.net.", IPVersion4: "198.41.0.4", IPVersion6: "2001:503:ba3e::2:30", }, { Name: "b.root-servers.net.", IPVersion4: "170.247.170.2", IPVersion6: "2801:1b8:10::b", }, { Name: "c.root-servers.net.", IPVersion4: "192.33.4.12", IPVersion6: "2001:500:2::c", }, { Name: "d.root-servers.net.", IPVersion4: "199.7.91.13", IPVersion6: "2001:500:2d::d", }, { Name: "e.root-servers.net.", IPVersion4: "192.203.230.10", IPVersion6: "2001:500:a8::e", }, { Name: "f.root-servers.net.", IPVersion4: "192.5.5.241", IPVersion6: "2001:500:2f::f", }, { Name: "g.root-servers.net.", IPVersion4: "192.112.36.4", IPVersion6: "2001:500:12::d0d", }, { Name: "h.root-servers.net.", IPVersion4: "198.97.190.53", IPVersion6: "2001:500:1::53", }, { Name: "i.root-servers.net.", IPVersion4: "192.36.148.17", IPVersion6: "2001:7fe::53", }, { Name: "j.root-servers.net.", IPVersion4: "192.58.128.30", IPVersion6: "2001:503:c27::2:30", }, { Name: "k.root-servers.net.", IPVersion4: "193.0.14.129", IPVersion6: "2001:7fd::1", }, }, QueryFor: QueryConfig{ OnFullNameResolved: []qmin2.QuestionTemplate{ { NameTemplate: "{name}", Type: client.TypeA, Class: client.ClassINET, }, { NameTemplate: "{name}", Type: client.TypeAAAA, Class: client.ClassINET, }, }, }, }
var InfraCacheFac = func(ctx common.Context, log zerolog.Logger, opts Options) *cache.InfraCache { var backoff cache.Backoff if strings.EqualFold(opts.Retry.Backoff, "exponential") { backoff = cache.ExponentialBackoff{ Min: time.Second, Max: 30 * time.Second, Factor: 1.8, } } if strings.EqualFold(opts.Retry.Backoff, "constant") { backoff = cache.ConstantBackoff{ Value: 20 * time.Second, } } if strings.EqualFold(opts.Retry.Backoff, "values") { backoff = cache.ValuesBackoff{ Values: opts.Retry.BackoffValues(), } } infraCache := cache.NewInfraCache(opts.Caching.InfraTTL(), opts.Caching.InfraCapacity, backoff, log) ctx.Go(infraCache.Start) ctx.OnDone(infraCache.Stop) return infraCache }
InfraCacheFac is the factory initializing the infrastructure cache on startup
var LogFac = func(opts Options) (zerolog.Logger, func() error) { zerolog.SetGlobalLevel(zerolog.Disabled) if strings.EqualFold(opts.Loglevel, "debug") { zerolog.SetGlobalLevel(zerolog.DebugLevel) } if strings.EqualFold(opts.Loglevel, "info") { zerolog.SetGlobalLevel(zerolog.InfoLevel) } if strings.EqualFold(opts.Loglevel, "warn") { zerolog.SetGlobalLevel(zerolog.WarnLevel) } if opts.Logfile != "" { logFile, logFileErr := os.OpenFile( opts.Logfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664, ) if logFileErr != nil { panic(logFileErr) } return zerolog.New(logFile).Level(zerolog.GlobalLevel()).With().Timestamp().Logger(), logFile.Close } return zerolog.New(os.Stderr).Level(zerolog.GlobalLevel()).With().Timestamp().Logger(), func() error { return nil } }
var PreResolveHook = func(ctx context.Context, batch []resolver.TaggedDomainName) []resolver.TaggedDomainName {
return batch
}
PreResolveHook is invoked right before the call to resolve. Allows modifying the target list last-minute.
var ResolverFac = func(log zerolog.Logger, worker resolver.Worker, strategy resolver.Strategy, opts Options) resolver.Resolver { return resolver.New(worker, strategy, opts.RootServers...). UseAllNameServerIPs(true). GatherDNSSEC(opts.GatherDNSSEC). DisableIPv4(opts.IPV6Only). DisableIPv6(opts.IPV4Only). FollowCNAMEsToDepth(opts.MaxCNAMEDepth). WithMaxQueries(opts.MaxQueriesPerResolution). LogTo(log) }
ResolverFac is the factory method initializing the resolver Overwrite it if you want to modify or change the resolver logic.
var StrategyFac = func(opts Options) resolver.Strategy { return qmin.New(). AddModule(opts.InitModules()...). TrustTLDs(opts.TrustAllTLDs). TrustZones(opts.GetTrustedZones()). TrustedNameserverCount(opts.TrustedZoneNSCount) }
StrategyFac is the factory method initializing the resolution strategy. Overwrite it if you want to inject a custom strategy into the resolver
var WorkerFac = func(ctx common.Context, client client.DNSClient, cache *cache.DNSCache, infraCache *cache.InfraCache, opts Options, log zerolog.Logger) resolver.Worker { worker := resolver.NewWorker(client, cache, infraCache, opts.Retry.MaxRetries) if opts.TCP.Disable { worker.DisableTCP() } if opts.UDP.Disable { worker.DisableUDP() } ctx.Go(func() { worker.Dequeue(ctx) }) return worker }
WorkerFac is the factory initializing the request worker
Functions ¶
Types ¶
type CachingConfig ¶
type CachingConfig struct {
// Capacity controls the number of items that are allowed in the DNS message cache.
// If the capacity is reached, old entries are evicted if new ones are added
Capacity uint64
// InfraCapacity controls the number of items that are allowed in the infrastructure cache.
// If the capacity is reached, old entries are evicted if new ones are added
InfraCapacity uint64
// InfraTTLInSeconds is the default time-to-live of items in the infrastructure cache.
// This setting also limits the amount of time that a server can be cached as dead/unresponsive.
// Recommended value is 300 (5 minutes)
InfraTTLInSeconds uint
// InfraDumpFile is a path to a file to which evicted infrastructure cache entries are written
InfraDumpFile string
}
CachingConfig contain all settings related to caching
func (CachingConfig) InfraTTL ¶
func (opts CachingConfig) InfraTTL() time.Duration
type InputConfig ¶
type InputConfig struct {
// Format can currently be either CSV or IPRange
Format string
// Path to the input file
Path string
// CSVColumnIndex specifies the column of the csv input file that contains the domain names.
// Only valid if Format=CSV
CSVColumnIndex int
// CSVSeparator specifies the separator for the CSV. Default is comma (,). Only single characters are allowed.
// Only valid if Format=CSV
CSVSeparator string
// Offset specifies the number of entries that are skipped from the beginning of the input list.
Offset uint
// Len specifies the number of entries that are read from the list.
// E.g. if you use a top million list as input and specify
// Offset=1000, Len=200, you will scan the entries at index 1000-1200
Len uint
// BatchSize can reduce storage needs and increase resolution speed if your target list contains domains
// that share the same second level domain. E.g. a.x.example.com, b.example.com and example.com.
// The more labels the batch shares, the better.
// Batching only happens if the input contains consecutive runs of domains that share the same
// second level domain. In that case, the resolver will read at most BatchSize items and put
// them into the same resolution. Batched entries are written into the same line of output.
BatchSize uint
// Path to a public suffix list. Needed for batching.
PSLPath string
}
InputConfig contains the settings that control the input
type MetricsConfig ¶
type MetricsConfig struct {
// EndpointPort is the port under which the prometheus endpoint will be exposed
EndpointPort int
// ServerCrtPath the path to the CER file for enabling HTTPS
ServerCrtPath string
// ServerKeyPath is the path to the KEY file for enabling HTTPS on the metrics endpoint
ServerKeyPath string
// PasswordChecksum and UserNameChecksum enable basic auth.
// PasswordChecksum contains the hex-encoded sha256 checksum of the password as provided by
// a := sha256.Sum256([]byte("the password"))
// fmt.Println(hex.EncodeToString(a[:]))
PasswordChecksum string
// PasswordChecksum and UserNameChecksum enable basic auth.
// PasswordChecksum contains the hex-encoded sha256 checksum of the username as provided by
// a := sha256.Sum256([]byte("the username"))
// fmt.Println(hex.EncodeToString(a[:]))
UserNameChecksum string
// If FilePath is set, metrics will be reported periodically to the given text file
FilePath string
}
MetricsConfig contains the configuration for the metrics instrumentation So far, metrics can be exposed via an HTTP(s) endpoint and protected by basic-auth. When using basic auth, make sure to also use HTTPS.
In the future we could support Client-Certificate authentication or OAuth (The prometheus scraper had some trouble with the client cert)
type Options ¶
type Options struct {
// Input determines how to read the input (aka target list)
Input InputConfig
// Output determines how to write the output.
Output OutputConfig
// Retry specifies the retry behavior
Retry RetryConfig
// Caching specifies the cache behavior.
Caching CachingConfig
// MemoryLimitInGB sets the amount of RAM that can be used, before parallelism is reduced
// in order to reduce the memory footprint temporarily and avoid an OOM exception.
// Negative values disable this feature.
MemoryLimitInGB int
// ResolutionTimeoutInSeconds is the max time that the resolution of a single domain (or batch) is allowed to take
ResolutionTimeoutInSeconds uint
// MaxQueriesPerResolution is the max number of queries that are allowed to be sent for a single domain (or batch)
MaxQueriesPerResolution uint
// Connectivity
TCP TCPConfig
UDP UDPConfig
// MaxQueriesPerSecondPerIP sets the rate limit for queries per second per IP.
// If set to N, the resolver will be able to send apx. N queries to an IP per second,
// unless the maximum number of inflight queries (MaxInflightPerIP) would be exceeded.
MaxQueriesPerSecondPerIP int
// MaxInflightPerIP sets the maximum number of queries that are allowed to be in-flight at the same time per IP.
// If set to N, the resolver will never allow more than N queries inflight per unique IP.
// It is used in addition to MaxQueriesPerSecondPerIP to avoid overloading servers that are slow to respond so
// A good choice for this parameter depends on your latency and should be determined experimentally.
MaxInflightPerIP int
// RateLimitingTimeoutInSeconds sets the time that the resolver will allow queries to be delayed in the rate-limiter.
// After this duration, a query will time out (will not be send)
// If you chose a reasonable large value (e.g. 120s) and still see timeouts, this is most likely caused by hotspots.
// Hotspots can occur e.g. by just scanning a specific infrastructure, or not randomizing your input.
// In order to resolve this, either use input batching, reorder/randomize your target list or reduce the parallelism of the scan (MaxParallelism, MaxBatchParallelism).
RateLimitingTimeoutInSeconds int
// IPV6Only instructs the resolver to only use IPv6.
IPV6Only bool
// IPV4Only instructs the resolver to only use IPv4.
IPV4Only bool
// Level to log to. Currently 'debug', 'info', 'warn' are supported.
Loglevel string
// Logfile is the path to the logfile.
Logfile string
// Metrics contains the configuration for the metrics exporting.
Metrics MetricsConfig
// If set, loads the cache dump before starting the scan
CacheDumpFile string
// ProgressDumpFile writes a file with indexes from the target list that
// have already been scanned. Useful for continuing crashed scans.
// On resume, indexes that are present in the file will be skipped.
ProgressDumpFile string
// MaxParallelism is the maximum number of parallel resolutions.
// This is independent of batch processing.
// If batching is enabled, also consider setting MaxBatchParallelism to limit the number of batches.
MaxParallelism uint
// MaxBatchParallelism is the maximum number of parallel batches that can be resolved if batching is enabled in Input.
// Without batching (batchSize=1), this parameter has the same effect as MaxParallelism.
// The resolver adhere to the minimum of MaxParallelism and MaxBatchParallelism.
// Example: If MaxParallelism=10 and MaxBatchParallelism=2, there can be at most two batches inflight, totalling 10 resolutions.
MaxBatchParallelism uint
// DoNotScanList contains a list to the file containing the IPs and Domainnames that should not be scanned.
// It will be periodically reloaded every DoNotScanListReloadIntervalInSeconds seconds.
DoNotScanList string
// DoNotScanListReloadIntervalInSeconds is the interval in seconds in which the DoNotScanList is reloaded.
DoNotScanListReloadIntervalInSeconds int
// EnableICMP enables listening to ICMP messages.
// When receiving a DST_UNREACHABLE message, the resolver will cache the server as unreachable for
// the duration specified in CachingConfig.InfraTTLInSeconds
EnableICMP bool
// ICMPOutPath sets the path to a file to which all received ICMP messages are written.
ICMPOutPath string
// WarmUp adds a small delay when enqueueing the first between the first MaxParallelism names.
// It reduces the load on the TLD and Root servers during ramp-up by filling the cache before going full speed.
WarmUp bool
// GatherDNSSEC sets the DO bit in all queries to request DNSSEC related records.
GatherDNSSEC bool
// QueryFor specifies which queries to ask for.
QueryFor QueryConfig
// RootServers contains the root server glue.
RootServers []resolver.NameServerSeed
// Modules contains a list of module names that will be initialized.
Modules []string
// MaxCNAMEDepth sets the maximum depth to which CNAMES will be followed.
// Set to 0 to disable following CNAMES.
MaxCNAMEDepth uint
// TrustedZones is a list of domains that are trusted.
// Works like TrustAllTLDs, but only for the specified domains.
// Zones do not need to be a TLD, but can be any name.
TrustedZones []string
// TrustAllTLDs controls whether queries for the top level domain are send to all nameservers.
// If true, the resolver will NOT send queries to all TLD nameservers.
// It will trust that the all servers respond correctly and consistently and thus only send the query to a single nameserver.
TrustAllTLDs bool
// TrustedZoneNSCount specifies the number of nameservers that will be asked for a trusted zone during a resolution.
// For example, if set to 1, a random nameserver will be queried (on all IP addresses)
// Even though the idea of trusted zones is, that they are very reliable and one need not to query all nameservers,
// a value of 2 is recommended to allow for some backup in case one name server still fails unexpectedly or
// there are connectivity problems to that specific subnet.
TrustedZoneNSCount int
}
func (Options) GetTrustedZones ¶
func (opts Options) GetTrustedZones() []model.DomainName
func (Options) InitModules ¶
func (Options) RateLimitingTimeout ¶
func (Options) UDPTimeout ¶
type OutputConfig ¶
type OutputConfig struct {
// Path is the path to which the output is written
Path string
// OutputFileSize is the number of target domains per file.
FileSize uint
// Format defines the kind of outputter that is used.
// Currently supported: 'json' and 'protobuf'
Format string
// Zip controls the compression method of the output files.
// Supported format: 'algorithm' or 'algorithm:level'
// Currently supported algorithms: 'none', 'zst', 'gzip', 'deflate'
// Currently supported compression levels: 'fastest', 'fast', 'better'
// Unless compatibility demands a certain format, it is recommended to use
// 'zst' as it provides more compression and faster speed than the others.
// When using compression levels other than 'fastest', make sure your machine
// can write the data fast enough. Otherwise, memory will fill up and overflow.
Zip string
// ParallelFiles is the number of files that can be written (open) in parallel
ParallelFiles uint32
}
OutputConfig contains the settings that control the output
type QueryConfig ¶
type QueryConfig struct {
// OnFullNameResolved contains queries that will be send when a full name is resolved.
// That includes, resolved name servers, the original name, and names enqueued by other modules such as mail servers.
OnFullNameResolved []qmin2.QuestionTemplate
// OnZoneCreated is triggered whenever a new zone is created.
// This is the place to ask questions that you want to ask once per zone, e.g. SOA records.
OnZoneCreated []qmin2.QuestionTemplate
}
type RetryConfig ¶
type RetryConfig struct {
// Max number of retries done
MaxRetries uint
// Backoff strategy applied.
// Currently supported 'Exponential' or 'Constant' or 'Values'
// If 'Values' is used, specify the sequence in BackoffValuesInMs
Backoff string
// BackoffValues is a fixed sequence of values that will be used for backoff.
// Only applies if Backoff=Values
BackoffValuesInMs []int
}
RetryConfig contains the settings that control the retrying
func (RetryConfig) BackoffValues ¶
func (opts RetryConfig) BackoffValues() []time.Duration
type ScanProgress ¶
type ScanProgress struct {
Count uint
Log zerolog.Logger
Missing map[uint]any
// contains filtered or unexported fields
}
ScanProgress is a utility type that tracks which domains are currently being resolved. on crash, it helps to determine from where the scanning should resume.
func (*ScanProgress) CanSkip ¶
func (p *ScanProgress) CanSkip(idx uint) bool
func (*ScanProgress) Close ¶
func (p *ScanProgress) Close()
func (*ScanProgress) Load ¶
func (p *ScanProgress) Load(in io.Reader)
Load loads the dump from a file and creates an index of domains that have not been scanned yet.
func (*ScanProgress) TrackFinished ¶
func (p *ScanProgress) TrackFinished(idx uint)
func (*ScanProgress) WriteWorker ¶
func (p *ScanProgress) WriteWorker(out io.Writer)
type TCPConfig ¶
type TCPConfig struct {
// Disable turns off TCP. Scanning will be done using UDP only.
Disable bool
// PoolSize is the size of the TCP connection pool
PoolSize uint16
// EphemeralConns is the max. number of open TCP ephemeral connections,
// that is, connections which are used for one exchange and closed afterwards.
// If EphemeralConns are available, the client will use them as a fallback mechanism
// if the pool is exhausted or the pooled conns are faulty.
EphemeralConns uint16
// IdlePeriodInMs is the period after which a TCP connection is considered idle by the pool
// and closing is initiated.
IdlePeriodInMs uint
// TimeoutInMs is the timeout for read and write operations on the connection
TimeoutInMs uint
// DialTimeoutInMs is the timeout for opening a TCP connection
DialTimeoutInMs uint
// If true, the EDNS0-TCP Keepalive option (rfc7828) is sent with a value
// that corresponds to IdlePeriodInMs. Answers from servers are parsed for
// keepalive-responses and the IdlePeriod of connections in the pool is adjusted
// to respect the servers choice.
UseKeepAlive bool
}
TCPConfig contains the config for TCP connectivity
func (TCPConfig) DialTimeout ¶
func (TCPConfig) IdlePeriod ¶
type UDPConfig ¶
type UDPConfig struct {
// Disable turns off UDP. Scanning will be done using TCP only.
Disable bool
// PoolSize is the size of the UDP socket pool
PoolSize uint16
// TimeoutInMs is the timeout for read and write operations on the connection
TimeoutInMs uint
// BufferSize sets the desired buffer size for UDP packets.
// It will be communicated via EDNS0 to the server.
BufferSize uint16
}
UDPConfig contains the config for UDP connectivity