Skip to content

c3l3si4n/pugdns

Repository files navigation

pugDNS

pugDNS

An experimental high-performance DNS query tool built in Rust with AF_XDP and eBPF for extremely fast bulk DNS lookups. pugDNS sends DNS packets from user space through AF_XDP and uses a selective XDP program to capture only the DNS replies it owns.

Overview

pugDNS is designed for security researchers, network administrators, and penetration testers who need DNS reconnaissance at scale. The current release is the Rust implementation at the repository root; the old Go implementation is no longer part of the published tree.

pugDNS can saturate a 1 Gbit/s link. Run it on a host where high packet rates are acceptable and verify the interface, gateway MAC, memlock, and XDP setup with --doctor before large scans.

Performance

pugDNS is designed to push bulk A-record lookups through AF_XDP with minimal kernel-network-stack overhead. The current high-throughput defaults use iterative DNS from root hints, a selective XDP reply filter, bounded authority fanout, paced authority hedging, and a large Rust worker pool.

The current promoted benchmark profile was measured on the 500,000-domain corpus at pugrecon/bench/pugdns_ch_500k_input.txt on the AX42 Hetzner host used during the optimization work. These are no-extra-knob default runs after the Rust implementation was promoted:

Run Wall time Domains/s Successful Failed TX drops
1 5.042s 99,123 499,704 93 0
2 4.934s 101,305 499,694 103 0
3 4.811s 103,891 499,704 93 0
4 4.743s 105,375 499,704 93 0
5 4.745s 105,330 499,704 93 0

The first sample landed just under 100K domains/s; the next four consecutive default runs cleared 100K domains/s with zero AF_XDP TX drops. See PERF_NOTES.md for the full optimization log, rejected experiments, and counter-level details.

Features & Roadmap

  • High-speed DNS query transmission via AF_XDP sockets
  • Rust iterative resolver that walks root/TLD/authoritative delegations directly
  • Selective eBPF/XDP DNS reply capture without stealing unrelated traffic
  • Bounded authority fanout, scored authority ordering, and paced hedging
  • Support for multiple nameservers and large domain lists via input files
  • Automatic query retries for unanswered domains
  • Kernel and user-space drop monitoring for observability
  • Config-file access to advanced throughput and resolver tuning
  • Plain progress output and compact final summaries
  • Results saved in JSON format
  • Support for different DNS record types (AAAA, MX, etc.)
  • IPv6 support
  • Dynamic rate limiting profiles

Usage

Usage:
  sudo ./pugdns -domains domains.txt -nameservers resolvers.txt [-interface eth0]

Fast defaults are enabled: iterative AF_XDP root-hint walking, JSON output,
5 retries, 1s retry timeout, and the measured high-throughput Rust defaults.

Common flags:
  -resolve-mode <mode>  recursive or iterative. Iterative uses AF_XDP root-hint walking.
  -iterative-cname <m>  Iterative CNAME handling: stop or chase. Default: stop.
  -domains <file>       Domain list to query, one name per line.
  -domain <name>        Query one domain instead of a file.
  -nameservers <file>   Resolver list, one IPv4 resolver per line.
  -interface <name>     Network interface. Auto-discovered when omitted.
  -xdp-mode <mode>      generic, driver, or auto. Default: generic.
  -doctor               Run setup, input, resolver, AF_XDP, and BPF checks.
  -max-retries <n>      Maximum retries per domain. Default: 5.
  -output <file>        Result file. Default: results.jsonl. Empty disables output.
  -output-mode <mode>   json or names. Default: json.
  -metrics-file <file>  Write JSON runtime metrics and throughput counters.
  -summary <mode>       text, json, or none. Default: text.
  -progress <mode>      auto, plain, or none. Default: auto.
  -config <file>        Load YAML or JSON config.
  -quiet                Suppress progress and routine logs.
  --version             Show version information.
  --generate-config <file>
                        Write a complete YAML config with advanced tuning fields.

Advanced tuning fields remain available through YAML or JSON config files. Use ./pugdns --generate-config config.yaml to start from the current defaults.

Example Usage:

# Query domains using the benchmarked fast defaults.
sudo ./pugdns -interface eth0 -domains domains.txt -nameservers resolvers.txt

# Capture runtime metrics while using the same defaults.
sudo ./pugdns -interface eth0 -domains domains.txt -nameservers resolvers.txt -metrics-file metrics.json

# Validate the environment before sending traffic.
sudo ./pugdns -doctor -interface eth0 -domains domains.txt -nameservers resolvers.txt

# Emit only a compact machine-readable final summary.
sudo ./pugdns -interface eth0 -domains domains.txt -nameservers resolvers.txt -quiet -summary json

# Resolve iteratively from root hints without a public resolver list.
sudo ./pugdns -resolve-mode iterative -interface eth0 -domains domains.txt -output results.jsonl -metrics-file metrics.json

(Note: Running with sudo or appropriate capabilities (CAP_NET_ADMIN, CAP_NET_RAW, potentially CAP_SYS_ADMIN for memlock/BPF) is typically required for AF_XDP and eBPF operations.)

Iterative mode uses the AF_XDP/eBPF engine for UDP authority queries and ignores configured resolver lists. It walks root/TLD/authoritative delegations directly, caches zone cuts and NS addresses, parses referrals and in-bailiwick glue, uses scored bounded authority fanout for each known zone cut, resolves no-glue NS addresses in parallel, batches AF_XDP authority fanout with a shared response channel, tracks sharded per-authority RTT/failure state, spreads equal-score authority ties by query name, and stops at CNAME answers by default before writing the same JSONL output format as recursive mode. Use -iterative-cname chase when the benchmark or workflow needs full CNAME target resolution. The iterative authority timeout defaults to 250ms. Iterative tuning fields such as authority fanout, hedge delay, referral thresholds, and timing attribution are intentionally config-file settings instead of top-level CLI flags.

Installing

If you don’t want to build pugdns from source and just want to test it out, simply download the pre-compiled binary from our Releases page. It will be easier and faster.

Building from source

If you really want to build from source, here's a rough guide on how to do so:

  1. Clone the repository:
    git clone https://github.com/c3l3si4n/pugdns
    cd pugdns
  2. Install Dependencies: Ensure you have Rust (>= 1.95) and Clang/LLVM (for eBPF compilation) installed. You may also need kernel headers (linux-headers-$(uname -r) on Debian/Ubuntu).
    sudo apt install linux-headers-$(uname -r) llvm libbpf-dev clang pkg-config
    
  3. Build:
    ./build.sh
    This builds pugdns in release mode and copies the binary to ./pugdns.
  4. Run:
    sudo ./pugdns [flags...]

Credits

  • aya-rs/aya - eBPF library used for loading and interacting with BPF programs.
  • netring - AF_XDP socket support for Rust.
  • hickory-dns - DNS protocol parsing and message handling.

Feel free to open issues for bugs, feature requests, or questions! Contributions are welcome.

About

An experimental high-performance DNS query bruteforce tool built with AF_XDP for extremely fast and accurate bulk DNS lookups.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages