From b7845f45eedf9ec26587bb082cb99d81c442e5ee Mon Sep 17 00:00:00 2001 From: Alexy Khrabrov Date: Sat, 12 Sep 2026 16:38:31 +0200 Subject: [PATCH] Publish the newer of the source and stored ACME serials (0.6.4) with_acme_overlay replaced an ACME-managed zone's SOA serial with the stored acme-serials value unconditionally. After an operator edit with a higher serial, the primary kept publishing the older ACME serial, so secondaries never transferred the change and deployments that wait for the new serial failed. Keep the newer of the two in RFC 1982 order; the next ACME update already advances past both through next_serial. Found in production: devreal.ai at 2026091201 in the source data kept publishing 2026081503 from acme-serials. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Cs9W8zZ4hWHGUfoQEydTab --- CHANGELOG.md | 9 +++++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 4 ++-- debian/changelog | 7 +++++++ debian/rgbdns.7 | 2 +- docs/DEBIAN.md | 8 ++++---- docs/DNSSEC-DESIGN.md | 4 ++-- docs/DNSSEC.md | 4 ++-- docs/OPENSUSE.md | 14 ++++++------- docs/RGBDNS_SETUP.md | 18 ++++++++--------- docs/conformance.md | 2 +- man/acme-materialize.1 | 2 +- man/aname-materialize.1 | 2 +- man/axfr-get.1 | 2 +- man/axfrdns-conf.1 | 2 +- man/axfrdns.1 | 2 +- man/compile-zone.8 | 2 +- man/dnscache-conf.1 | 2 +- man/dnscache.1 | 2 +- man/dnsfilter.1 | 2 +- man/dnsip.1 | 2 +- man/dnsip6.1 | 2 +- man/dnsip6q.1 | 2 +- man/dnsipq.1 | 2 +- man/dnsmx.1 | 2 +- man/dnsname.1 | 2 +- man/dnsq.1 | 2 +- man/dnsqr.1 | 2 +- man/dnstrace.1 | 2 +- man/dnstxt.1 | 2 +- man/multilog.1 | 2 +- man/pickdns-conf.1 | 2 +- man/pickdns-data.1 | 2 +- man/pickdns.1 | 2 +- man/random-ip.1 | 2 +- man/rbldns-conf.1 | 2 +- man/rbldns-data.1 | 2 +- man/rbldns.1 | 2 +- man/rgbdns-acme.1 | 2 +- man/rgbdns-log-report.1 | 2 +- man/rgbdns-setup.8 | 2 +- man/rgbsec-check.1 | 2 +- man/rgbsec-data.1 | 2 +- man/rgbsec-ds.1 | 2 +- man/rgbsec-keygen.1 | 2 +- man/rgbsec-sign.1 | 2 +- man/secondary-sync.8 | 2 +- man/setuidgid.1 | 2 +- man/tai64n.1 | 2 +- man/tai64nlocal.1 | 2 +- man/tinydns-conf.1 | 2 +- man/tinydns-data.1 | 2 +- man/tinydns-edit.1 | 2 +- man/tinydns-get.1 | 2 +- man/tinydns.1 | 2 +- man/walldns-conf.1 | 2 +- man/walldns.1 | 2 +- packaging/rpm/rgbdns.spec | 5 ++++- src/zone.rs | 42 ++++++++++++++++++++++++++++++++++++++- 60 files changed, 137 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c190922..7e2fe64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ versioning once its djbdns-compatible public surface stabilizes. ## [Unreleased] +## [0.6.4] - 2026-09-12 + +### Fixed + +- Publish the newer (RFC 1982 order) of the source data's SOA serial and the + stored ACME serial for ACME-managed zones. The stored serial used to replace + the source serial unconditionally, so an operator's edit with a higher serial + kept publishing the older ACME serial and secondaries never transferred it. + ## [0.6.3] - 2026-08-20 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 124fcaf..e87c0ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1135,7 +1135,7 @@ checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "rgbdns" -version = "0.6.3" +version = "0.6.4" dependencies = [ "async-trait", "base64", diff --git a/Cargo.toml b/Cargo.toml index 1a07d22..1a705b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rgbdns" -version = "0.6.3" +version = "0.6.4" edition = "2024" license = "Unlicense" description = "A safe, faithful Rust reimplementation of the djbdns suite" diff --git a/README.md b/README.md index 95e89dc..54e5265 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,7 @@ On Debian or Ubuntu, build the package with: ```sh sudo apt install build-essential cargo debhelper rustc packaging/build-deb.sh -sudo apt install ../rgbdns_0.6.3_$(dpkg --print-architecture).deb +sudo apt install ../rgbdns_0.6.4_$(dpkg --print-architecture).deb ``` On openSUSE Leap 16.0, build the RPM with: @@ -182,7 +182,7 @@ sudo zypper --non-interactive install \ git cargo rust python3 rpm-build systemd-rpm-macros packaging/build-rpm.sh sudo zypper --non-interactive --no-gpg-checks install \ - dist/rpmbuild/RPMS/x86_64/rgbdns-0.6.3-1.x86_64.rpm + dist/rpmbuild/RPMS/x86_64/rgbdns-0.6.4-1.x86_64.rpm ``` ## Book diff --git a/debian/changelog b/debian/changelog index c2dbf28..c799837 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +rgbdns (0.6.4) unstable; urgency=medium + + * Publish the newer of the source data serial and the stored ACME serial for + ACME-managed zones, so operator edits reach secondaries. + + -- Alexy Khrabrov Sat, 12 Sep 2026 08:00:00 -0700 + rgbdns (0.6.3) unstable; urgency=medium * Answer mixed-case negative queries with signed NSEC proofs instead of diff --git a/debian/rgbdns.7 b/debian/rgbdns.7 index 715a837..fdd4b04 100644 --- a/debian/rgbdns.7 +++ b/debian/rgbdns.7 @@ -1,4 +1,4 @@ -.TH RGBDNS 7 "2026-08-18" "rgbdns 0.6.3" "System Administration" +.TH RGBDNS 7 "2026-08-18" "rgbdns 0.6.4" "System Administration" .SH NAME rgbdns \- authoritative DNS, AXFR, recursion, and djbdns-compatible tools .SH SYNOPSIS diff --git a/docs/DEBIAN.md b/docs/DEBIAN.md index 29a385f..e426a5d 100644 --- a/docs/DEBIAN.md +++ b/docs/DEBIAN.md @@ -20,7 +20,7 @@ sudo apt install build-essential cargo debhelper rustc git clone https://github.com/querygraph/rgbdns.git cd rgbdns packaging/build-deb.sh -sudo apt install ../rgbdns_0.6.3_$(dpkg --print-architecture).deb +sudo apt install ../rgbdns_0.6.4_$(dpkg --print-architecture).deb ``` `packaging/build-deb.sh` calls `dpkg-buildpackage --build=binary --no-sign`. @@ -258,16 +258,16 @@ sudo apt install -y build-essential cargo debhelper rustc git git clone https://github.com/querygraph/rgbdns.git cd rgbdns packaging/build-deb.sh -dpkg-deb --info ../rgbdns_0.6.3_amd64.deb +dpkg-deb --info ../rgbdns_0.6.4_amd64.deb ``` Copy the package to the EC2 host, then install it there: ```sh -scp ../rgbdns_0.6.3_amd64.deb admin@52.10.53.234:/tmp/ +scp ../rgbdns_0.6.4_amd64.deb admin@52.10.53.234:/tmp/ ssh admin@52.10.53.234 sudo apt update -sudo apt install -y /tmp/rgbdns_0.6.3_amd64.deb +sudo apt install -y /tmp/rgbdns_0.6.4_amd64.deb dpkg-query -W rgbdns ``` diff --git a/docs/DNSSEC-DESIGN.md b/docs/DNSSEC-DESIGN.md index 5db5c89..8ca78e5 100644 --- a/docs/DNSSEC-DESIGN.md +++ b/docs/DNSSEC-DESIGN.md @@ -1,6 +1,6 @@ # DNSSEC design: small tools and visible state -Status: implementation contract for rgbdns 0.6.3. +Status: implementation contract for rgbdns 0.6.4. rgbdns DNSSEC follows the tinydns posture: each program does one bounded job, configuration is one record per line, persistent state is an ordinary file, and @@ -152,7 +152,7 @@ they do not resolve the target independently for a signed zone. Key creation, activation, parent DS publication, rollover, revocation, and retirement are distinct operator actions represented by files and policy -lines. Version 0.6.3 delivers safe single-key operation and DS derivation. A +lines. Version 0.6.4 delivers safe single-key operation and DS derivation. A later feature release will add a deliberately specified multi-key rollover state machine; operators must not simulate rollover by silently swapping a key file under an unchanged policy line. diff --git a/docs/DNSSEC.md b/docs/DNSSEC.md index 44895be..d54a58c 100644 --- a/docs/DNSSEC.md +++ b/docs/DNSSEC.md @@ -1,6 +1,6 @@ # Optional authoritative DNSSEC -rgbdns 0.6.3 adds authoritative DNSSEC as an explicit offline publication +rgbdns 0.6.4 adds authoritative DNSSEC as an explicit offline publication pipeline. It is disabled by default. If `/etc/rgbdns/dnssec.env` and the working-directory `dnssec` policy are absent, `tinydns-data`, `tinydns`, ACME, ANAME, setup, and secondary synchronization follow the existing @@ -43,7 +43,7 @@ This permits a deliberate mixed signed/unsigned CDB without making omission mean “unsigned.” Keep a recoverable encrypted backup of the key. Key replacement is not an -implicit file operation: version 0.6.3 deliberately supports one active +implicit file operation: version 0.6.4 deliberately supports one active combined signing key per zone and does not claim an automated multi-key rollover state machine. diff --git a/docs/OPENSUSE.md b/docs/OPENSUSE.md index e6df6f6..4c6dcb5 100644 --- a/docs/OPENSUSE.md +++ b/docs/OPENSUSE.md @@ -55,8 +55,8 @@ sudo zypper --non-interactive install \ git clone https://github.com/querygraph/rgbdns.git cd rgbdns packaging/build-rpm.sh -rpm -qip dist/rpmbuild/RPMS/x86_64/rgbdns-0.6.3-1.x86_64.rpm -rpm -qlp dist/rpmbuild/RPMS/x86_64/rgbdns-0.6.3-1.x86_64.rpm +rpm -qip dist/rpmbuild/RPMS/x86_64/rgbdns-0.6.4-1.x86_64.rpm +rpm -qlp dist/rpmbuild/RPMS/x86_64/rgbdns-0.6.4-1.x86_64.rpm ``` `build-rpm.sh` creates a clean rpmbuild tree under `dist/rpmbuild`, archives @@ -81,9 +81,9 @@ gh run download RUN_ID \ Inspect an artifact before installation: ```sh -rpm -K dist/cloud-rpm/rgbdns-0.6.3-1.x86_64.rpm -rpm -qip dist/cloud-rpm/rgbdns-0.6.3-1.x86_64.rpm -rpm -qlp dist/cloud-rpm/rgbdns-0.6.3-1.x86_64.rpm +rpm -K dist/cloud-rpm/rgbdns-0.6.4-1.x86_64.rpm +rpm -qip dist/cloud-rpm/rgbdns-0.6.4-1.x86_64.rpm +rpm -qlp dist/cloud-rpm/rgbdns-0.6.4-1.x86_64.rpm ``` The development RPM is not repository-signed. `rpm -K` still verifies the @@ -96,11 +96,11 @@ Copy a locally built package to the EC2 instance: ```sh scp -i ~/.ssh/KEY.pem \ - dist/rpmbuild/RPMS/x86_64/rgbdns-0.6.3-1.x86_64.rpm \ + dist/rpmbuild/RPMS/x86_64/rgbdns-0.6.4-1.x86_64.rpm \ ec2-user@PUBLIC_ADDRESS:/tmp/ ssh -i ~/.ssh/KEY.pem ec2-user@PUBLIC_ADDRESS sudo zypper --non-interactive --no-gpg-checks install \ - /tmp/rgbdns-0.6.3-1.x86_64.rpm + /tmp/rgbdns-0.6.4-1.x86_64.rpm rpm -q rgbdns rpm -V rgbdns ``` diff --git a/docs/RGBDNS_SETUP.md b/docs/RGBDNS_SETUP.md index ca4c703..d7da115 100644 --- a/docs/RGBDNS_SETUP.md +++ b/docs/RGBDNS_SETUP.md @@ -1,6 +1,6 @@ # End-to-end rgbdns setup: `fieldnotes.es` -This walkthrough deploys rgbdns 0.6.3 on two AWS EC2 instances and retains +This walkthrough deploys rgbdns 0.6.4 on two AWS EC2 instances and retains BuddyNS as an additional secondary network. It covers installation, initial role configuration, authoritative data, AXFR, atomic primary and secondary updates, verification, upgrades, and recovery. @@ -118,12 +118,12 @@ gh run download "$RPM_RUN" \ -D "$HOME/rgbdns-rpm" ``` -The 0.6.3 artifacts are: +The 0.6.4 artifacts are: ```text -rgbdns_0.6.3_amd64.deb -RPMS/x86_64/rgbdns-0.6.3-1.x86_64.rpm -SRPMS/rgbdns-0.6.3-1.src.rpm +rgbdns_0.6.4_amd64.deb +RPMS/x86_64/rgbdns-0.6.4-1.x86_64.rpm +SRPMS/rgbdns-0.6.4-1.src.rpm ``` ## 4. Install the Debian package on the primary @@ -131,14 +131,14 @@ SRPMS/rgbdns-0.6.3-1.src.rpm Copy the package: ```sh -scp "$HOME/rgbdns-deb/rgbdns_0.6.3_amd64.deb" \ +scp "$HOME/rgbdns-deb/rgbdns_0.6.4_amd64.deb" \ bitnami@52.10.53.234:/tmp/ ``` On the primary: ```sh -sudo apt install /tmp/rgbdns_0.6.3_amd64.deb +sudo apt install /tmp/rgbdns_0.6.4_amd64.deb sudo systemctl daemon-reload dpkg-query -W -f='${Package} ${Version}\n' rgbdns getent passwd rgbdns @@ -160,7 +160,7 @@ SUSE_USER=ec2-user Copy the package: ```sh -scp "$HOME/rgbdns-rpm/RPMS/x86_64/rgbdns-0.6.3-1.x86_64.rpm" \ +scp "$HOME/rgbdns-rpm/RPMS/x86_64/rgbdns-0.6.4-1.x86_64.rpm" \ "$SUSE_USER"@52.38.177.160:/tmp/ ``` @@ -168,7 +168,7 @@ On the secondary: ```sh sudo zypper --non-interactive --no-gpg-checks install \ - /tmp/rgbdns-0.6.3-1.x86_64.rpm + /tmp/rgbdns-0.6.4-1.x86_64.rpm sudo systemctl daemon-reload rpm -q rgbdns sudo rpm -V rgbdns diff --git a/docs/conformance.md b/docs/conformance.md index 21bf012..d3e172d 100644 --- a/docs/conformance.md +++ b/docs/conformance.md @@ -52,7 +52,7 @@ normative RFC that supplies each oracle. ## Deliberate scope boundaries -The following are not claimed as implemented by rgbdns 0.6.3: +The following are not claimed as implemented by rgbdns 0.6.4: - general-purpose dynamic UPDATE, NOTIFY, IXFR, DSO, DNS Cookies, or SIG(0); - TSIG algorithms other than the ACME update profile's HMAC-SHA256; diff --git a/man/acme-materialize.1 b/man/acme-materialize.1 index 2ba2515..1a09071 100644 --- a/man/acme-materialize.1 +++ b/man/acme-materialize.1 @@ -1,4 +1,4 @@ -.TH ACME-MATERIALIZE 1 "2026-08-18" "rgbdns 0.6.3" "User Commands" +.TH ACME-MATERIALIZE 1 "2026-08-18" "rgbdns 0.6.4" "User Commands" .SH NAME acme-materialize \- merge durable ACME DNS-01 state into tinydns source .SH SYNOPSIS diff --git a/man/aname-materialize.1 b/man/aname-materialize.1 index a52c2ea..63ee64c 100644 --- a/man/aname-materialize.1 +++ b/man/aname-materialize.1 @@ -1,4 +1,4 @@ -.TH ANAME-MATERIALIZE 1 "2026-08-18" "rgbdns 0.6.3" "User Commands" +.TH ANAME-MATERIALIZE 1 "2026-08-18" "rgbdns 0.6.4" "User Commands" .SH NAME aname-materialize \- replace rgbdns ANAME directives with address records .SH SYNOPSIS diff --git a/man/axfr-get.1 b/man/axfr-get.1 index a552a24..3c1c34f 100644 --- a/man/axfr-get.1 +++ b/man/axfr-get.1 @@ -1,4 +1,4 @@ -.TH AXFR-GET 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH AXFR-GET 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME axfr-get \- retrieve a DNS zone using AXFR .SH SYNOPSIS diff --git a/man/axfrdns-conf.1 b/man/axfrdns-conf.1 index 6501383..fe87c06 100644 --- a/man/axfrdns-conf.1 +++ b/man/axfrdns-conf.1 @@ -1,4 +1,4 @@ -.TH AXFRDNS-CONF 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH AXFRDNS-CONF 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME axfrdns-conf \- create an axfrdns service directory .SH SYNOPSIS diff --git a/man/axfrdns.1 b/man/axfrdns.1 index 06a9385..0f02d9b 100644 --- a/man/axfrdns.1 +++ b/man/axfrdns.1 @@ -1,4 +1,4 @@ -.TH AXFRDNS 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH AXFRDNS 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME axfrdns \- serve DNS zone transfers .SH SYNOPSIS diff --git a/man/compile-zone.8 b/man/compile-zone.8 index 6d0b4e5..87c18cc 100644 --- a/man/compile-zone.8 +++ b/man/compile-zone.8 @@ -1,4 +1,4 @@ -.TH COMPILE-ZONE 8 "2026-07-23" "rgbdns 0.6.3" "System Administration" +.TH COMPILE-ZONE 8 "2026-07-23" "rgbdns 0.6.4" "System Administration" .SH NAME compile-zone \- compile the packaged authoritative zone .SH SYNOPSIS diff --git a/man/dnscache-conf.1 b/man/dnscache-conf.1 index 6de7df2..72b0234 100644 --- a/man/dnscache-conf.1 +++ b/man/dnscache-conf.1 @@ -1,4 +1,4 @@ -.TH DNSCACHE-CONF 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSCACHE-CONF 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnscache-conf \- create a dnscache service directory .SH SYNOPSIS diff --git a/man/dnscache.1 b/man/dnscache.1 index 9b2927b..1fdb3dd 100644 --- a/man/dnscache.1 +++ b/man/dnscache.1 @@ -1,4 +1,4 @@ -.TH DNSCACHE 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSCACHE 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnscache \- caching recursive DNS resolver .SH SYNOPSIS diff --git a/man/dnsfilter.1 b/man/dnsfilter.1 index c01e62b..98bdd6c 100644 --- a/man/dnsfilter.1 +++ b/man/dnsfilter.1 @@ -1,4 +1,4 @@ -.TH DNSFILTER 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSFILTER 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnsfilter \- add reverse DNS names to input lines .SH SYNOPSIS diff --git a/man/dnsip.1 b/man/dnsip.1 index 5bce827..6adb185 100644 --- a/man/dnsip.1 +++ b/man/dnsip.1 @@ -1,4 +1,4 @@ -.TH DNSIP 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSIP 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnsip \- look up IPv4 addresses .SH SYNOPSIS diff --git a/man/dnsip6.1 b/man/dnsip6.1 index 73f7ee7..d428109 100644 --- a/man/dnsip6.1 +++ b/man/dnsip6.1 @@ -1,4 +1,4 @@ -.TH DNSIP6 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSIP6 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnsip6 \- look up IPv6 addresses .SH SYNOPSIS diff --git a/man/dnsip6q.1 b/man/dnsip6q.1 index 7c9d30b..3547408 100644 --- a/man/dnsip6q.1 +++ b/man/dnsip6q.1 @@ -1,4 +1,4 @@ -.TH DNSIP6Q 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSIP6Q 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnsip6q \- look up and label IPv6 addresses .SH SYNOPSIS diff --git a/man/dnsipq.1 b/man/dnsipq.1 index 0a6b933..8f4b596 100644 --- a/man/dnsipq.1 +++ b/man/dnsipq.1 @@ -1,4 +1,4 @@ -.TH DNSIPQ 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSIPQ 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnsipq \- look up and label IPv4 addresses .SH SYNOPSIS diff --git a/man/dnsmx.1 b/man/dnsmx.1 index 7d77c92..6df8452 100644 --- a/man/dnsmx.1 +++ b/man/dnsmx.1 @@ -1,4 +1,4 @@ -.TH DNSMX 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSMX 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnsmx \- look up mail exchangers .SH SYNOPSIS diff --git a/man/dnsname.1 b/man/dnsname.1 index 12e73eb..102e7be 100644 --- a/man/dnsname.1 +++ b/man/dnsname.1 @@ -1,4 +1,4 @@ -.TH DNSNAME 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSNAME 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnsname \- look up names for IPv4 addresses .SH SYNOPSIS diff --git a/man/dnsq.1 b/man/dnsq.1 index 1a9b619..e797970 100644 --- a/man/dnsq.1 +++ b/man/dnsq.1 @@ -1,4 +1,4 @@ -.TH DNSQ 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSQ 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnsq \- send a non-recursive DNS query .SH SYNOPSIS diff --git a/man/dnsqr.1 b/man/dnsqr.1 index 070e1e0..1bad214 100644 --- a/man/dnsqr.1 +++ b/man/dnsqr.1 @@ -1,4 +1,4 @@ -.TH DNSQR 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSQR 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnsqr \- perform a recursive DNS query .SH SYNOPSIS diff --git a/man/dnstrace.1 b/man/dnstrace.1 index edac1c3..701a222 100644 --- a/man/dnstrace.1 +++ b/man/dnstrace.1 @@ -1,4 +1,4 @@ -.TH DNSTRACE 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSTRACE 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnstrace \- trace DNS delegation .SH SYNOPSIS diff --git a/man/dnstxt.1 b/man/dnstxt.1 index 01be272..fdc92e1 100644 --- a/man/dnstxt.1 +++ b/man/dnstxt.1 @@ -1,4 +1,4 @@ -.TH DNSTXT 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH DNSTXT 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME dnstxt \- look up DNS text records .SH SYNOPSIS diff --git a/man/multilog.1 b/man/multilog.1 index 98dfd45..fc6f1ee 100644 --- a/man/multilog.1 +++ b/man/multilog.1 @@ -1,4 +1,4 @@ -.TH MULTILOG 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH MULTILOG 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME multilog \- collect and rotate service logs .SH SYNOPSIS diff --git a/man/pickdns-conf.1 b/man/pickdns-conf.1 index b1404bb..c4c0234 100644 --- a/man/pickdns-conf.1 +++ b/man/pickdns-conf.1 @@ -1,4 +1,4 @@ -.TH PICKDNS-CONF 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH PICKDNS-CONF 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME pickdns-conf \- create a pickdns service directory .SH SYNOPSIS diff --git a/man/pickdns-data.1 b/man/pickdns-data.1 index c6a18b3..1402533 100644 --- a/man/pickdns-data.1 +++ b/man/pickdns-data.1 @@ -1,4 +1,4 @@ -.TH PICKDNS-DATA 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH PICKDNS-DATA 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME pickdns-data \- compile a pickdns database .SH SYNOPSIS diff --git a/man/pickdns.1 b/man/pickdns.1 index a673597..6bb489d 100644 --- a/man/pickdns.1 +++ b/man/pickdns.1 @@ -1,4 +1,4 @@ -.TH PICKDNS 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH PICKDNS 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME pickdns \- serve location-dependent DNS data .SH SYNOPSIS diff --git a/man/random-ip.1 b/man/random-ip.1 index d0649d6..4e73e6d 100644 --- a/man/random-ip.1 +++ b/man/random-ip.1 @@ -1,4 +1,4 @@ -.TH RANDOM-IP 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH RANDOM-IP 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME random-ip \- generate shuffled IPv4 addresses .SH SYNOPSIS diff --git a/man/rbldns-conf.1 b/man/rbldns-conf.1 index f5fb002..4669efe 100644 --- a/man/rbldns-conf.1 +++ b/man/rbldns-conf.1 @@ -1,4 +1,4 @@ -.TH RBLDNS-CONF 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH RBLDNS-CONF 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME rbldns-conf \- create an rbldns service directory .SH SYNOPSIS diff --git a/man/rbldns-data.1 b/man/rbldns-data.1 index 875d5cd..39765fb 100644 --- a/man/rbldns-data.1 +++ b/man/rbldns-data.1 @@ -1,4 +1,4 @@ -.TH RBLDNS-DATA 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH RBLDNS-DATA 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME rbldns-data \- compile an rbldns database .SH SYNOPSIS diff --git a/man/rbldns.1 b/man/rbldns.1 index 524b124..d475896 100644 --- a/man/rbldns.1 +++ b/man/rbldns.1 @@ -1,4 +1,4 @@ -.TH RBLDNS 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH RBLDNS 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME rbldns \- serve a DNS block-list database .SH SYNOPSIS diff --git a/man/rgbdns-acme.1 b/man/rgbdns-acme.1 index 568fe1e..8e145d7 100644 --- a/man/rgbdns-acme.1 +++ b/man/rgbdns-acme.1 @@ -1,4 +1,4 @@ -.TH RGBDNS-ACME 1 "2026-08-18" "rgbdns 0.6.3" +.TH RGBDNS-ACME 1 "2026-08-18" "rgbdns 0.6.4" .SH NAME rgbdns-acme \- manage ACME DNS-01 TXT state through rgbdns .SH SYNOPSIS diff --git a/man/rgbdns-log-report.1 b/man/rgbdns-log-report.1 index 8e55494..fd17684 100644 --- a/man/rgbdns-log-report.1 +++ b/man/rgbdns-log-report.1 @@ -1,4 +1,4 @@ -.TH RGBDNS-LOG-REPORT 1 "2026-08-18" "rgbdns 0.6.3" +.TH RGBDNS-LOG-REPORT 1 "2026-08-18" "rgbdns 0.6.4" .SH NAME rgbdns-log-report \- aggregate rgbdns query logs by authoritative zone .SH SYNOPSIS diff --git a/man/rgbdns-setup.8 b/man/rgbdns-setup.8 index 5855109..6a27be6 100644 --- a/man/rgbdns-setup.8 +++ b/man/rgbdns-setup.8 @@ -1,4 +1,4 @@ -.TH RGBDNS-SETUP 8 "2026-07-26" "rgbdns 0.6.3" "System Administration" +.TH RGBDNS-SETUP 8 "2026-07-26" "rgbdns 0.6.4" "System Administration" .SH NAME rgbdns-setup \- configure a packaged rgbdns primary or secondary .SH SYNOPSIS diff --git a/man/rgbsec-check.1 b/man/rgbsec-check.1 index c6e7bdb..78db9de 100644 --- a/man/rgbsec-check.1 +++ b/man/rgbsec-check.1 @@ -1,4 +1,4 @@ -.TH RGBSEC-CHECK 1 "2026-08-19" "rgbdns 0.6.3" "User Commands" +.TH RGBSEC-CHECK 1 "2026-08-19" "rgbdns 0.6.4" "User Commands" .SH NAME rgbsec-check \- verify an rgbdns signed snapshot and signature lifetime .SH SYNOPSIS diff --git a/man/rgbsec-data.1 b/man/rgbsec-data.1 index 626eb4d..b6b77cf 100644 --- a/man/rgbsec-data.1 +++ b/man/rgbsec-data.1 @@ -1,4 +1,4 @@ -.TH RGBSEC-DATA 1 "2026-08-19" "rgbdns 0.6.3" "User Commands" +.TH RGBSEC-DATA 1 "2026-08-19" "rgbdns 0.6.4" "User Commands" .SH NAME rgbsec-data \- sign and compile an rgbdns DNSSEC snapshot .SH SYNOPSIS diff --git a/man/rgbsec-ds.1 b/man/rgbsec-ds.1 index 6aa45d5..2a366bd 100644 --- a/man/rgbsec-ds.1 +++ b/man/rgbsec-ds.1 @@ -1,4 +1,4 @@ -.TH RGBSEC-DS 1 "2026-08-19" "rgbdns 0.6.3" "User Commands" +.TH RGBSEC-DS 1 "2026-08-19" "rgbdns 0.6.4" "User Commands" .SH NAME rgbsec-ds \- derive the parent DS record from an rgbdns DNSSEC policy .SH SYNOPSIS diff --git a/man/rgbsec-keygen.1 b/man/rgbsec-keygen.1 index 0db228c..dd6cff0 100644 --- a/man/rgbsec-keygen.1 +++ b/man/rgbsec-keygen.1 @@ -1,4 +1,4 @@ -.TH RGBSEC-KEYGEN 1 "2026-08-19" "rgbdns 0.6.3" "User Commands" +.TH RGBSEC-KEYGEN 1 "2026-08-19" "rgbdns 0.6.4" "User Commands" .SH NAME rgbsec-keygen \- create an rgbdns DNSSEC signing key and policy line .SH SYNOPSIS diff --git a/man/rgbsec-sign.1 b/man/rgbsec-sign.1 index e35cdc9..232619a 100644 --- a/man/rgbsec-sign.1 +++ b/man/rgbsec-sign.1 @@ -1,4 +1,4 @@ -.TH RGBSEC-SIGN 1 "2026-08-19" "rgbdns 0.6.3" "User Commands" +.TH RGBSEC-SIGN 1 "2026-08-19" "rgbdns 0.6.4" "User Commands" .SH NAME rgbsec-sign \- sign tinydns source as an offline DNSSEC snapshot .SH SYNOPSIS diff --git a/man/secondary-sync.8 b/man/secondary-sync.8 index d3d8f39..e1fddc4 100644 --- a/man/secondary-sync.8 +++ b/man/secondary-sync.8 @@ -1,4 +1,4 @@ -.TH SECONDARY-SYNC 8 "2026-07-23" "rgbdns 0.6.3" "System Administration" +.TH SECONDARY-SYNC 8 "2026-07-23" "rgbdns 0.6.4" "System Administration" .SH NAME secondary-sync \- refresh the packaged secondary zone .SH SYNOPSIS diff --git a/man/setuidgid.1 b/man/setuidgid.1 index 50107bc..1b8b9a7 100644 --- a/man/setuidgid.1 +++ b/man/setuidgid.1 @@ -1,4 +1,4 @@ -.TH SETUIDGID 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH SETUIDGID 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME setuidgid \- run a program with another account's identity .SH SYNOPSIS diff --git a/man/tai64n.1 b/man/tai64n.1 index 76d7a4e..34e60cc 100644 --- a/man/tai64n.1 +++ b/man/tai64n.1 @@ -1,4 +1,4 @@ -.TH TAI64N 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH TAI64N 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME tai64n \- prefix lines with precise timestamps .SH SYNOPSIS diff --git a/man/tai64nlocal.1 b/man/tai64nlocal.1 index f6ab95b..7aa9f9f 100644 --- a/man/tai64nlocal.1 +++ b/man/tai64nlocal.1 @@ -1,4 +1,4 @@ -.TH TAI64NLOCAL 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH TAI64NLOCAL 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME tai64nlocal \- convert TAI64N timestamps to local time .SH SYNOPSIS diff --git a/man/tinydns-conf.1 b/man/tinydns-conf.1 index c977efa..28bf545 100644 --- a/man/tinydns-conf.1 +++ b/man/tinydns-conf.1 @@ -1,4 +1,4 @@ -.TH TINYDNS-CONF 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH TINYDNS-CONF 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME tinydns-conf \- create a tinydns service directory .SH SYNOPSIS diff --git a/man/tinydns-data.1 b/man/tinydns-data.1 index 4279ee1..7d5a9c4 100644 --- a/man/tinydns-data.1 +++ b/man/tinydns-data.1 @@ -1,4 +1,4 @@ -.TH TINYDNS-DATA 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH TINYDNS-DATA 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME tinydns-data \- compile a tinydns zone database .SH SYNOPSIS diff --git a/man/tinydns-edit.1 b/man/tinydns-edit.1 index 4bcf282..f3113c7 100644 --- a/man/tinydns-edit.1 +++ b/man/tinydns-edit.1 @@ -1,4 +1,4 @@ -.TH TINYDNS-EDIT 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH TINYDNS-EDIT 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME tinydns-edit \- add a record to tinydns source data .SH SYNOPSIS diff --git a/man/tinydns-get.1 b/man/tinydns-get.1 index 5392ece..8973aa1 100644 --- a/man/tinydns-get.1 +++ b/man/tinydns-get.1 @@ -1,4 +1,4 @@ -.TH TINYDNS-GET 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH TINYDNS-GET 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME tinydns-get \- inspect an answer from tinydns source data .SH SYNOPSIS diff --git a/man/tinydns.1 b/man/tinydns.1 index 6da250d..2d57c5d 100644 --- a/man/tinydns.1 +++ b/man/tinydns.1 @@ -1,4 +1,4 @@ -.TH TINYDNS 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH TINYDNS 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME tinydns \- authoritative DNS server .SH SYNOPSIS diff --git a/man/walldns-conf.1 b/man/walldns-conf.1 index 0d00387..9737704 100644 --- a/man/walldns-conf.1 +++ b/man/walldns-conf.1 @@ -1,4 +1,4 @@ -.TH WALLDNS-CONF 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH WALLDNS-CONF 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME walldns-conf \- create a walldns service directory .SH SYNOPSIS diff --git a/man/walldns.1 b/man/walldns.1 index 096897d..bde5ced 100644 --- a/man/walldns.1 +++ b/man/walldns.1 @@ -1,4 +1,4 @@ -.TH WALLDNS 1 "2026-07-23" "rgbdns 0.6.3" "User Commands" +.TH WALLDNS 1 "2026-07-23" "rgbdns 0.6.4" "User Commands" .SH NAME walldns \- provide generic reverse DNS answers .SH SYNOPSIS diff --git a/packaging/rpm/rgbdns.spec b/packaging/rpm/rgbdns.spec index e6f299b..aca5ecd 100644 --- a/packaging/rpm/rgbdns.spec +++ b/packaging/rpm/rgbdns.spec @@ -1,5 +1,5 @@ Name: rgbdns -Version: 0.6.3 +Version: 0.6.4 Release: 1%{?dist} Summary: Memory-safe DNS server and djbdns-compatible tool suite License: Unlicense @@ -171,6 +171,9 @@ fi %{_mandir}/man1/rgbsec-sign.1%{?ext_man} %changelog +* Sat Sep 12 2026 Alexy Khrabrov - 0.6.4-1 +- Publish the newer of the source and stored ACME serials + * Thu Aug 20 2026 Alexy Khrabrov - 0.6.3-1 - Answer 0x20-randomized negative queries with signed NSEC proofs diff --git a/src/zone.rs b/src/zone.rs index 689c3d8..2339470 100644 --- a/src/zone.rs +++ b/src/zone.rs @@ -33,6 +33,15 @@ pub(crate) struct RecordMetadata { pub location: Option<[u8; 2]>, } pub(crate) type MaterializationInput = (Vec, Vec<(Name, Aname)>); +/// The later of two SOA serials in RFC 1982 serial-number order. +pub(crate) fn newer_serial(a: u32, b: u32) -> u32 { + if b != a && b.wrapping_sub(a) < (1 << 31) { + b + } else { + a + } +} + impl Zone { /// Returns a validated snapshot with the supplied ACME TXT overlay and SOA /// serial overrides. The source zone is not modified. @@ -78,7 +87,10 @@ impl Zone { serial: current, .. } = &mut soa.data { - *current = *serial; + // The stored ACME serial only moves forward from updates; a newer + // source serial (an operator's edit) must still publish, or + // secondaries never see the change. + *current = newer_serial(*current, *serial); } } zone.validate_aliases()?; @@ -1217,6 +1229,34 @@ mod tests { )); } + #[test] + fn acme_overlay_publishes_the_newer_of_source_and_stored_serials() { + let zone: Name = "example".parse().unwrap(); + let soa = |base: u32| { + Zone::parse(&format!( + "Zexample:ns.example:hostmaster.example:{base}:16384:2048:1048576:2560:3600\n" + )) + .unwrap() + }; + let published = |base: u32, stored: u32| { + let serials = BTreeMap::from([(zone.clone(), stored)]); + soa(base) + .with_acme_overlay(&[], &serials) + .unwrap() + .soa_serial(&zone) + .unwrap() + }; + // an operator's edit after the last ACME update must still publish + assert_eq!(published(2_026_091_201, 2_026_081_503), 2_026_091_201); + // ACME updates since the last edit keep their higher serial + assert_eq!(published(2_026_081_501, 2_026_081_503), 2_026_081_503); + assert_eq!(published(7, 7), 7); + // RFC 1982 order across the wrap + assert_eq!(published(2, u32::MAX), 2); + assert_eq!(newer_serial(u32::MAX, 2), 2); + assert_eq!(newer_serial(2, u32::MAX), 2); + } + #[test] fn implicit_soa_uses_source_serial_and_generic_types_are_restricted() { let zone = Zone::parse_with_serial(".example::ns.example\n", 1_234_567).unwrap();