---
title: "Newly Registered Domains in Zeek: Catch Phishing & C2"
slug: "/resources/blog/detect-phishing-and-c2-with-nrd-feeds-in-zeek-corelight"
description: "See how an NRD feed in Zeek flags fresh phishing and C2 domains in encrypted traffic using TLS SNI and certificate names. Open-source integration"
---

# Detect Phishing and C2 With NRD Feeds in Zeek & Corelight

Written By [Sameer Asad](https://pk.linkedin.com/in/sameer-asad-sheikh), WhoisFreaks Team Published: July 28, 2026, Last Updated: July 28, 2026

> **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. Loaded into Zeek or Corelight as a live intelligence source, it flags _any_ connection on your network that touches a fresh domain, whether in a DNS lookup, an HTTP `Host` header, or a **TLS SNI / certificate name**, so it works even on encrypted traffic without decryption. Because phishing and command-and-control (C2) infrastructure runs on domains registered hours to days before a campaign goes live, watching by _freshness_ catches threats that curated blocklists have not flagged yet. The integration is open source: [github.com/WhoisFreaks/wf-zeek-nrd-feed](https://github.com/WhoisFreaks/wf-zeek-nrd-feed).

## Curated blocklists arrive late

The lifecycle of a threat feed has a built-in delay. A phishing domain goes live, victims click, a security team eventually triages the report, and days later the domain lands in a public blocklist. By then the campaign has burned through it and registered five more. Reputation-based feeds are doing the right thing, just always a step behind, because a domain has to _earn_ its bad reputation before it can appear on one. A 2025 longitudinal study of 690,502 phishing domains found that [detection times vary widely across blocklists](https://arxiv.org/pdf/2502.09549), with some domains taking more than a year to be listed and flagged domains staying reachable for an average of 11.5 days even after detection.

Newly registered domains invert that timing. Instead of asking "has anyone reported this domain as bad yet?", you ask "how old is this domain?", and treat freshness itself as the signal. It is unlikely that a legitimate business communicates from a domain in the first hours of its existence; attackers, on the other hand, register in bulk and use immediately. WhoisFreaks publishes the full daily registration feed across **1,528+ TLDs**, roughly **250,000 to 300,000 new domains every day**, not a curated subset, so you decide the freshness window that fits your risk tolerance. (Feed coverage and daily volume are from the WhoisFreaks Newly Registered Domains database, as of July 2026.)

## Why apply it in Zeek, not just at the DNS layer

WhoisFreaks already offers NRD integrations that _block_ at the DNS layer: Pi-hole, AdGuard Home, and a BIND9 RPZ zone. Those are built for prevention: a fresh domain simply returns `NXDOMAIN` and the user never reaches it. Zeek is the complementary half of the story, and it earns its place for two reasons.

**Zeek observes; it doesn't block.** It sits passively on a SPAN port or tap and _labels_ traffic. That is exactly what you want for detection and threat hunting, where you would rather the connection happen so you can study the behaviour: the beacon interval, how much data is leaving, which internal host reached out. An NRD hit in Zeek is a thread to pull, not just a door closed.

**Zeek sees fresh domains even in encrypted traffic.** You do not need to decrypt TLS to catch them, because the domain name is visible on the wire in several places Zeek already parses: the client's DNS query, the HTTP `Host` header, the **TLS SNI** in the ClientHello, and the **X.509 certificate** common name / subject-alternative names. A malware implant beaconing to a freshly registered C2 domain over HTTPS still gives itself away through the SNI and the server certificate, long before any payload could be inspected.

_One NRD indicator matches across DNS, HTTP, and TLS, including the SNI and certificate names visible in encrypted sessions._

## How the integration works

The design is deliberately thin, because Zeek's built-in Intelligence Framework already does the heavy lifting: it holds indicators in an in-memory store, hooks into every protocol analyzer that observes a domain, and hot-reloads indicator files that change on disk. The integration's only job is to keep a correctly formatted, current indicator file in front of it.

```
WhoisFreaks NRD feed                 this integration (daily)              Zeek / Corelight
────────────────────         ─────────────────────────────────         ────────────────────
files.whoisfreaks.com  ──►    fetch_nrd_feed.py                  ──►    Intel framework
 /download/domainer/           • fetch only missing days                 • Intel::read_files
   gtld + cctld                 • per-day gzip cache                      • auto hot-reload
 (gzip, 1 domain/line)          • merge rolling window                    • match DNS/HTTP/TLS/cert
                                • write Zeek Intel file (atomic)           • notice + intel.log
```

A daily job fetches the previous day's gTLD and ccTLD files, caches each day separately, and merges a rolling window, 30 days by default, into a single Zeek Intel file. Because each day is cached on its own, sliding the window forward is cheap: fetch one new day, drop the oldest, re-merge. A normal night is two API calls. Each domain is written as an `Intel::DOMAIN` indicator tagged with the earliest date it was seen, so its **age travels with it** into every alert.

_Daily fetch, rolling-window merge, Zeek Intel file, live matching._

## Up and running

Zeek needs to be installed first (the integration wires itself into an existing Zeek; it does not install the engine). From there it is a short sequence:

```bash
git clone https://github.com/WhoisFreaks/wf-zeek-nrd-feed.git
cd wf-zeek-nrd-feed
./install.sh                                   # venv, dirs, policy, wires local.zeek

$EDITOR .env                                   # set WHOISFREAKS_API_KEY
set -a; . ./.env; set +a

.venv/bin/python scripts/verify_endpoint.py    # confirm the feed answers for your key
.venv/bin/python src/fetch_nrd_feed.py --backfill   # first full-window fetch
sudo /opt/zeek/bin/zeekctl deploy              # load it (or restart standalone Zeek)
```

In a real backfill the fetcher pulls the full window in one pass. Here is a 30-day run building the live indicator set:

```
[wf-zeek-nrd] INFO cached gtld  2026-07-20: 191688 domains
[wf-zeek-nrd] INFO cached cctld 2026-07-20:  39807 domains
...
[wf-zeek-nrd] INFO merged window: 9684117 unique domains across 30 day(s)
[wf-zeek-nrd] INFO wrote 9684117 indicators -> .../whoisfreaks-nrd.intel
```

Nearly **9.7 million** live indicators from a single month. After that, the daily scheduler keeps the window current on its own. (Indicator counts come from a sample 30-day backfill of the WhoisFreaks feed run in July 2026; your totals will vary with the window length and TLD scope you choose.)

## What a hit looks like

When traffic touches a fresh domain, it lands in `intel.log` and raises a notice. This is a real match from a test lookup of a live ccTLD registration:

```
note:  WhoisFreaks_NRD::Domain_Hit
msg:   Traffic to WhoisFreaks NRD 0--0.jp (NRD first seen 2026-07-04),
       observed in DNS::IN_REQUEST
sub:   0--0.jp
```

Notice the age rides along in the message, `NRD first seen 2026-07-04`, so an analyst reading the alert knows immediately how fresh the domain is, without a second lookup. A domain first seen in traffic a day or two after registration is a very different risk profile from one that is three weeks old. If you want to confirm a flagged domain's registration details, a [WHOIS lookup](https://whoisfreaks.com/tools/whois) returns the registrar and creation date in one query. Route the notice wherever your other Zeek notices go, whether SIEM, Slack, or email, via `Notice::policy`.

_A live NRD hit in notice.log, with the domain's first-seen date attached._

## Concrete use cases, in order of payoff

**1. Early-warning on phishing and C2.** This is the headline. Freshly spun phishing sites and C2 domains show up in your traffic before they are on any blocklist. An NRD hit on a DNS query or TLS SNI is your first, earliest indication that a host may be talking to attacker infrastructure.

**2. Beacon hunting on encrypted traffic.** Correlate an NRD hit with Zeek's `conn.log`. Malware C2 tends to beacon at regular intervals to a fresh domain over HTTPS. The NRD match surfaces the domain via SNI; the connection records reveal the tell-tale periodicity and small, repeated payloads. Neither signal alone is conclusive, but together they are a strong lead.

**3. Data-exfiltration leads.** A single internal host repeatedly contacting a brand-new domain, moving more data outbound than in, is a classic exfil pattern. NRD freshness raises it out of the noise of ordinary web traffic.

**4. Triage by age.** The first-seen date in every hit is a built-in triage dial. Sort your NRD notices by domain age and work the freshest first: a domain used within 48 hours of registration is far more likely to be purpose-built for an attack than one nearing the end of your window.

**5. Retrospective hunting.** Because Zeek logs everything, you can replay stored `dns.log` / `ssl.log` against today's indicator set to ask, "did anything on my network touch a domain that has since been flagged as newly registered?", turning the feed into a look-back tool as well as a live one. A [historical WHOIS](https://whoisfreaks.com/tools/whois/historical) check then confirms exactly when a suspect domain was registered.

## Sizing and false positives

Two things to set expectations on before production.

**Memory.** The Intelligence Framework keeps every indicator in RAM. A 30-day window is around 8 to 10 million indicators, on the order of 1.5 to 2 GB on the Zeek manager. That is fine on a well-specced sensor; if you are constrained, shorten the retention window (a 7-day window is roughly 1.8M indicators) or run gTLD-only. On a cluster the intel store lives on the manager, so size that node.

**Not every fresh domain is malicious.** Product launches, marketing microsites, and freshly provisioned CDN and cloud hostnames are legitimately new. Treat an NRD hit as a _pivot_, not an automatic incident. The signal sharpens when combined with other context: beacon periodicity, a domain only one host talks to, or a very recent first-seen date. Whitelist known-good new domains and suppress noisy ones through `Notice::policy`.

## Where it fits in the WhoisFreaks NRD family

Same feed, different detection surfaces. Pick the layer, or run several together:

*   **DNS blocking:** [Pi-hole](https://whoisfreaks.com/resources/blog/pihole-nrd-feed-proactive-phishing-protection), [AdGuard Home](https://whoisfreaks.com/resources/blog/adguard-home-whoisfreaks-nrd-feed-integration), and [BIND9 RPZ](https://whoisfreaks.com/resources/blog/integrating-whoisfreaks-nrd-data-with-bind9-rpz) _prevent_ access.
*   **IDS:** [Suricata](https://whoisfreaks.com/resources/blog/catch-attacker-infrastructure-before-it-goes-live-feeding-newly-registered-domains-into-suricata) alerts inline.
*   **Passive network analysis:** **this integration** labels and hunts across all traffic, encrypted included.

_One NRD feed, many detection surfaces. This post covers the Zeek/Corelight path._

## Frequently asked questions

**Does the NRD feed work on encrypted HTTPS traffic?** Yes. Zeek reads the domain name from the TLS SNI in the ClientHello and from the X.509 certificate names, both visible without decryption. An NRD indicator matches there the same way it does in a DNS query or an HTTP `Host` header, so a beacon to a fresh C2 domain over HTTPS still raises a hit before any payload could be inspected.

**How is this different from blocking newly registered domains at the DNS layer?** DNS blocking with Pi-hole, AdGuard Home, or BIND9 RPZ prevents access by returning `NXDOMAIN`. Zeek does the opposite: it observes passively and labels the traffic, letting the connection happen so you can study beacon timing and data volume. Use DNS blocking for prevention and Zeek for detection and threat hunting.

**How much memory does a 30-day NRD window need in Zeek?** Around 1.5 to 2 GB on the Zeek manager. The Intelligence Framework holds every indicator in RAM, and a 30-day window is roughly 8 to 10 million domains. If a sensor is constrained, shorten the window to about 1.8 million indicators at 7 days, or run gTLD-only to cut the count further.

**Is every newly registered domain malicious?** No. Product launches, marketing microsites, and freshly provisioned CDN and cloud hostnames are legitimately new. Treat an NRD hit as a pivot, not an automatic incident. The signal sharpens with added context such as beacon periodicity, a domain only one host contacts, or a very recent first-seen date. Whitelist known-good domains through `Notice::policy`.

## Get started

Point your network's freshest-domain intelligence at every flow it sees:

*   **Repo:** [wf-zeek-nrd-feed](https://github.com/WhoisFreaks/wf-zeek-nrd-feed)
*   **Feed:** the [WhoisFreaks Newly Registered Domains](https://whoisfreaks.com/products/newly-registered-domains) Domainer subscription covers 1,528+ TLDs. A free daily sample of 1,000 domains is available if you want to wire up the plumbing first.

Fresh domains are where attacks begin. With this integration, they are also where your detection begins.
