Blog
Written By Sameer Asad, WhoisFreaks Team Published: June 26, 2026, Last Updated: June 26, 2026
Every day, tens of thousands of new domains are registered across the internet. Most are legitimate: new businesses, personal projects, side ventures. But a meaningful share are registered for one purpose, to impersonate a bank, deliver malware, or phone home to a command-and-control server before security vendors have ever seen them.
This is the Newly Registered Domain (NRD) problem, and it sits at the heart of a detection gap that traditional threat intelligence feeds consistently fail to close. In this post, we walk through how we built an open-source integration between WhoisFreaks NRD data and BIND9's Response Policy Zone (RPZ) engine, and how you can deploy it on any Linux server in under 20 minutes.
The full source code is available at github.com/WhoisFreaks/wf-bind9-nrd-rpz.
Reputation-based threat intelligence works on hindsight. A domain gets flagged only after it has been observed behaving maliciously, reported by researchers, analyzed, and added to a feed. Even in well-tuned pipelines that process takes hours to days, and the early hours are exactly when fresh phishing and C2 infrastructure does its damage.
<p align="center"> <img src="PLACEHOLDER_IMAGE_1_threat-timeline.png" alt="Timeline showing the gap between domain registration, first malicious use, and threat feed inclusion" width="800"/> <br/> <em>Fig 1: The detection gap. Most phishing infrastructure is live and weaponized within hours of registration, long before reputation-based feeds catch it.</em> </p>
The volume of fresh malicious infrastructure is large and growing. Infoblox's December 2025 DNS threat report found that more than 7.6 million new threat-related domains appeared between August and November 2025, a 20 percent increase over the prior quarter. Most of that infrastructure is registered and put to use well before reputation feeds catch up to it.
The approach behind this project inverts the usual model. Rather than waiting for a domain to be flagged as malicious, block every newly registered domain by default and maintain a short whitelist of trusted exceptions. Most legitimate new domains do not need to be reachable by your users on the day they are registered. Most malicious ones do.
A Response Policy Zone is a DNS zone that BIND9 consults before it answers a query. Instead of mapping names to IP addresses, it holds policy rules. When a client asks for a domain that matches a rule, BIND9 overrides the normal answer and returns whatever the policy specifies. The most common action is NXDOMAIN, which tells the client the domain does not exist, so the query fails fast at the application layer before any connection opens.
Administrators usually point RPZ at reputation feeds so a resolver can block known-bad names in near real time. The same mechanism works for a whole category of names rather than a named blocklist, which is what this integration relies on: it treats every domain registered in the last N days as suspect by default, minus the whitelist.
Everything happens inside the resolver. There is no proxy, no inline appliance, and no packet inspection, so there is nothing to fail open. If BIND9 is already your recursive resolver, RPZ adds negligible latency, and with qname-wait-recurse no set, the policy is checked before recursion begins.
The integration is built around a three-stage daily pipeline:
WhoisFreaks NRD API
│
▼
Fetch + cache daily feed ──→ /var/cache/bind9-nrd/YYYY-MM-DD.gz
│
▼
Expire old cache files (removes days older than retention window)
│
▼
Merge all cached days ──→ deduplicated domain list
│
▼
Build RPZ zone file ──→ /etc/bind/db.rpz.nrd
│
▼
rndc reload rpz.nrd.local ──→ BIND9 applies new policy live
The key design decision is incremental updates via a local cache. Rather than re-fetching the entire retention window every night, the tool fetches only yesterday's feed (2 API calls, one for gTLD and one for ccTLD), saves it as a compressed file, expires anything older than retention_days, then rebuilds the zone from the merged cache. This means:
Running a 7-day backfill against the WhoisFreaks NRD API on a test deployment gives a sense of the volume. Here are the per-day unique-domain counts from one such run (June 18 to 24, 2026):
2026-06-18 → 419,936 unique domains
2026-06-19 → 513,415 unique domains
2026-06-20 → 80,946 unique domains
2026-06-21 → 284,835 unique domains
2026-06-22 → 245,034 unique domains
2026-06-23 → 333,319 unique domains
2026-06-24 → 372,614 unique domains
─────────────────────────────────────
7-day total → ~2,250,000 unique domains
That is roughly 2.25 million unique domains across a single week. BIND9 loads a zone of this size and serves it without a measurable hit to query latency, because RPZ matching happens in memory and the policy is evaluated before recursion.
Ubuntu users: The stockbind9package from Ubuntu's default repositories is compiled without RPZ support. The installer handles this by adding the ISC official PPA (ppa:isc/bind) automatically before installing BIND9.
git clone https://github.com/WhoisFreaks/wf-bind9-nrd-rpz.git
cd wf-bind9-nrd-rpz
sudo bash scripts/install.sh
The installer detects your distro, installs BIND9 with RPZ support, sets up a Python virtualenv, creates the cache directory at /var/cache/bind9-nrd/, deploys a systemd service and daily timer, and sets correct file permissions on the zone file (640 root:bind).
sudo nano /etc/bind9-nrd/config.ini
# Set: api_key = YOUR_WHOISFREAKS_API_KEY
Or via environment variable:
echo "NRD_API_KEY=your_key_here" | sudo tee /etc/bind9-nrd/env
sudo chmod 600 /etc/bind9-nrd/env
Add to /etc/bind/named.conf.local:
zone "rpz.nrd.local" {
type master;
file "/etc/bind/db.rpz.nrd";
allow-query { none; };
allow-transfer { none; };
};
Replace the contents of /etc/bind/named.conf.options with:
options {
directory "/var/cache/bind";
recursion yes;
allow-recursion { any; };
forwarders {
8.8.8.8;
1.1.1.1;
};
dnssec-validation no;
listen-on-v6 { none; };
response-policy {
zone "rpz.nrd.local" policy NXDOMAIN log yes;
} qname-wait-recurse no;
};
Important:qname-wait-recurse nois a modifier on the closing}ofresponse-policy. It must appear on the same line as the closing brace, not as a separate statement.recursion yesis also required, since RPZ does not apply to non-recursive queries.
Add to /etc/bind/named.conf (top-level, not inside named.conf.options):
logging {
channel rpz_hits {
file "/var/log/named/rpz.log" versions 7 size 50m;
severity info;
print-time yes;
};
category rpz { rpz_hits; };
};
Create the log directory so BIND9 can write to it:
sudo mkdir -p /var/log/named
sudo chown bind:bind /var/log/named
Then validate and reload:
sudo named-checkconf
sudo systemctl reload bind9
sudo nrd-rpz-update
The first run automatically detects an empty cache and backfills the last 7 days. Every subsequent nightly run (handled by the systemd timer) fetches only the previous day's feed.
# Check zone is loaded
sudo rndc -k /etc/bind/rndc.key zonestatus rpz.nrd.local
# Pick a blocked domain from the zone and query it
sudo grep "CNAME \.$" /etc/bind/db.rpz.nrd | head -1 | awk '{print $1}'
dig @127.0.0.1 <that-domain>
# Expected: status: NXDOMAIN
# Verify normal domains still resolve
dig @127.0.0.1 google.com
# Expected: status: NOERROR with an A record
The retention window is the most important tuning knob. Edit /etc/bind9-nrd/config.ini:
[retention]
# Rolling window in days. Zone always covers the last N days.
# Every nightly run fetches only 1 new day regardless of this value.
days = 7
cache_dir = /var/cache/bind9-nrd
days value |
Zone covers | Use case |
|---|---|---|
1 |
Yesterday only | Minimal footprint, tightest scope |
7 |
Last week | Recommended default |
30 |
Last month | Maximum coverage |
You can also use the CLI directly:
# Use a 30-day window
nrd-rpz-update --days 30
# Force backfill all missing days
nrd-rpz-update --backfill
# Dry run, preview without writing anything
nrd-rpz-update --dry-run
# Check what feeds are available
nrd-rpz-update --status
Whitelist management is the most important ongoing operational task. The installer deploys a default whitelist at /etc/bind/nrd-whitelist.txt covering major cloud providers, CDNs, and developer platforms. Add any domains your organization depends on that might appear in the NRD feed:
# /etc/bind/nrd-whitelist.txt
# Add your trusted domains here, one per line
partner-api.yourcompany.com
internal-service.example.com
False positives are rare but expected. Legitimate businesses register new domains and use them immediately: SaaS launches, marketing campaigns, new products. The whitelist is your safety valve. If users report a blocked domain that is legitimate, add it to the whitelist and the next nightly run will exclude it from the zone.
Monitoring is simple. Every query that hits the policy is logged to /var/log/named/rpz.log. A sudden spike in RPZ hits from a single internal host is a strong indicator of malware attempting to phone home to freshly registered C2 infrastructure.
# Watch hits in real time
sudo tail -f /var/log/named/rpz.log
# Check cache contents
ls /var/cache/bind9-nrd/
# 2026-06-18.gz 2026-06-19.gz ... 2026-06-24.gz
Traditional threat intelligence assumes you know what you are looking for. NRD blocking inverts the model: instead of maintaining a list of known-bad domains, you maintain a list of known-good domains and block everything registered in the last N days by default. The attacker then has to register infrastructure that is either old enough to have aged out of your retention window or already on your whitelist. Both options significantly constrain their operational freedom.
The DNS layer is the right place to enforce this. It is network-wide (it covers every device using your resolver), protocol-agnostic (HTTP, HTTPS, DNS-over-HTTPS resolving through BIND9, and SMTP are all covered), and the enforcement happens before any connection is established. There is no payload to inspect, no certificate to verify, no packet to drop. The domain simply does not resolve.
The full project is open source under the MIT license:
github.com/WhoisFreaks/wf-bind9-nrd-rpz
The repository ships with a test suite wired into CI on every commit, a cross-distro installer for Debian/Ubuntu, RHEL/Fedora, and Arch, complete systemd service and timer units, and documentation that covers the known gotchas, including the Ubuntu RPZ-support issue and the qname-wait-recurse placement quirk.
Pull requests are welcome. If you deploy this and run into issues or have improvements, open an issue on GitHub.
WhoisFreaks provides domain intelligence data including newly registered domains, WHOIS history, reverse WHOIS, and DNS data. Learn more at whoisfreaks.com.
Quick answer: A newly registered domain (NRD) feed is a daily list of every domain added to the global DNS in the last N days. Loading it into Pi-hole as a rolling blocklist means any domain registered in your chosen window (commonly 5 to 30 days) returns NXDOMAIN on your network. Because most phishing, malware, and scam infrastructure runs on domains registered hours to days before a campaign launches, blocking by freshness stops threats that curated blocklists have not flagged yet. Curated bl
14 min read
Understand why attackers prefer newly registered domains and the WHOIS patterns that expose malicious infrastructure before campaigns go live.
10 min read