A lightweight, open-source DNS sinkhole written in Rust, inspired by Pi-hole. RustyHole acts as a network-wide ad blocker by intercepting DNS queries and blocking requests to known ad/malware domains.
- DNS Sinkhole: Intercepts DNS queries and blocks ad/malware domains
- Blocklist Management: Downloads and parses blocklists from URLs (StevenBlack format)
- Web Dashboard: Simple HTTP dashboard for monitoring stats
- Async Performance: Built with Tokio for high concurrent query handling
- Memory Efficient: Uses HashSet for O(1) domain lookups
- Configurable: TOML-based configuration for easy customization
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Client DNS │───▶│ RustyHole DNS │───▶│ Upstream DNS │
│ Query │ │ Server │ │ (8.8.8.8) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│
▼
┌──────────────────┐
│ Blocklist │
│ Checker │
└──────────────────┘
│
▼
┌──────────────────┐
│ Web Dashboard │
│ (Stats/Monitor)│
└──────────────────┘
- Rust 1.70+
- Root privileges (for DNS port 53 binding)
- Clone the repository:
git clone https://github.com/yourusername/rusty-hole.git
cd rusty-hole- Build the project:
cargo build --releaseEdit config.toml:
# Upstream DNS server to forward legitimate queries to
upstream_dns = "8.8.8.8:53"
# List of URLs to fetch blocklists from
blocklist_urls = [
"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts",
]
# Domains to whitelist (overrides blocklist)
whitelist = []
# Port for the web dashboard
web_port = 8080
# DNS server bind address (requires root privileges)
dns_bind = "0.0.0.0:53"-
Configure Network DNS: Set your router's DNS server to point to this machine's IP address.
-
Run RustyHole:
sudo ./target/release/rusty-holeThe DNS server will bind to port 53 and the web dashboard will be available at http://localhost:8080.
- Stats API:
GET /stats- Returns JSON with query statistics - Dashboard:
GET /dashboard- HTML interface showing current stats
- Access your router's admin panel
- Find DHCP settings
- Create a static IP reservation for this machine
- Set the router's DNS server to the reserved IP
Alternatively, configure each device to use this machine's IP as DNS server.
RustyHole supports any hosts-file format blocklist. Popular sources:
- StevenBlack hosts:
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts - AdAway: Various mirrors available
- Custom lists in hosts format
- The web dashboard currently has no authentication
- Only bind the dashboard to localhost in production
- Run with minimal privileges where possible
- Memory usage: ~50-100MB depending on blocklist size
- Handles thousands of concurrent queries
- Fast O(1) domain lookups using HashSet
- Written in Rust for memory safety and performance
- Simpler architecture, no gravity update mechanism
- No built-in DHCP server
- Minimal dependencies
- No auto-updates (rebuild required)
# Run tests
cargo test
# Run with debug logging
RUST_LOG=debug cargo run
# Lint code
cargo clippyRun with sudo:
sudo cargo run --releaseReduce blocklist URLs or switch to smaller lists.
Check:
- Router DNS points to RustyHole IP
- Blocklist URLs are accessible
- Logs show blocked queries
MIT License - see LICENSE file for details.
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request