Important
Authorized use only. Only scan domains you own or have explicit written permission to test. Unauthorized scanning may violate applicable laws. Users are solely responsible for compliance with all applicable laws and regulations.
| Module | Description |
|---|---|
| Worker Pool | Spawn N goroutines for parallel DNS resolution with a configurable concurrency ceiling |
| DNS Engine | Resolve subdomains against any DNS server with per-query timeouts and retry backoff |
| Wildcard Detection | Double-probe check before scanning; aborts early unless -force is set |
| Graceful Shutdown | Trap SIGINT/SIGTERM, drain in-flight workers, flush partial results |
| Input Validation | RFC-compliant domain syntax and strict ip:port format enforcement |
| Wordlist Dedup | Deduplicate wordlist entries in a single pass before scanning begins |
| Simulation Mode | Generate synthetic DNS results at a configurable hit rate — zero network I/O |
| Output Pipeline | Resolved domains to stdout (pipe-clean); progress and diagnostics to stderr |
| Interactive TUI | Form-based config and live-scrolling results via -tui; session values persisted |
flowchart LR
subgraph Input
A[Wordlist File] -->|"dedup + load"| B(Entry Slice)
C[CLI Flags / TUI Form] --> D(Argument Parser)
end
subgraph PreScan
D --> W{Wildcard\nDetection}
W -->|"no wildcard / -force"| E
end
subgraph Engine
B --> E{Worker Pool\nN Goroutines}
E -->|subdomain.domain| F[DNS Resolver]
F -->|retry + backoff| F
G[Context] -->|cancel| E
G -->|timeout| F
end
subgraph OutputLayer ["Output"]
F -->|resolved| H["stdout (results)"]
F -->|resolved| I[Output File]
E -->|atomic counters| J["stderr (progress)"]
end
K[SIGINT / SIGTERM] -->|cancel| G
Prerequisites: Go 1.22+ · Git · Make (optional) · Docker (optional)
Build from source
git clone https://github.com/TMHSDigital/subenum.git
cd subenum
go build -buildvcs=false -o subenumPre-built binaries
Download the appropriate binary for your platform from the Releases page.
Platforms: Linux (amd64, arm64) · macOS (amd64, arm64) · Windows (amd64)
SHA-256 checksums are provided alongside each binary.
Docker
docker build -t subenum .
docker run --rm -v $(pwd)/data:/data subenum -w /data/wordlist.txt example.comOr with Compose:
docker compose run subenumMake targets
make build # compile binary
make test # run test suite with race detector
make lint # run golangci-lint
make simulate # safe run — no DNS queries
make tui # launch interactive TUI
make docker-build # build Docker image
make help # list all targets| Flag | Default | Description |
|---|---|---|
-w <file> |
— | Wordlist file, one prefix per line (required) |
-t <n> |
100 |
Concurrent worker goroutines |
-timeout <ms> |
1000 |
Per-query DNS timeout in milliseconds |
-dns-server <ip:port> |
8.8.8.8:53 |
DNS server address (validated on startup) |
-attempts <n> |
1 |
DNS resolution attempts per subdomain (1 = no retry) |
-force |
false |
Continue scanning even if wildcard DNS is detected |
-o <file> |
— | Write results to file in addition to stdout |
-v |
false |
Verbose output: IPs, timings, per-query detail (stderr) |
-progress |
true |
Live progress line on stderr |
-simulate |
false |
Simulation mode: no real DNS queries |
-hit-rate <n> |
15 |
Simulated resolution rate, percent (1–100) |
-tui |
false |
Launch the interactive Terminal UI |
-version |
— | Print version and exit |
-retries <n> |
— | Deprecated — alias for -attempts, prints a warning |
Note
Wildcard DNS is detected automatically before scanning begins. If the target resolves wildcard records, the tool exits with a warning — all subdomains would match, making results meaningless. Pass -force to override.
Caution
Simulation mode (-simulate) generates synthetic results and performs zero network I/O. Do not confuse simulated output with real DNS data.
subenum -w <wordlist> [flags] <domain>Examples
Basic scan
./subenum -w wordlist.txt example.comHigh-throughput with Cloudflare DNS, saving results
./subenum -w wordlist.txt -t 300 -timeout 500 -dns-server 1.1.1.1:53 -o results.txt example.comResilient scan for flaky networks
./subenum -w wordlist.txt -attempts 3 -timeout 2000 example.comPipe-friendly — only resolved subdomains on stdout
./subenum -w wordlist.txt example.com | cut -d' ' -f2 | your-takeover-scannerForce scan on a wildcard domain
./subenum -w wordlist.txt -force example.comSimulation — zero network I/O
./subenum -simulate -hit-rate 20 -w examples/sample_wordlist.txt example.comPress Ctrl+C at any time to abort. In-flight queries drain and partial results are flushed before exit.
./subenum -tuiNo flags required. Fill in the form and press ctrl+r to start scanning. Last-used values are saved to ~/.config/subenum/last.json and restored on next launch.
TUI keyboard reference
| Key | Action |
|---|---|
tab / shift+tab / ↑ ↓ |
Navigate fields |
space |
Toggle Simulate / Force |
ctrl+r |
Start scan |
ctrl+c |
Abort scan (scan view) / quit (form) |
r |
New scan — restores last-used values |
q |
Quit after scan completes |
| Layer | Components |
|---|---|
| Core Engine | Go 1.22 · net.Resolver · context · sync/atomic |
| Concurrency | goroutines · channels · sync.WaitGroup · sync.Mutex |
| TUI | Bubble Tea · Bubbles (textinput, viewport, progress) · Lip Gloss |
| Infrastructure | Docker · Alpine · Make · docker-compose |
| CI/CD | GitHub Actions · CodeQL · Dependabot · golangci-lint v2 |
| Quality | go test -race · gosec · govet · staticcheck |
Project structure
subenum/
├── .github/
│ ├── workflows/
│ │ ├── go.yml # CI: build, test, lint, release
│ │ ├── codeql.yml # Weekly CodeQL security analysis
│ │ └── pages.yml # GitHub Pages deployment
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── dependabot.yml
│ └── PULL_REQUEST_TEMPLATE.md
├── data/
│ └── wordlist.txt # Default wordlist for Docker/Make
├── docs/
│ ├── assets/
│ │ └── tui-form.png # TUI screenshot
│ ├── ARCHITECTURE.md
│ ├── CONTRIBUTING.md
│ ├── DEVELOPER_GUIDE.md
│ ├── docker.md
│ ├── _config.yml
│ └── index.md
├── examples/
│ ├── sample_wordlist.txt
│ ├── advanced_usage.md
│ ├── demo.sh
│ └── multi_domain_scan.sh
├── internal/
│ ├── dns/ # ResolveDomain, CheckWildcard, SimulateResolution
│ ├── output/ # Thread-safe Writer (stdout/stderr separation)
│ ├── scan/ # Scan engine: Config, Event types, Run()
│ ├── tui/ # Bubble Tea UI: form, scan view, session config
│ └── wordlist/ # LoadWordlist (dedup + sanitize)
├── tools/
│ └── wordlist-gen.go
├── main.go # CLI entry point
├── main_test.go
├── go.mod
├── Dockerfile
├── docker-compose.yml
├── Makefile
├── .golangci.yml # golangci-lint v2 configuration
├── CHANGELOG.md
├── SECURITY.md
└── LICENSE # GNU General Public License v3.0
See CONTRIBUTING.md for the pull request workflow and ethical guidelines. See DEVELOPER_GUIDE.md for build setup, testing, and project structure.
