Skip to content

Commit 8cf97a7

Browse files
committed
Refactor and enhance DNS resolution tool with new features
- Introduced wildcard DNS detection, exiting early unless overridden with `-force`. - Implemented wordlist deduplication, reporting duplicates removed during loading. - Replaced `-retries` flag with `-attempts` for clarity, maintaining backward compatibility with a warning. - Refactored code into `internal/dns`, `internal/output`, and `internal/wordlist` packages for better organization. - Updated output handling to direct results to stdout and diagnostics to stderr, improving pipe compatibility. - Bumped version to 0.4.0 and documented changes in CHANGELOG.md.
1 parent 9aa4a8f commit 8cf97a7

File tree

13 files changed

+738
-443
lines changed

13 files changed

+738
-443
lines changed

README.md

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
[![CodeQL](https://img.shields.io/github/actions/workflow/status/TMHSDigital/subenum/codeql.yml?label=CodeQL&style=for-the-badge)](https://github.com/TMHSDigital/subenum/actions/workflows/codeql.yml)
1313
[![Release](https://img.shields.io/github/v/release/TMHSDigital/subenum?style=for-the-badge)](https://github.com/TMHSDigital/subenum/releases)
1414

15-
`Concurrent Workers` · `Context-Aware Cancellation` · `Retry with Backoff` · `Simulation Mode` · `Zero Dependencies`
15+
`Concurrent Workers` · `Context-Aware Cancellation` · `Retry with Backoff` · `Wildcard Detection` · `Simulation Mode` · `Zero Dependencies`
1616

1717
[Quick Start](#-installation) | [Documentation](./docs) | [Architecture](#-system-architecture) | [Changelog](./logs/CHANGELOG.md)
1818

@@ -30,10 +30,12 @@
3030
| :--- | :--- |
3131
| Worker Pool | Spawn N goroutines for parallel DNS resolution with configurable concurrency ceiling. |
3232
| DNS Engine | Resolve subdomains against any custom DNS server with per-query timeouts and exponential-backoff retries. |
33+
| Wildcard Detection | Double-probe random subdomain check before scanning; exits early unless `-force` is set. |
3334
| Graceful Shutdown | Trap SIGINT/SIGTERM, drain in-flight workers, flush partial results to disk. |
3435
| Input Validation | Enforce RFC-compliant domain syntax and strict IP:port format for DNS server arguments. |
36+
| Wordlist Dedup | Automatically remove duplicate entries from the wordlist before scanning. |
3537
| Simulation Mode | Generate synthetic DNS results at a configurable hit rate without network I/O. |
36-
| Output Pipeline | Stream results to stdout and optionally to a buffered output file simultaneously. |
38+
| Output Pipeline | Stream resolved domains to stdout (pipe-friendly); progress and diagnostics go to stderr. |
3739
| Progress Reporting | Live terminal progress with atomic counters, updated on a 2-second ticker. |
3840

3941
<br>
@@ -47,10 +49,15 @@
4749
```mermaid
4850
flowchart LR
4951
subgraph Input
50-
A[Wordlist File] -->|line-by-line| B(Sanitize + Channel)
52+
A[Wordlist File] -->|"dedup + load"| B(Entry Slice)
5153
C[CLI Flags] --> D(Argument Parser)
5254
end
5355
56+
subgraph PreScan
57+
D --> W{Wildcard\nDetection}
58+
W -->|"no wildcard / --force"| E
59+
end
60+
5461
subgraph Engine
5562
B --> E{Worker Pool\nN Goroutines}
5663
E -->|subdomain.domain| F[DNS Resolver]
@@ -59,10 +66,10 @@ flowchart LR
5966
G -->|timeout| F
6067
end
6168
62-
subgraph Output
63-
F -->|resolved| H[stdout]
69+
subgraph OutputLayer ["Output"]
70+
F -->|resolved| H["stdout (results only)"]
6471
F -->|resolved| I[Output File]
65-
E -->|atomic counters| J[Progress Reporter]
72+
E -->|atomic counters| J["stderr (progress)"]
6673
end
6774
6875
K[SIGINT / SIGTERM] -->|cancel| G
@@ -77,6 +84,9 @@ flowchart LR
7784
> [!IMPORTANT]
7885
> **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.
7986
87+
> [!NOTE]
88+
> **Wildcard DNS detection.** Before scanning, subenum resolves two random subdomains to check for wildcard DNS. If the domain uses wildcard records, the tool exits with a warning (all subdomains would resolve, making results meaningless). Pass `-force` to override and scan anyway.
89+
8090
> [!CAUTION]
8191
> **Simulation mode** (`-simulate`) generates synthetic results and performs zero network I/O. Do not confuse simulated output with real DNS data.
8292
@@ -122,13 +132,15 @@ make help # list all targets
122132
| `-t <n>` | `100` | Concurrent worker goroutines |
123133
| `-timeout <ms>` | `1000` | Per-query DNS timeout in milliseconds |
124134
| `-dns-server <ip:port>` | `8.8.8.8:53` | DNS server address (validated on startup) |
125-
| `-retries <n>` | `1` | Retry attempts per subdomain on failure |
135+
| `-attempts <n>` | `1` | Total DNS resolution attempts per subdomain (1 = no retry) |
136+
| `-force` | `false` | Continue scanning even if wildcard DNS is detected |
126137
| `-o <file>` | -- | Write results to file in addition to stdout |
127-
| `-v` | `false` | Verbose output: IPs, timings, per-query status |
128-
| `-progress` | `true` | Live progress line (disable with `-progress=false`) |
138+
| `-v` | `false` | Verbose output: IPs, timings, per-query status (written to stderr) |
139+
| `-progress` | `true` | Live progress line on stderr (disable with `-progress=false`) |
129140
| `-simulate` | `false` | Simulation mode: no real DNS queries |
130141
| `-hit-rate <n>` | `15` | Simulated resolution rate, percent (1-100) |
131142
| `-version` | -- | Print version and exit |
143+
| `-retries <n>` | -- | **Deprecated:** alias for `-attempts`, prints a warning |
132144

133145
<br>
134146

@@ -157,13 +169,19 @@ subenum -w <wordlist> [flags] <domain>
157169
**Resilient scan for flaky networks:**
158170

159171
```bash
160-
./subenum -w wordlist.txt -retries 3 -timeout 2000 example.com
172+
./subenum -w wordlist.txt -attempts 3 -timeout 2000 example.com
173+
```
174+
175+
**Pipe-friendly output (progress goes to stderr, only results on stdout):**
176+
177+
```bash
178+
./subenum -w wordlist.txt example.com | cut -d' ' -f2 | your-takeover-scanner
161179
```
162180

163-
**Pipe-friendly output:**
181+
**Force scan on wildcard domain:**
164182

165183
```bash
166-
./subenum -w wordlist.txt -progress=false example.com | cut -d' ' -f2 | your-takeover-scanner
184+
./subenum -w wordlist.txt -force example.com
167185
```
168186

169187
**Simulation (zero network I/O):**
@@ -212,12 +230,24 @@ subenum/
212230
│ ├── advanced_usage.md # Scripting and integration patterns
213231
│ ├── demo.sh # Quick demo script
214232
│ └── multi_domain_scan.sh # Batch scanning example
233+
├── internal/
234+
│ ├── dns/
235+
│ │ ├── resolver.go # ResolveDomain, ResolveDomainWithRetry, CheckWildcard
236+
│ │ ├── resolver_test.go # DNS resolution and wildcard detection tests
237+
│ │ ├── simulate.go # SimulateResolution (synthetic DNS)
238+
│ │ └── simulate_test.go # Simulation logic tests
239+
│ ├── output/
240+
│ │ ├── writer.go # Thread-safe output (results→stdout, rest→stderr)
241+
│ │ └── writer_test.go # Output writer tests
242+
│ └── wordlist/
243+
│ ├── reader.go # LoadWordlist (dedup + sanitize)
244+
│ └── reader_test.go # Wordlist loading and dedup tests
215245
├── logs/
216246
│ └── CHANGELOG.md # Versioned release history
217247
├── tools/
218248
│ └── wordlist-gen.go # Custom wordlist generator utility
219-
├── main.go # Entry point: CLI, worker pool, DNS engine
220-
├── main_test.go # Test suite: resolution, validation, I/O
249+
├── main.go # CLI entry point: flag parsing, wiring
250+
├── main_test.go # CLI-level tests: validation, flag logic
221251
├── go.mod # Go module (zero external dependencies)
222252
├── Dockerfile # Multi-stage Alpine build
223253
├── docker-compose.yml # Compose orchestration

0 commit comments

Comments
 (0)