Skip to content

Behavioral detector

Lists only catch names someone has already reported. The behavioral detector looks at names no list has seen yet and asks whether they look machine-generated. Malware that rotates through random-looking domains to find its command server produces exactly that kind of name.

Try it: the behavioral detector demo runs this detector in your browser.

The detector reads the hostname only; timing and per-device history are coming soon. It strips the public suffix (.com, .co.uk, …) and scores the registrable label, the one immediately left of the suffix (example in ads.example.co.uk), on five signals. Some names are never scored and always come back benign with a score of 0: reverse-DNS names (in-addr.arpa, ip6.arpa), punycode labels, single-label names such as desktop-ab12cd3, and names under local-use or reserved suffixes (.local, .lan, .home, .internal, .localdomain, .localhost, .corp, .mail, .intranet, .private, .domain, .workgroup, .test, .example, .invalid and home.arpa). LAN device names often look random but are never registered public domains, so they cannot be DGA names.

Reason code Signal
high_entropy Characters are spread too evenly to look like words.
rare_ngrams Three-letter sequences that rarely occur in normal domain names.
digit_heavy An unusual share of digits.
consonant_run Long runs of consonants that people do not type.
long_label An unusually long label.

Each signal adds weight to a score between 0 and 1. Above the threshold, the verdict is malicious (DGA-like) and Ward records a flag with the score and the reasons, largest first.

It runs in-process, with no network access, no model download and no GPU. Turn it on with:

model:
builtin: lexical

In the beta the detector flags, never blocks. A flagged name is still forwarded and answered normally. Flags show up in the log and in the dashboard’s Flags section with the hostname, the client, the score and the top reasons. If you agree with a flag, add the name to a blocklist and Ward enforces it on the fast path from then on.

This follows from Ward’s first rule: the detector is a classifier, never a decider. It returns a typed verdict, and only the deterministic policy engine maps verdicts to actions.

  • Content-delivery and hash-style names (d1x2y3.cloudfront.net) can look random. Ward scores the registrable label rather than every subdomain, which removes most of these, but not all. Allowlist any that remain.
  • Short names carry little signal, so the detector gives them low scores.
  • A name that looks ordinary scores as benign however badly it behaves. The detector only judges how a name looks.
  • Timing and per-device history: how often a device asks, at what cadence, and whether this device has ever asked for anything like it before.
  • Enforcement mode: an opt-in setting that lets high-confidence verdicts block, still through the policy engine.
  • LLM explainer: an optional local model that explains a flag in plain language. It explains and never decides.