| Crates.io | backdisco |
| lib.rs | backdisco |
| version | 0.3.0 |
| created_at | 2026-01-23 20:41:13.328113+00 |
| updated_at | 2026-01-23 21:38:15.806869+00 |
| description | Discover backend origins from CDN frontends using LLM-assisted pattern analysis and brute force enumeration |
| homepage | |
| repository | |
| max_upload_size | |
| id | 2065432 |
| size | 162,134 |
backDisco is a tool that discovers exposed backend origins from CDN frontends using LLM-assisted pattern analysis and brute force enumeration.
Given a known pattern of CDN frontend and backend hostname pairs, backDisco uses an LLM to identify naming patterns and then applies those patterns to discover additional backend origins from a list of target frontends. It can also perform brute force subdomain enumeration based on extracted patterns.
cargo install backdisco
git clone <repository-url>
cd backdisco
cargo build --release
The binary will be located at target/release/backdisco.
backDisco supports multiple LLM API types with automatic detection:
https://api.openai.com/v1)http://localhost:11434/v1 or http://localhost:11434/api)https://api.anthropic.com/v1)The LLM endpoint URL and model can be specified via command-line arguments:
--llmurl: LLM API base URL (defaults to http://localhost:11434/v1)--model: Model name (if not provided, the tool will fetch available models and prompt for selection)The API type is automatically detected from the URL using pattern matching, so you don't need to specify it manually.
backdisco \
--front "cdn.example.com" \
--back "api.internal.example.com" \
--targets targets.txt
Specify a custom LLM endpoint and model:
backdisco \
--front "cdn.example.com" \
--back "api.internal.example.com" \
--targets targets.txt \
--llmurl "https://api.openai.com/v1" \
--model "gpt-4"
If --model is not specified, the tool will fetch available models and prompt for selection:
backdisco \
--front "cdn.example.com" \
--back "api.internal.example.com" \
--targets targets.txt \
--llmurl "http://localhost:11434/v1"
Extract Subject Alternative Names from target certificates:
backdisco \
--front "cdn.example.com" \
--back "api.internal.example.com" \
--targets targets.txt \
--extract-sans
Enable brute force subdomain enumeration with position-aware expansion:
backdisco \
--front "cdn.example.com" \
--back "api.internal.example.com" \
--targets targets.txt \
--brute \
--llm-expand 5 \
--llm-batch-size 20
The --brute flag enables structured candidate generation that:
backdisco \
--front "cdn.example.com" \
--back "api.internal.example.com" \
--targets targets.txt \
--output results.txt \
--llmurl "http://localhost:11434/v1" \
--model "llama2" \
--extract-sans \
--brute \
--llm-expand 5 \
--llm-batch-size 20 \
--max-depth 3 \
--concurrency 50 \
--timeout 5 \
--gen-wordlist-output candidates.txt \
--verbose 2
| Option | Short | Description |
|---|---|---|
--front |
-f |
Known frontend hostname (required) |
--back |
-b |
Known backend hostname (required) |
--targets |
-t |
File with target frontends, one per line (required) |
--output |
-o |
Output file (defaults to stdout) |
--verbose |
-v |
Verbosity level 0-2 (default: 1) |
--dns-only |
Skip HTTP checks, DNS only | |
--timeout |
HTTP timeout in seconds (default: 5) | |
--concurrency |
Concurrent check limit (default: 50) | |
--extract-sans |
Extract SANs from target certificates and add to target list | |
--no-sans |
Skip SAN extraction (opposite of --extract-sans) | |
--brute |
Enable brute force subdomain enumeration with position-aware expansion | |
--llm-expand |
Number of related words to generate per seed word using LLM (default: 5, 0 to disable) | |
--llm-batch-size |
Batch size for LLM position expansion (default: 20) | |
--max-depth |
Override maximum subdomain depth for brute forcing (default: derived from backend URL) | |
--llmurl |
LLM API base URL (default: http://localhost:11434/v1) | |
--model |
LLM model name (if not provided, will fetch and prompt for selection) | |
--gen-wordlist-output |
Output file for generated candidate list (one hostname per line) |
LLM Configuration:
--llmurl is provided, uses that endpoint; otherwise uses default--model is provided, uses that model; otherwise fetches available models and prompts for selectionPre-flight Check: Verifies connectivity to the LLM endpoint and model availability
Backend Analysis:
Target Loading: Reads target frontends from the specified file
SAN Extraction (optional): Extracts Subject Alternative Names from target certificates to discover additional hosts and wildcard patterns
Pattern Discovery: Queries the LLM to identify naming patterns between the frontend and backend hostnames
Pattern Application: Applies discovered patterns to target frontends to generate backend candidates
Brute Force (optional):
Verification: Tests all candidates via DNS resolution and HTTP/HTTPS checks with configurable concurrency
Output: Reports live backends with DNS and HTTP status information
The tool provides colored output with different verbosity levels:
Example output:
[+] LIVE: api.internal.example.com
DNS: 192.168.1.100
HTTPS: 200 OK
HTTP: 301 Moved Permanently
Given:
cdn.example.comapi.internal.example.comcdn with api.internalApplied to targets:
cdn.target1.com → api.internal.target1.comcdn.target2.com → api.internal.target2.comIf cdn.example.com has a certificate with SANs:
*.internal.example.comapi.internal.example.comadmin.internal.example.comThese will be added to the target list for pattern application.
Backend: api-v2.internal.example.com
["api", "v2", "internal"], base "example.com"["api"] → ["api", "rest", "graphql", "rpc", "service", "gateway"]["v2"] → ["v2", "v1", "v3", "beta", "alpha", "prod"]["internal"] → ["internal", "int", "private", "corp", "internal"]api.v2.internal.example.com, rest.v1.internal.example.com, graphql.prod.int.example.com, etc.example.comThis project is licensed under the MIT License. See the LICENSE file for details.
Contributions are welcome! Please ensure your code follows Rust best practices and includes appropriate error handling.