Skip to content

lib/rules: add rpz-passthru support + fix ZLA overwrite bug#142

Open
mmbeanz wants to merge 2 commits into
CZ-NIC:masterfrom
mmbeanz:rpz-passthru
Open

lib/rules: add rpz-passthru support + fix ZLA overwrite bug#142
mmbeanz wants to merge 2 commits into
CZ-NIC:masterfrom
mmbeanz:rpz-passthru

Conversation

@mmbeanz

@mmbeanz mmbeanz commented Apr 12, 2026

Copy link
Copy Markdown

Summary

Two related fixes for RPZ handling in the LMDB rules engine: the first is a standalone correctness bug, the second was the original motivation.

Commits

1. fix rule_local_subtree() silently discarding overwrites

ruledb_op(write) uses MDB_NOOVERWRITE, so calling
rule_local_subtree() for a name that already has a ZLA entry silently
fails and keeps the old value. In release builds kr_assert() is a
no-op so this goes completely unnoticed.

Fixed by doing remove-then-write, mirroring the existing pattern in
kr_rule_tag_add() which already has an explicit comment about this.

2. add RPZ rpz-passthru support

CNAME .rpz-passthru. records are currently skipped with:
[rules] skipping unsupported CNAME target .rpz-passthru

This was noted on the mailing list (Dec 2025): https://lists.nic.cz/hyperkitty/list/knot-resolver-users@lists.nic.cz/thread/6HL6T6NTKUPM3AWAOIH4TR77FYNFDMKU/

Adds KR_RULE_SUB_PASSTHRU as a new ZLA action type. When matched, RET_CONT_CACHE is returned immediately, falling through to recursive resolution and bypassing any remaining local rules.

Wildcard passthru records are handled by stripping the wildcard label before inserting the ZLA entry, consistent with how CNAME . records are processed.

Context

We run a large blocklist (~2.7M RPZ entries) and needed per-domain whitelist overrides without rebuilding the whole zone. Tested on Knot Resolver 6.2.0, Arch Linux.

Load order note: whitelist RPZ should be listed last in config so PASSTHRU entries overwrite DENY entries from earlier files.

mmbeanz added 2 commits April 12, 2026 14:57
ruledb_op(write) uses MDB_NOOVERWRITE, so calling rule_local_subtree()
for a name that already has a ZLA entry silently fails and keeps the
old value. In release builds kr_assert() is a no-op, so this goes
completely unnoticed.

Fix by doing remove-then-write, mirroring the existing pattern in
kr_rule_tag_add() which has an explicit comment about this behavior.

This affects any scenario where RPZ files are loaded in sequence and
a later file is expected to override an earlier one for the same name.
RPZ zones can use CNAME .rpz-passthru. to mark domains that should
bypass blocking rules — the standard use case being a whitelist that
takes precedence over a blocklist loaded from the same or a later file.

Currently these records are skipped with a warning:
  [rules] skipping unsupported CNAME target .rpz-passthru

This adds KR_RULE_SUB_PASSTHRU as a new ZLA action type. When matched
during query processing, it returns RET_CONT_CACHE immediately, falling
through to normal recursive resolution and skipping any remaining local
rules for that subtree.

Wildcard passthru records (*.example.com CNAME .rpz-passthru.) are
handled by stripping the wildcard label before inserting the ZLA entry,
consistent with how CNAME . (NXDOMAIN) records are processed.

Load order matters: since ZLA entries use last-write-wins semantics
(after the fix in the previous commit), the whitelist RPZ file should
be listed last in the config so its PASSTHRU entries overwrite any
DENY entries from earlier files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant