Назад к обновлениям
UpdatedAug 28, 2026

vegadns — Updated!

Инструмент на основе Rust для перечисления DNS и обнаружения поддоменов, предназначенный для разведки и оценки безопасности при тестировании на проникновение.

Поделиться

vegadns - subdomain enum and path discovery

license gitlab

vegadns

High-concurrency subdomain enum, passive OSINT, HTTP path discovery, and Java / hidden endpoint extract in one Rust binary.

Sanskrit vega = impetus / velocity. Also the star.

The problem this solves

Subdomain and content-discovery tools split into two camps: slow-but-clean passive OSINT and fast-but-junk-prone DNS brute. vegadns does both in one binary, and it filters the noise (wildcard DNS, soft-404s) that buries massdns and gobuster users in false positives. It is built and benchmarked against massdns, puredns, dnsx, subfinder, altdns, and ZDNS on planted-answer lab suites (see below).

Quick start

git clone [email protected]:WattoCyber/vegadns.git
cd vegadns
cargo build --release
./target/release/vegadns --help

Requires Rust stable. Full CLI reference in the README below or --help.

The shipped product is vegadns from src/ (cargo build --release). There is no Python on the scan path. scripts/*.py are optional peer-bench drivers (massdns / ffuf / subfinder H2H on the same mock) and are excluded from language statistics - see scripts/README.md.

LaneCommandWhat it does
Offlinewordlist / expand / permuteDepth packs, FQDN expand, altdns-class mutate (no network)
Lab DNSmock-serveFixture zone over UDP for peer H2H
Passive OSINTpassivePublic CT / datasets / APIs → in-scope names (no DNS brute)
DNSenumWordlist expand → concurrent UDP resolve → wildcard filter → emit
Live HTTPprobeHost list → concurrent GET → live URLs (httpx-class)
ArchivesharvestWayback CDX → in-scope hosts + subdirectory prefixes
SurfacemapPassive → recurse/permute → resolve → harvest → probe
HTTP pathspathsConcurrent path scan + soft-404 fingerprint filter
EndpointsendpointsJava / source / hidden seed + HTML/JS/robots/sitemap extract

Research pass covered massdns, puredns/shuffledns, dnsx, subfinder, alterx/gotator/altdns, and ZDNS. See docs/RESEARCH.md.

How to read the numbers

We plant a fixed set of real answers (oracle). Every tool gets the same wordlist and the same mock server.

ColumnPlain English
TimeSeconds until the tool finishes (lower is faster)
Real foundHow many planted answers it recovered (higher is better; max = oracle size)
ReportedHow many names/URLs it printed as hits
JunkReported − Real found (noise you still have to triage)
Clean hit rateReal found / Reported. 100% means every printed hit was real

Faster is not always better. A tool can finish first and still bury you in junk. We care about all real answers, almost no junk, then speed.

These are private lab / gym suites plus one public OSINT domain (hackerone.com). Not “fastest on the public internet.” Full raw tables: docs/BENCHMARKS.md. This-revision vegadns-only clocks: docs/feature_timing_cloud.json (python scripts/feature_timing.py).

Benchmarks at a glance

1. DNS lab - find subdomains, ignore wildcard noise

Setup: 500 real subdomains planted. Zone also answers random junk labels (wildcard). Wordlist: 8000 labels. Host: Kali.

toolTimeReal found (of 500)ReportedJunkClean hit rate
vegadns0.18s5005000100%
massdns0.43s50072122169%
gobuster-dns161s000-

Takeaway: vegadns and massdns both found every real name. massdns also printed 221 wildcard lies. vegadns filtered those and finished faster on this suite.

2. DNS stress gym - flaky resolver (latency + packet loss)

Setup: 800 real names. Mock DNS adds 10 ms delay, 5% SERVFAIL, 2% drop. Wordlist: 2000. Host: Kali.

toolTimeReal found (of 800)ReportedJunkClean hit rate
vegadns0.14s8008000100%
massdns0.55s8001700~90047%

Takeaway: vegadns wins wall and clean output on this suite. massdns still dumps ~half junk.

3. Same tool, before vs after hot-path work

Setup: Windows gym-stress, 3000 candidates, same 800 oracle. No peer race. We only compare vegadns to itself.

buildTimeReal foundClean hit rateNames checked / sec
before0.59s800 / 800100%5,047
after (best)0.40s800 / 800100%7,583

Takeaway: ~33% faster, ~50% more names per second, still zero junk. Detail: docs/OPTIMIZATION_BREAKTHROUGHS.md. Later ceiling work (UDP buffers, poll instead of spin, no silent concurrency clamps) is in docs/OPTIMIZATION_CEILING.md.

4. HTTP paths - server lies with “200 OK” on missing pages

Setup: 24 real paths planted (/admin, /api, …). Soft-404: missing paths still return HTTP 200 with a fixed “not found” body. Status-only tools treat those as hits. Wordlist mixes real paths + bait. Same process-wall clock for every tool.

toolTimeReal found (of 24)ReportedJunkClean hit rate
vegadns paths0.032s24240100%
feroxbuster1.03s24613739%

What this means

  1. Every timed tool found all 24 real paths.
  2. ferox also reported 37 fake pages (soft-404 200s).
  3. vegadns fingerprints the lie, drops fakes, prints exactly the 24 real URLs, and finishes faster.

Takeaway: vegadns wins clean output and wall on this fixed Kali suite (body drain + keep-alive reuse; process-wall H2H).

5. Same suites, re-run on Linux cloud host (2026-08-20)

Real adjacent binaries on PATH (massdns, dnsx, puredns, shuffledns, gobuster, ffuf, ferox). Single measured run. Full tables: docs/PEER_BENCH_CLOUD_2026-08-20.md.

DNS gym-stress (800 planted, 2000 labels, 10 ms / 5% SERVFAIL / 2% drop):

toolTimevs vegadnsReal found (of 800)JunkClean hit rateF1
vegadns0.164s1.0×8000100%1.000
massdns0.515s3.1×80090047%0.640
puredns1.211s7.4×80090047%0.640
shuffledns1.435s8.7×80090047%0.640
dnsx6.673s41×79589547%0.639

DNS lab (500 planted, 5000 labels, wildcard zone): vegadns 0.029s / 500/500 / 0 junk vs massdns 0.337s (11.8×, 400 junk) vs dnsx 0.502s (17.5×, 400 junk).

HTTP hard (24 planted, soft-404 200s; process-wall H2H vs peers):

toolTimeReal found (of 24)ReportedJunkClean hit rateF1
ffuf0.132s24603640%0.571
vegadns paths0.239s24240100%1.000
gobuster-dir0.461s23230100%0.979
feroxbuster0.777s24613739%0.565

ffuf wins raw wall and loses the quality race. vegadns is the only timed tool at R=1.0 and P=1.0. In-process hard mock on this revision: 0.025s / 24/24 / 36 soft-404s dropped (no peer process start).

6. Subdomain enum tools (subfinder / amass / assetfinder / findomain)

vegadns does subdomain enum in two lanes: vegadns enum (active wordlist brute) and vegadns passive (OSINT / CT / public datasets, no DNS brute). Full write-up: docs/SUBDOMAIN_ENUM_COMPARE.md.

Active lab (500 planted, 2000 labels): vegadns 0.023s / 500/500 / 0 junk vs findomain-brute 26s (1120×, 1500 junk) vs gobuster-dns 41s / 0 found.

Passive on the same private zone: vegadns / subfinder / amass / assetfinder / findomain all found 0 of 500 (no CT/API data for lab.test).

Passive on hackerone.com (union = 31 in-scope descendants, no brute): vegadns 31 names in 0.339s (100% of union, 0 junk, F1 1.000, 91 names/s) vs assetfinder 10 real / 3 junk / 1.11s vs subfinder 24 / 20.2s vs findomain 13 / 36s vs amass 0.

This revision, vegadns-only (same domain, no peers): complete 31 names / 0.493s (wall = last source); --fast 30 names / 0.055s.

7. Endpoints vs katana; probe vs httpx

Same local fixture (HTML → runtime.js → chunk.js → hidden paths + robots/sitemap). No Chrome. Raw: docs/e2e_http_compare.json. Write-up: docs/E2E_CLOUD_2026-08-20.md.

toolTimeMust-have (5)URLs
vegadns endpoints --no-seed0.009s5/510
vegadns endpoints (java seed pack)2.01s5/511
naive urllib0.023s1/53
katana -jc -kf all -d 3 -c 326.39s1/55

Seeded wall on Python ThreadingHTTPServer is pinned by ~100 404s. Same seed pack on the in-process mock, this revision: 0.053s / 104 req / 9 hits. --no-seed mock: 0.003s / 9 req / 9 hits.

Probe (4-line list, 3 live + 1 dead):

toolTimeLive
vegadns probe0.005s3
httpx0.423s3

8. Public OSINT field check (no DNS brute)

TargetToolTimeIn-scope namesNotes
hackerone.comvegadns0.34s31100% of same-run peer union; 0 junk
hackerone.comsubfinder20.2s (0.58s best earlier)24crt.sh stall on the slow run
tesla.comvegadns0.32s1326Chaos + sub.md + Anubis + THC
tesla.comsubfinder8.38s13271292 overlap; 34 only-vega; 35 only-subfinder
tesla.comvegadns --fast0.40s1301Wall = sub.md that run

vegadns is faster on the domains we timed, with a near-equal tesla count and a different remainder. It does not emit a strict superset of subfinder’s keyed-source farm. Raw: docs/tesla_passive_cloud.json.

9. This revision - every command (vegadns-only)

Linux cloud host, target/release/vegadns, 2026-08-20. Process wall unless noted. Quality floors held where an oracle exists.

FeatureTimeResult
--help / wordlist list / expand file0.001-0.002sprocess-start floor
wordlist emit tiny / medium0.002s / 0.005s273 / 5038 labels
permute --max 50000.005s5000 lines
enum lab mock (25k / 500)0.091s (engine 0.067s)500/500, 0 junk, ~425k qps
enum gym-stress 2k (10 ms / 5% / 2%)0.085s (engine 0.082s)800/800, 0 junk
paths hard mock0.025s (engine 0.023s)24/24, 36 soft-404s dropped
passive hackerone.com0.493s31 names (wall = last source)
passive --fast hackerone.com0.055s30 names
probe local HTTP0.003s1 live
endpoints --mock-crawl0.053s104 req, 9 hits, 0 err
endpoints --mock-crawl --no-seed0.003s9 req, 9 hits
map mock (no passive/harvest/probe)0.058s10 names, 1 round
harvest hackerone.com Wayback8.008sfailed (archive.org CDX error / timeout)

expand via bash -lc stdin is ~0.20s - that is shell+pipe cost. Native expand on a file is 1-2 ms.

10. Test gates (this revision)

GateResult
cargo test --release --offline141 passed, 0 failed (lib 81 + cli 3 + lab 2 + logic 7 + mutation 24 + paths 5 + extra 17 + scrutinize 2)
python scripts/gherkin_run.py4/4 scenarios
python scripts/paths_suite.pyPASS, 8/8 hits, two-run path set stable

Build

cargo build --release

Binary: target/release/vegadns (.exe on Windows).

Requires a recent Rust toolchain. No massdns dependency for the binary itself.

Output model: stdout = results only (pipe-safe). stderr = ferox-class human UI (ASCII banner, scan-config panel, [INF]/[OK ]/[WRN] tags, live [####>---] progress on TTY, boxed complete stats). Color when TTY and NO_COLOR unset. Use -q / --quiet to silence the UI; --quiet-names keeps stderr stats but does not reprint names.

Quick start

Offline mocks (copy-paste)

# Wordlist packs (no network)
vegadns wordlist list
vegadns wordlist emit tiny | wc -l # 273
vegadns wordlist emit medium -o medium.txt # 5038

# Labels → FQDNs (no network)
vegadns expand -d lab.test -w fixtures/wordlist_small.txt
printf 'www\nmail\n' | vegadns expand -d lab.test -w -

# altdns-class permute (no network)
printf 'api\ndev\nwww\n' > seeds.txt
vegadns permute -i seeds.txt -w alter -d example.com --max 20 -o muts.txt

# Active enum against an embedded zone (wildcard filtered)
vegadns enum \
 --mock-zone fixtures/zone_bench.json \
 --wordlist fixtures/wordlist_small.txt \
 --output hits.txt \
 --known-true fixtures/known_true.txt
# → 10/10 names, recall=1.000 precision=1.000

# Lab volume (500 planted, 25k labels, wildcard parents)
vegadns enum \
 --mock-zone fixtures/lab/zone_lab.json \
 -w fixtures/lab/wordlist_lab.txt \
 --known-true fixtures/lab/known_true_lab.txt \
 -o lab.txt --stats-json lab.json -q --quiet-names

# HTTP paths, soft-404 200s
vegadns paths --mock-hard-zone fixtures/paths/hard_zone.txt \
 -w fixtures/paths/wordlist_hard.txt --known-true fixtures/paths/known_true_hard.txt \
 --status 200,401,403 --soft404-probes 10 -q -o path_hits.txt
# → 24/24 real, 36 soft-404s dropped

# Java / hidden / JS extract (HTML → chunk.js → /hidden/admin)
vegadns endpoints --mock-crawl -o endpoints.txt --stats-json end.json
vegadns endpoints --mock-crawl --no-seed --jsonl -o endpoints.jsonl

# Surface map on a fixture (skip OSINT / Wayback / probe)
vegadns map -d bench.test --mock-zone fixtures/zone_bench.json \
 --no-passive --no-harvest --no-probe --rounds 1 -D fast -o ./map -q
# → ./map/subs.txt (10 names)

# Shared UDP mock for a peer tool on the same answers
vegadns mock-serve --zone fixtures/lab/zone_lab.json --bind 127.0.0.1:5353

What a mock enum looks like

 SCAN CONFIG
 ------------------------------------------------------
 mode | mock DNS
 target | lab.test
 labels | 25000
 concurrency | 2000
 ------------------------------------------------------
[INF] resolving | 25000 labels
[INF] wrote 500 names → lab.txt
[OK ] quality floor recall=1.000 precision=1.000 known=500 found=500

Stdout is the 500 names only. Pipe that into probe / paths / another tool.

Live resolvers (authorized targets only)

vegadns enum \
 -d example.com \
 -w wordlist.txt \
 -r resolvers.txt \
 -o found.txt \
 --concurrency 4000 \
 --timeout-ms 1500

Depth ladder

DepthFlagPackLabelsAuto-permute
fast-D fast / -D 1tiny273off
normal-D normal / -D 2small621off
deep-D deep / -D 3medium5038off
deeper-D deeper / -D 4large20012off
final-D final / -D 5final65478on (top 300 seeds × alter, cap 250k)
vegadns wordlist list

vegadns enum -d example.com -D fast -r resolvers.txt -o found.txt
vegadns enum -d example.com -D deep -r resolvers.txt -o found.txt
vegadns enum -d example.com -D final -r resolvers.txt -o found.txt
vegadns enum -d example.com -D final --no-permute -r resolvers.txt

Passive OSINT (no DNS brute)

vegadns passive -d hackerone.com -o names.txt --stats-json stats.json
vegadns passive -d hackerone.com --fast -o names.txt # skip slower bonus source
vegadns passive -d hackerone.com -d tesla.com --fast # parallel apexes
vegadns enum -d example.com -w words.txt -r resolvers.txt --aaaa # IPv6-only names

Queries public sources concurrently (crt.name, Chaos, sub.md, Anubis, THC unless --fast). Emits in-scope descendants only (drops apex echo and foohackerone.com lookalikes). Then enum / map still resolve and wildcard-filter. The index is a seed, not a replacement for DNS.

Live HTTP probe (httpx-class)

vegadns probe -l hosts.txt -o live.txt --stats-json probe.json
printf 'example.com\n' | vegadns probe -l - -o live.txt --schemes https

Bug-bounty surface (authorized programs only)

Toy enum is wordlist × apex. A real program is iterative: names you already have become parents (api.dev.target.com) and alterx seeds, and subdirs come from archives, not only /admin.

# One loop: passive → recurse/permute → resolve → Wayback harvest → HTTP probe
vegadns map -d in-scope.example -r resolvers.txt -o ./map --depth fast --rounds 2

# Archives only (no DNS brute)
vegadns harvest -d in-scope.example -o urls.txt --hosts-out hosts.txt --paths-out paths.txt

# Brute the harvested subdirectory prefixes on a live host
vegadns paths -u https://in-scope.example/ -w ./map/paths.txt -o path_hits.txt

# Java / source / hidden endpoints (authorized origin only; no browser)
vegadns endpoints -u https://in-scope.example/ -o endpoints.txt --jsonl
vegadns endpoints -l live.txt --scope-subs --jsonl -o endpoints.jsonl

--no-enum skips resolve (OSINT + harvest + candidate expansion only). --no-harvest / --no-probe / --fast cut wall when you do not need archives. ./map/ contains subs.txt, candidates.txt, urls.txt, paths.txt, live.txt, stats.json.

Wayback CDX can be slow or empty. This host’s harvest of hackerone.com hit an archive.org timeout (8s, 0 URLs). Use --no-harvest if you only want DNS.

HTTP paths

vegadns paths --mock-paths fixtures/paths/hit_paths.txt \
 -w fixtures/paths/wordlist.txt --known-true fixtures/paths/known_true.txt \
 -o hits.txt --status 200

# hard soft-404 mock
vegadns paths --mock-hard-zone fixtures/paths/hard_zone.txt \
 -w fixtures/paths/wordlist_hard.txt --known-true fixtures/paths/known_true_hard.txt \
 --status 200,401,403 --soft404-probes 10 -q

# live (authorized base URL only)
vegadns paths -u http://127.0.0.1:18080/ -w paths.txt -o hits.txt

Typical recon stack

vegadns passive → vegadns enum [--aaaa] → vegadns probe → vegadns paths
 ↘ vegadns endpoints

Or one authorized program loop: vegadns map then paths / endpoints on live origins.

Tests

The product suite is Rust. This revision: 141 tests.

cargo test --release

Optional lab harnesses

Not part of the binary. Python here only drives target/release/vegadns (and peer tools on PATH) for gym / H2H. Details: scripts/README.md.

# Gym (mock-stress / mock-clean / live-resolve)
python scripts/gen_gym_fixtures.py
python scripts/gym_bench.py --mode mock-stress --out ./gym_out --wordlist-cap 5000

# Same mock + wordlist vs massdns / dnsx / ffuf / …
bash scripts/install_bench_peers.sh
python scripts/coverage_surpass.py --out ./coverage_out --wordlist-cap 8000

Docs: docs/SUBDOMAIN_SCANNER_GYM.md, docs/HTB_UNBIASED_BENCH.md, docs/DISCOVERY_COVERAGE.md.

Docs map

DocTopic
docs/BENCHMARKS.mdFull comparison tables + reproduce
docs/PEER_BENCH_CLOUD_2026-08-20.mdMeasured cloud-host re-run vs real adjacent binaries
docs/SUBDOMAIN_ENUM_COMPARE.mdvegadns vs subfinder / amass / assetfinder / findomain
docs/E2E_CLOUD_2026-08-20.mdFull E2E + katana / httpx compare on this host
docs/feature_timing_cloud.jsonThis-revision wall for every command
docs/OPTIMIZATION_BREAKTHROUGHS.mdMeasured hot-path campaign
docs/OPTIMIZATION_CEILING.mdI/O ceiling + tesla OSINT cross-check
docs/DISCOVERY_COVERAGE.mdF1 surpass definition
docs/SUBDOMAIN_SCANNER_GYM.mdGym modes + GUI
docs/PIPELINE.mdDNS → probe → paths / endpoints
docs/BOUNTY_SURFACE.mdRecursive DNS + archive subdirs for bug bounty
docs/ENDPOINTS.mdJava / hidden endpoint discovery (httpx + katana class)
docs/BREADTH.mdWordlist depth + permute
docs/RESEARCH.mdPeer landscape notes
docs/QA.mdQuality procedures

License

MIT. See LICENSE.

Wordlist packs include SecLists / altdns snapshots under their upstream licenses. See wordlists/README.md.

Ethics

Use only on systems you own or are authorized to test. The gym and lab suites are private mocks by default. Live enum and path modes are for authorized targets.

Категории