You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Update Dockerfile, main.go, and tests to enhance functionality and validation. Added output file support with -o flag, DNS retry mechanism with -retries flag, and graceful shutdown on SIGINT/SIGTERM. Implemented domain and DNS server validation. Updated tests for new features and improved error handling.
Copy file name to clipboardExpand all lines: docs/ARCHITECTURE.md
+25-17Lines changed: 25 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,8 +16,6 @@ This architecture is designed to be efficient by performing multiple DNS lookups
16
16
17
17
## 2. Key Components / Modules
18
18
19
-
*(Details to be added regarding components, data flow, concurrency, etc.)*
20
-
21
19
### 2.1. Argument Parsing
22
20
23
21
***Purpose**: This component is responsible for processing the command-line arguments provided by the user when `subenum` is executed. It extracts the target domain, the path to the wordlist file, the desired number of concurrent workers, and the DNS lookup timeout.
@@ -29,9 +27,11 @@ This architecture is designed to be efficient by performing multiple DNS lookups
29
27
*`flag.Bool("v", false, "Enable verbose output")`: Defines the verbose flag.
30
28
*`flag.Bool("progress", true, "Show progress during scanning")`: Defines the progress reporting flag.
31
29
*`flag.Bool("version", false, "Show version information")`: Defines the version flag.
30
+
*`flag.String("o", "", "Write results to file")`: Defines the output file flag.
31
+
*`flag.Int("retries", 1, "Number of DNS retry attempts")`: Defines the retry count flag.
32
32
*`flag.Parse()`: Parses the provided arguments.
33
33
*`flag.Arg(0)`: Retrieves the positional argument (the target domain).
34
-
***Interactions**: The parsed values are used to configure the subsequent components, such as the Wordlist Processing and DNS Resolution Engine. Input validation is also performed to ensure valid values for critical parameters like concurrencyand timeout.
34
+
***Interactions**: The parsed values are used to configure the subsequent components, such as the Wordlist Processing and DNS Resolution Engine. Input validation is performed to ensure valid values for critical parameters like concurrency, timeout, DNS server format (validated via `validateDNSServer`), and domain syntax (validated via `validateDomain`).
35
35
36
36
### 2.2. Wordlist Processing
37
37
@@ -47,15 +47,16 @@ This architecture is designed to be efficient by performing multiple DNS lookups
47
47
48
48
***Purpose**: This is the core component responsible for performing the actual DNS lookup for each constructed subdomain (e.g., `prefix.targetdomain.com`). It determines if a subdomain has a valid DNS record (typically A or CNAME, though the current implementation checks for any successful resolution).
* Function: `resolveDomainWithRetry(domain string, timeout time.Duration, dnsServer string, verbose bool, maxRetries int) bool` — wraps `resolveDomain` with configurable retry logic and exponential backoff between attempts.
51
52
*`net.Resolver{}`: A custom DNS resolver is configured.
52
53
*`PreferGo: true`: Instructs the resolver to use the pure Go DNS client.
53
-
*`Dial func(ctx context.Context, network, address string) (net.Conn, error)`: A custom dial function is provided to control the connection to the DNS server. This allows for setting a specific timeout for the dial operation and for specifying the DNS server to use (currently hardcoded to Google's public DNS `8.8.8.8:53`).
54
+
*`Dial func(ctx context.Context, network, address string) (net.Conn, error)`: A custom dial function is provided to control the connection to the DNS server, using the user-specified `dnsServer` address.
54
55
*`net.Dialer{Timeout: timeout}`: A `Dialer` is created with the user-specified timeout.
55
-
*`d.DialContext(ctx, "udp", "8.8.8.8:53")`: Establishes a UDP connection to the DNS server.
56
+
*`d.DialContext(ctx, "udp", dnsServer)`: Establishes a UDP connection to the configured DNS server.
56
57
*`resolver.LookupHost(context.Background(), domain)`: Performs the DNS lookup for the given domain. It attempts to find A or AAAA records for the host.
57
58
* The function returns `true` if `LookupHost` returns no error (i.e., the domain resolved), and `false` otherwise.
58
-
***Interactions**: This function is called by each worker goroutine. It takes a fully qualified domain name and the timeout durationas input. It outputs a boolean indicating whether the domain resolved successfully. The result is used to decide if the domain should be printed to the console.
59
+
***Interactions**: Workers call `resolveDomainWithRetry`, which delegates to `resolveDomain` with retry logic. It takes a fully qualified domain name, timeout duration, DNS server address, verbose flag, and retry count as input. It outputs a boolean indicating whether the domain resolved successfully. The result is used to decide if the domain should be printed to the console and/or written to the output file.
59
60
60
61
### 2.4. Concurrency Management (Worker Pool)
61
62
@@ -144,8 +145,13 @@ Visually, this can be seen as:
144
145
145
146
### 4.1. User Input Errors
146
147
147
-
***Missing Required Arguments**: When the user doesn't provide a wordlist file (`-w` flag) or a target domain, the tool prints a usage message (`fmt.Println("Usage: subenum -w <wordlist_file> <domain>")`) followed by the description of all flags, and then exits with a non-zero status code (`os.Exit(1)`).
148
-
***Validation**: Currently, the tool performs minimal validation of the input arguments. The domain and wordlist file must be provided, but there is no validation of flag values (e.g., checking if the concurrency level or timeout is a positive number).
148
+
***Missing Required Arguments**: When the user doesn't provide a wordlist file (`-w` flag) or a target domain, the tool prints a usage message followed by the description of all flags, and then exits with a non-zero status code (`os.Exit(1)`).
149
+
***Validation**: The tool validates:
150
+
* Concurrency level and timeout must be positive integers.
151
+
* DNS server must be a valid `ip:port` format with proper IP address and port range (1-65535), validated by `validateDNSServer`.
152
+
* Target domain must conform to DNS naming rules, validated by `validateDomain`.
153
+
* Hit rate (simulation mode) must be 1-100.
154
+
* Retry count must be at least 1.
149
155
150
156
### 4.2. File Operation Errors
151
157
@@ -162,12 +168,14 @@ Visually, this can be seen as:
162
168
***Channel Operations**: The tool uses a channel (`subdomains`) to pass work between the wordlist reading goroutine and the worker goroutines. No explicit error handling is implemented for channel operations, as Go's channel semantics ensure that operations like closing an already closed channel would panic. This is avoided by design in the current implementation.
163
169
***Worker Goroutine Errors**: Each worker goroutine processes DNS lookups independently. If an error occurs within a worker (outside of the expected DNS resolution failures), it can cause the entire goroutine to terminate. The current implementation doesn't have specific handling for such scenarios.
164
170
165
-
### 4.5. Potential Improvements
171
+
### 4.5. Graceful Shutdown
172
+
173
+
The tool listens for `SIGINT` and `SIGTERM` signals. Upon receiving an interrupt, it cancels the work context, drains in-flight workers, and exits cleanly with a summary of results processed so far.
174
+
175
+
### 4.6. Output File Support
176
+
177
+
When the `-o` flag is provided, resolved subdomains are written to the specified file (one per line) in addition to stdout. A mutex protects concurrent writes to both stdout and the output file.
178
+
179
+
### 4.7. Retry Mechanism
166
180
167
-
***Input Validation**: Add more thorough validation of command-line arguments, including:
168
-
* Checking that the concurrency level is positive.
169
-
* Validating that the timeout value is reasonable.
170
-
* Verifying that the domain adheres to DNS naming rules.
171
-
***Verbose Mode**: Implement a verbose mode (e.g., `-v` flag) that would print more information, including errors during DNS lookups, to help with debugging.
172
-
***Graceful Handling of DNS Server Issues**: Add better handling of DNS server problems, possibly including retry mechanisms or fall-back to alternative DNS servers.
173
-
***Progress Reporting**: Provide information about the progress of the enumeration to give the user feedback on long-running scans.
181
+
The `-retries` flag (default: 1) controls how many times each subdomain is attempted before being marked as unresolved. A short backoff delay is applied between retries to handle transient DNS failures.
This tool is provided for **educational and legitimate security testing purposes only**. Users must ensure they have proper authorization before conducting subdomain enumeration on any domains. See the [LICENSE](https://github.com/yourusername/subenum/blob/main/LICENSE) file for detailed terms of use.
91
+
This tool is provided for **educational and legitimate security testing purposes only**. Users must ensure they have proper authorization before conducting subdomain enumeration on any domains. See the [LICENSE](https://github.com/TMHSDigital/subenum/blob/main/LICENSE) file for detailed terms of use.
0 commit comments