Skip to content

Changelog

One entry per release, newest first. Security-relevant node releases are marked Security and link their advisory. The API has its own changelog. An Atom feed is planned.

No release has been published yet: there is no versioned node image or binary. Until the beta, entries list what landed in the code, by date.

  • Am I using opdns? A public page, opdns.io/check, and a panel on each profile’s Setup page tell whether this device’s DNS goes through opdns, and with which profile, identification and transport. It works by looking up a random name only opdns answers; the lookup is never logged or counted. check.opdns.io TXT gives the same facts on the command line. (Check it works)
  • The PoPs can no longer be used to amplify attacks: UDP answers are at most twice the question’s size (four times for identified queries) or truncated to TCP, responses are rate-limited per client network, ANY gets the short RFC 8482 answer, and DNS cookies (RFC 7873) exempt verified clients. Under a reflection-style load test, the bytes a PoP sent back fell from 13.7 to 0.5 times the bytes it received. (The public resolver path, Amplification)
  • Profiles are signed (Ed25519) on their way to the PoPs and to self-hosted nodes, which refuse a profile that is unsigned or signed by an unknown key and keep the last good one. (Signed profiles)
  • The list catalogue (GET /v1/lists) names every source of a list, with its licence, the credit it requires and when it last changed. (Privacy blocklists)
  • New list builds go to a few canary PoPs first. After a soak (15 minutes), their block and SERVFAIL rates are compared with the rest of the fleet; the build is promoted everywhere or rejected. Operators can roll back to an older version fleet-wide and pin promotions. (List rollouts)
  • List manifests, latest.json and a new keys.json of trusted keys carry detached minisign signatures, and each build records where its sources came from.
  • Lists can hold exact (=example.com) and children-only (*.example.com) rules besides suffix rules (list artifact format 2; PoPs and nodes still load format 1). A public suffix is never blocked as a whole.
  • Every build is checked before it is published: a never-block guard list removes block rules on names that must keep resolving, and four gates (per-list change, memory budget, guard, popular sites newly blocked) refuse a suspicious build, which then never reaches a PoP. List ids are never reused. (List rollouts)
  • Every PoP runs the same pinned Unbound (1.26.1), built from the verified source, and keeps a local copy of the root zone (RFC 8806, checked with ZONEMD), so cold lookups no longer go to the root servers. (Architecture)
  • The fleet’s resolver job forwards EDNS Client Subnet, so the profile’s ECS mode now applies on PoPs deployed from it. (Settings)
  • Tested clients: which command-line DNS clients work over which transport; operating systems and browsers are still to be tested.
  • Analytics globes: the Destinations card is now a dot-matrix globe shaded by country, like the Where your queries were answered card, and both can be zoomed up to 6x (pinch, Ctrl or ⌘ + scroll, the + and − buttons, or the +, - and 0 keys) with finer dots as you zoom in; point at a country for its count and share. (Using the globes)
  • List reports: you get an email when the maintainers accept or reject your report; they aim to answer within two business days. (Report a wrong block or a miss)
  • Query limits on logs and analytics: ranges of at most 31 days for the shapes that read every row (400 days for hourly totals), a query budget and at most four queries at once per organisation, and a cap on what one query may read (range_too_large, too_many_queries, query_too_expensive). A query without from covers the longest range allowed. (Log query limits)
  • API 0.5.2 to 0.6.2: the query limits, signed node profiles, list sources and attribution in the catalogue with triage_due_at on list reports, the list history endpoints for operators, and node token rotation. The document now passes a Redocly lint in CI. (API changelog)
  • Cloud log retention is at most 90 days (it was up to 730). The menu offers 1 day, 7 days, 30 days and 3 months; the API accepts 1 to 90. Queries logged on your own node are not limited. (Retention)
  • Passwords are 12 to 128 characters, with no other rule, and a strength meter under every new-password field that advises without blocking. New passwords are not checked against breached-password lists. (Password rules)
  • Suspended profiles: a profile the operators suspend keeps answering, without filtering or logging, and shows a banner with its settings read-only until it is reinstated. (Suspended profiles)
  • Analytics: a GAFAM card (the share of queries that reached Google, Apple, Meta, Amazon or Microsoft, then the big CDNs) and a Where your queries were answered card with a globe of the PoPs that answered; the destinations map credits its GeoIP data. (Where your queries were answered)
  • API 0.2.1 to 0.5.1: retention 1 to 90, the password length codes, suspended on profiles with 409 profile_suspended, the top_pops shape and GET /v1/pops. (API changelog)
  • Report a wrong block or a miss from a query’s details in Logs; your reports and the maintainers’ decision are under Settings → Lists. (Report a wrong block or a miss)
  • Analytics: the Destinations card has a world map of answer addresses by country, where the deployment has a GeoIP database. (Destinations globe)
  • Settings hides or disables, with the reason, what this deployment does not offer (today the block page). (Settings that do not apply here)
  • Account security (from an ASVS level 2 review of sign-in): emails when an authenticator app, a passkey or recovery codes change, and when a reused authenticator code is refused; recovery codes are salted one by one; a password change, reset or recovery ends older reset and recovery links; adding a second factor lifts only that session’s restriction; passkey and token names refuse control and invisible characters; new Activity entries for failed password changes, wrong codes and reused codes; a Show button on every password field. (Account)
  • Operator pages and admin-scoped tokens need a sign-in with a passkey or a second factor outside development (mfa_required). (Operator pages)
  • API 0.2.0: X-Opdns-Api-Version on every response, Deprecation and Sunset headers on deprecated fields, GET /v1/capabilities, list reports, country and owner on destinations, a top_owners shape, and browser security headers on every response. (API versioning and deprecation)
  • Logs: the live tail is a stream (server-sent events), with a fallback to polling every 2 seconds; the indicator says which. Every result shows where it came from (Cloud or Your node), and relayed results have their own states: asking your node, node offline with an automatic retry, node timeout. (Logs)
  • Query details say why a query was blocked, allowed or rewritten, with the reason code, list or rule, and the Extended DNS Error the device received. Allowing a name a security list blocked needs an explicit confirmation. (Query details)
  • Analytics has a Top reasons card, counted over the whole range by the log store. (Analytics)
  • Logs and Analytics say when a result from your node is partial, and why: near its time limit, reconnecting, or busy. (Logs)
  • Settings disables the node log destinations until a node is enrolled and names the node once there is one; log options that do not apply while logs are off say so. (Settings)
  • Account → Activity shows the account’s audit log; Operator → Audit shows every organisation’s. (Activity)
  • Account recovery with an emailed link and a recovery code, for an owner who lost their authenticator app or passkeys. (Account recovery)
  • Node offline alerts: owners get an email when a self-hosted node has been offline for 10 minutes, and when it is back; a preference turns them off. (Nodes)
  • Password sign-in slows down after failures, and ten failures in an hour send the owner an email. Sessions last at most 30 days, end after 7 days unused, and renew their token daily.
  • Account → Error reports turns off the dashboard’s crash reports for a browser.
  • API: cursor pagination on every list, Idempotency-Key on creating POSTs, the live log stream, audit log endpoints, preferences, account recovery, DELETE /v1/nodes/self, and enrolment with a profile. (Errors and limits)
  • API: every log row carries reason, reason_code, ede_code and ede_text; a top_reasons analytics shape; results relayed from a node can be marked partial; dashboard error reports (POST /v1/client-errors, listed for operators); profile.update audit entries record what changed, from and to. (Log query results)
  • Local names: the node answers your network’s own names under home.arpa (from local.hosts and DHCP lease files) and reverse lookups of private addresses itself, and names plain-DNS clients in its logs after their host name. On by default. (Local names)
  • Node token rotation: the node replaces its token every 90 days by itself, and opdns-node rotate-token does it now; the previous token keeps working for 10 minutes. (Rotate the node token)
  • Profile signing keys: the node verifies every profile the cloud sends; the keys are learnt at enrolment (profile_keys.json, backed up) or pinned with cloud.profile_public_keys. (Profile signing keys)
  • IPv6 preference: on a host without IPv6 the node’s Unbound uses IPv4 only, and prefers IPv4 when the host has no public IPv6 address; unbound.ipv6 overrides it. (IPv6 for upstream queries)
  • One set of link phases (connected, backoff, offline, revoked…) on the local page, in opdns-node status, /healthz, the metrics and the log. (The link’s state)
  • Enrolling a standalone node shows the profile it will upload and asks first (--yes in scripts), then archives it and stops reading profile_file. (Enrol a standalone node)
  • The node keeps a local copy of the root zone (RFC 8806, ZONEMD checked), on by default, as the PoPs do: cold lookups start at the top-level domain’s servers. dns.root_zone and dns.root_zone_sources configure it; the status page shows the copy’s serial and age. (Local root zone)
  • A suspended profile resolves unfiltered and unlogged on an enrolled node too. (Suspended profiles)
  • Open-resolver guard: the node answers only private, CGNAT, ULA, link-local and loopback sources unless dns.allow_from allows more; others get REFUSED. The local page and API answer only the same networks and reject unknown host names. Nodes with global IPv6 clients need their prefix in dns.allow_from. (Network access)
  • opdns-node unenrol revokes the node in the cloud as well (--local-only skips it). (Unenrol)
  • Enrolling a standalone node takes its local profile to the dashboard when the dashboard profile is untouched (--keep-cloud-profile to leave it out). (Enrol a standalone node)
  • Standalone nodes have a local API: read and write the profile, read and refresh the lists, with a bearer token. (Local API)
  • Nodes follow list rollbacks: an announced older version is installed; an old notice replayed within 30 seconds of a newer one is ignored. (List updates and rollbacks)
  • opdns-node config check validates a configuration file and prints every value with where it came from (default, file, environment, flag); config reference prints every key. The file has a format version. (Configuration)
  • systemctl reload (SIGHUP) applies dns.allow_from, web.allow_from, web.hosts, web.password_hash and store.retention_days without a restart. (Reload)
  • A standalone node reloads its profile_file within seconds of an edit; an invalid edit keeps the last good profile and shows the error. (Standalone mode)
  • opdns-node backup and restore move a node, enrolled and with its logs, to another host; schema upgrades of the log database copy it to backups/ first, and a corrupt database is moved aside instead of stopping the node. (Upgrade and back up)
  • Logging pauses below store.min_free_mb of free disk (500 MB) while DNS keeps answering. (Low disk space)
  • An optional password on the local page (opdns-node hash-password, web.password_hash), and /metrics is now off unless page.metrics: true. (Network access)
  • Connections to opdns use TLS 1.3 only; cloud.spki_pins can pin the cloud’s keys. (Connections to opdns)
  • The node refuses to start while node.json or secrets/ is readable by every user.
  • A busy node answers dashboard queries it cannot take with a partial result instead of an error (link.max_inflight_queries). (Logs on your node)
  • The container ships the same pinned Unbound as the PoPs.
  • Nodes answer the top_owners analytics shape and name the company behind each destination address, from classification data built into the release; the control plane adds destination countries, since nodes have no GeoIP data. (Analytics from your node)
  • Fleet operations: fleetctl pop add takes a new server to announced in 11 resumable steps, pop remove takes one away, fleet reboot and fleet update go through the fleet one drained server at a time with a host agent, pop-agent. A Nomad outage rehearsal found that PoP clients killed every task after 6 minutes; nomad_retry { attempts = 0 } is now required and rendered. (Fleet operations)
  • Profile messages, snapshots and node profile responses are signed; key rotation, refusal metrics. (Signed profiles)
  • Amplification mitigations on the edge (-rrl-*) with an audit table and a reflection load rig. (Amplification)
  • List history in Postgres (list_sources, list_versions), read by GET /v1/admin/lists/sources and /versions; alerts ListVersionNotPromoted, ListArtifactRefused and ListReportsOverdue; triaging a report emails the reporter. (List history)
  • PoPs refuse an operator or source block file that does not match its announced checksum or is older than announced (Operator and source blocks); control-plane roles refuse the simulation’s published secrets outside development (Admin tools).
  • opdns-cp geoip: a role that downloads DB-IP’s free country database every week, verifies it, publishes it to the object store for the api and ingest roles, and can roll it back; the GeoIPStale alert fires after 45 days without a successful refresh. (GeoIP refresh)
  • opdns-cp admin profile suspend|unsuspend and GET/PATCH /v1/admin/profiles/{id} suspend and reinstate a profile, audited with an operator-only reason. (Suspend a profile)
  • ClickHouse’s monthly backups are kept 120 days (was 730), since no log is kept longer than 90. (Backups and restore)
  • Each PoP’s Unbound configuration is rendered from the fleet inventory (fleetctl unbound render|diff), the same way for the simulation and production.
  • opdns-cp admin grant|revoke|list flags operator accounts; admin endpoints on the control plane roles (certificate rotation, list builds, rollouts) share one guard. (Admin tools)
  • A propagation canary measures, per PoP, the time from a profile change to it being applied, with alerts; opdns-cp admin profiles status|replay|republish|reconcile|snapshot inspects and repairs the profile stream. (Profile propagation)
  • opdns-cp admin profile list|get|create|set and opdns-cp admin operator block list|add|remove, audited like the API. (Admin tools)
  • opdns-cp backup: encrypted Postgres archives every hour, native ClickHouse backups every day, retention, scheduled restore tests and alerts. (Backups and restore)
  • opdns-lists lookup -why names the source line behind a blocked name, diff compares two published versions, and gate previews the publish gates. (Why is a name blocked?)
  • Unbound statistics as metrics with a dashboard row and two alerts; the edge sizes the Go runtime from its container’s limits. (Resolver operations)
  • Alert delivery: Alertmanager routes pages and warnings to their receivers with inhibition, and a dead-man check pages when the alerting heartbeat stops for 5 minutes; node_exporter on every PoP server with nine host alerts. (Alerting)
  • GeoIP (a MaxMind-format country database, reloaded when replaced) and owner classification, stamped on cloud log rows at ingest. (GeoIP and owner classification)
  • List reports: a triage API for operators and opdns-cp admin list-reports export, which turns accepted reports into guard and gate-override candidates for review. (List reports)
  • The local simulation has an offline mode, solo modes per track, enforced loop-speed and footprint budgets, an ambient traffic generator and a clock-skew chaos scenario; CI gains a solo-edge job and a nightly workflow. (The development environment)
  • A shared integration test harness with throw-away services and fakes of the edge and the node, and a lint of the OpenAPI document in CI. (Integration tests)
  • Domain logging off is now applied on the PoP: the name, the answer addresses and rule text never leave the machine. Before, they were removed later, at ingest.
  • Profiles with query logs off now get hourly counts of their queries, so Analytics totals and the timeline work with logs off.
  • A DNS-over-TLS or DNS-over-QUIC server name that asks for a profile but is malformed (a typo in the id, a missing hyphen) is now refused with an error instead of being answered unfiltered.
  • EDNS Client Subnet has three modes per profile: off (the default), anonymised (/24 and /56) and full (your address). Forwarding is not yet switched on at the PoPs, so for now every mode behaves as off.
  • Operator blocks carry a reason code (legal_order, abuse or csam) and a public reference in the error text, and always answer NXDOMAIN. Queries blocked by a CSAM entry are never logged.
  • Operators can block abusive client addresses fleet-wide or per PoP or country, for a limited time.
  • Devices: the devices seen on a profile, with rename, kind, notes and forget. Display names show in Logs and Analytics. (Devices)
  • Parental control uses a real catalogue: 13 categories and 46 services, each service with a note on what else stops working, each category with its sources and their licences. (Parental control)
  • Setup downloads an iOS and macOS configuration profile, for DNS-over-HTTPS or DNS-over-TLS, with the device name filled in. It is not signed yet. (iOS)
  • Account: export all your data as a zip, and delete your account with a 7-day period in which you can change your mind. (Account)
  • Operator pages for operator and source blocks, visible only to operator accounts. (Operator and source blocks)
  • Settings has a choice of EDNS Client Subnet mode. (Settings)
  • Nodes learn the list signing key from the cloud (or from the public latest.json in standalone mode) and keep it for offline restarts, so no key has to be configured.
  • A node that is not set up no longer resolves unfiltered: it prints how to enrol and exits.
  • A hardened systemd unit ships in the repository, with install steps.
  • Renewed TLS certificates are picked up without a restart; systemctl reload forces a reload.
  • opdns-node unenrol also forgets the list keys learnt from the cloud.
  • Parental categories and services are curated in the repository (data/parental/), reviewed by pull request, and compiled into the signed list artifact. Sources whose licence is under review are used by the cloud only; self-hosted nodes do not receive them.
  • Privacy policy addendum on EDNS Client Subnet, and a status note: domain logging off on the PoP and counters for logs-off profiles now match what the policy states.