DNS System¶
Amass implements a sophisticated DNS resolution system with multiple resolver pools, intelligent rate limiting, wildcard detection, and caching.
Resolver Architecture¶
Resolver Types¶
| Type | Description | Default QPS |
|---|---|---|
| Baseline | Curated reliable resolvers (Google 8.8.8.8, Cloudflare 1.1.1.1, Quad9 9.9.9.9) | 15 |
| Public | Dynamic pool from public-dns.info with reliability filtering | 5 |
| Custom | User-specified via -r flag |
Configurable |
| Trusted | High-priority resolvers via -tr flag |
15+ |
Rate Limiting¶
The system enforces strict query rate limits per resolver:
Configuration Flags¶
| Flag | Description | Default |
|---|---|---|
-dns-qps |
Maximum total DNS queries per second | Unlimited |
-rqps |
Max QPS per untrusted resolver | 5 |
-trqps |
Max QPS per trusted resolver | 15 |
Wildcard Detection¶
The wildcard detector prevents false positives from catch-all DNS configurations:
Detection Method¶
- Generate random subdomain string
- Query
random-string.target.com - If resolves → domain has wildcard DNS
- Filter subsequent results against wildcard response
DNS Caching¶
Responses are cached respecting TTL values:
| Cache Layer | Storage | TTL |
|---|---|---|
| In-Memory | Session cache | Query duration |
| File | Disk cache | DNS TTL |
| Database | Graph DB | Permanent |
DNS Discovery Handlers¶
The DNS plugin ecosystem includes specialized handlers executed by priority:
| Handler | Priority | Function |
|---|---|---|
| DNS TXT Handler | 1 | Extract TXT record data (SPF, DKIM, etc.) |
| DNS CNAME Handler | 2 | Follow CNAME relationships |
| DNS IP Handler | 3 | Resolve A/AAAA records |
| DNS Subdomain Handler | 4 | Enumerate subdomains |
| DNS Apex Handler | 5 | Analyze root domain records |
| DNS Reverse Handler | 8 | Perform reverse DNS lookups |
DNS Discovery Techniques¶
Subdomain Enumeration¶
Techniques¶
| Technique | Description | Mode |
|---|---|---|
| Brute Forcing | Wordlist-based subdomain guessing | Active |
| NSEC Walking | Exploit DNSSEC NSEC/NSEC3 records | Active |
| Zone Transfer | AXFR queries (rarely successful) | Active |
| Reverse DNS | PTR record lookups from IPs | Active |
| Certificate Transparency | CT log analysis | Passive |
| API Queries | Third-party data sources | Passive |
Brute Force Configuration¶
| Flag | Description |
|---|---|
-brute |
Enable brute forcing |
-w |
Custom wordlist path |
-min-for-recursive |
Minimum discoveries before recursive brute forcing |
-max-depth |
Maximum subdomain label depth |
DNS Resolution Flow¶
sequenceDiagram
participant Plugin
participant Dispatcher
participant RateLimiter
participant Resolver
participant Cache
Plugin->>Dispatcher: DNS Query Request
Dispatcher->>Cache: Check Cache
alt Cache Hit
Cache-->>Plugin: Cached Response
else Cache Miss
Dispatcher->>RateLimiter: Request Slot
RateLimiter-->>Dispatcher: Approved
Dispatcher->>Resolver: Execute Query
Resolver-->>Dispatcher: DNS Response
Dispatcher->>Cache: Store (with TTL)
Dispatcher-->>Plugin: Fresh Response
end
Feedback Loop¶
Discovered assets generate new DNS queries, enabling cascading discovery:
example.com (seed)
│
├─► DNS Resolution → 192.0.2.1
│ └─► Reverse DNS → mail.example.com (new FQDN)
│ └─► DNS Resolution → 192.0.2.10
│
├─► TXT Records → SPF includes mx.example.com
│ └─► DNS Resolution (new FQDN queued)
│
└─► Certificate → SAN: api.example.com
└─► DNS Resolution (new FQDN queued)
Best Practices¶
DNS Performance
- Use trusted resolvers (
-tr) for higher throughput - Set appropriate rate limits to avoid resolver blocks
- Enable caching for repeated queries
- Use passive mode (
-passive) for stealth reconnaissance
Rate Limiting
Aggressive DNS queries can trigger rate limiting or blocks from DNS providers. Always respect the configured QPS limits.
Technical Reference¶
The following diagrams detail DNS internals from the resolver infrastructure and query execution subsystems.
Resolver Pool Architecture¶
graph TB
subgraph "Configuration Layer"
ConfigYAML["config.yaml<br/>Resolver Lists"]
DefaultBaseline["DefaultBaselineResolvers<br/>17 Trusted IPs"]
PublicDNSInfo["public-dns.info<br/>CSV Download"]
end
subgraph "Resolver Pool Management"
BaselinePool["baselineResolvers<br/>78 Trusted Servers<br/>Variable QPS"]
TrustedPool["trusted *pool.Pool"]
PublicPool["PublicResolvers []string"]
end
subgraph "Selection and Execution"
RandomSelector["selectors.NewRandom()<br/>Load Distribution"]
ConnPool["conn.New()<br/>Connection Pool"]
PoolExec["pool.New()<br/>Query Execution"]
end
subgraph "Wildcard Detection"
WildcardDetector["detector *wildcards.Detector<br/>8.8.4.4 Single Server"]
EffectiveTLD["publicsuffix.EffectiveTLDPlusOne()<br/>Domain Extraction"]
end
ConfigYAML --> BaselinePool
DefaultBaseline --> BaselinePool
PublicDNSInfo --> PublicPool
BaselinePool --> TrustedPool
PublicPool --> TrustedPool
TrustedPool --> RandomSelector
RandomSelector --> ConnPool
ConnPool --> PoolExec
WildcardDetector --> EffectiveTLD
PoolExec --> WildcardDetector
DNS Plugin Layer¶
graph TB
subgraph "DNS Plugin Layer"
TXTHandler["dnsTXT Handler"]
CNAMEHandler["dnsCNAME Handler"]
IPHandler["dnsIP Handler"]
PTRHandler["dnsReverse Handler"]
end
subgraph "Support Package"
PerformQuery["support.PerformQuery(name, qtype)"]
QueryLoop["Retry loop (10x)"]
TrustedPool["trusted *pool.Pool<br/>(78 baseline resolvers)"]
WildcardDetector["detector *wildcards.Detector<br/>(8.8.4.4)"]
end
subgraph "Resolve Library"
PoolExchange["pool.Exchange(ctx, msg)"]
RandomSelector["Random resolver selection"]
Connection["TCP/UDP connection"]
NetworkQuery["DNS protocol query"]
end
TXTHandler --> PerformQuery
CNAMEHandler --> PerformQuery
IPHandler --> PerformQuery
PTRHandler --> PerformQuery
PerformQuery --> QueryLoop
QueryLoop --> TrustedPool
TrustedPool --> PoolExchange
QueryLoop --> WildcardDetector
PoolExchange --> RandomSelector
RandomSelector --> Connection
Connection --> NetworkQuery
PerformQuery Execution Flow¶
DNS Query Response Handling¶
Wildcard Response Validation¶
Wildcard Detector Initialization¶
Resolver Configuration Loading¶
graph TB
subgraph "Configuration Loading"
ConfigFile["config.yaml<br/>resolvers: [...]"]
LoadSettings["loadResolverSettings()"]
ConfigFile --> LoadSettings
LoadSettings --> CheckFormat{"Is IP Address?"}
CheckFormat -->|Yes| AddIP["Append to resolversList"]
CheckFormat -->|No| ParsePath["Treat as File Path"]
ParsePath --> LoadFile["loadResolversFromFile()"]
LoadFile --> ParseLines["Split by Newlines"]
ParseLines --> ValidateIP["net.ParseIP() Each Line"]
ValidateIP --> AddIP
AddIP --> Dedupe["stringset.Deduplicate()"]
Dedupe --> Assign["c.Resolvers = resolverIPs"]
end
subgraph "Resolver Management Functions"
SetResolvers["SetResolvers(...)"]
AddResolvers["AddResolvers(...)"]
CalcQPS["CalcMaxQPS()"]
SetResolvers --> AddResolvers
AddResolvers --> CalcQPS
end
Assign --> SetResolvers