Skip to content

feat(querylog): ignore domains (exact/wildcard/regex) in query log - #2084

Merged
0xERR0R merged 7 commits into
mainfrom
feat/querylog-ignore-domains
Jun 5, 2026
Merged

0xERR0R merged 7 commits into
mainfrom
feat/querylog-ignore-domains

Conversation

@0xERR0R

@0xERR0R 0xERR0R commented Jun 4, 2026

Copy link
Copy Markdown
Owner

Summary

Adds queryLog.ignore.domains, letting users exclude queries from the query log by domain name. Each entry is an exact domain, a *.wildcard, or a /regex/ — the same syntax as blocklists. This complements the existing queryLog.ignore.sudn flag.

Motivation (closes #1390): conditional forwarding makes Apple devices flood the query log with repetitive *._dns-sd._udp.* and reverse-lookup *.in-addr.arpa queries. Pi-hole and AdGuard Home already let users suppress such domains; this brings the same capability to Blocky.

queryLog:
  type: postgresql
  target: postgres://user:password@db:5432/blocky_query_log
  ignore:
    sudn: true
    domains:
      - "*._dns-sd._udp.home"
      - "db._dns-sd._udp.home"
      - "/\\.in-addr\\.arpa$/"
      - "apple.com"

Implementation

  • Reuses the existing blocklist matcher (cache/stringcache.ChainedGroupedCache: regex + wildcard + exact) — no new matching logic.
  • The matcher is built once at query-logging-resolver construction from the inline list, and is nil when no domains are configured (zero per-query cost on the common path).
  • Consulted in the existing QueryLoggingResolver.ignore(), matching the question name normalized via util.ExtractDomain (lowercase, trailing dot stripped) — consistent with how blocklist entries are stored.
  • Invalid /regex/ entries are pre-validated with regexp.Compile and warned+skipped at startup (the underlying cache otherwise only logs to a global logger), and a lone "/" entry is rejected rather than crashing.
  • Scope is intentionally minimal (YAGNI): inline rules only — no file/URL sources, no refresh, no per-client rules.

Test plan

  • go build ./...
  • go test ./config/ ./resolver/ (Ginkgo) — exact/wildcard/regex matches excluded, non-matching domains still logged, SUDN unaffected, empty list = fast path, invalid-regex and lone-/ warn+skip without panic
  • go vet ./config/ ./resolver/
  • golangci-lint run ./config/... ./resolver/... — 0 issues
  • Docs updated (docs/configuration.md: table rows + example)

Note for reviewers

While building this I found a pre-existing latent bug in cache/stringcache: regexCacheFactory.addEntry slices entry[1:len(entry)-1] without a length guard, so a lone / entry panics. It's reachable from any list source (e.g. a stray / line in a blocklist). I guarded the new query-log path against it here, but did not touch the shared cache (out of scope for this issue) — worth a separate hardening PR.

Copilot AI review requested due to automatic review settings June 4, 2026 14:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for suppressing specific domains from being written to the query log via a new queryLog.ignore.domains configuration, complementing the existing queryLog.ignore.sudn behavior. This fits into Blocky’s resolver pipeline by filtering log entries at QueryLoggingResolver.ignore() using the existing stringcache matcher stack (regex → wildcard → exact).

Changes:

  • Add queryLog.ignore.domains to config and log output, and build an in-memory matcher at QueryLoggingResolver construction time.
  • Apply the matcher in QueryLoggingResolver.ignore() to skip logging matching domains.
  • Add resolver/config tests and update configuration documentation with the new option and examples.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
resolver/query_logging_resolver.go Builds and applies a domain ignore matcher to skip query log entries.
resolver/query_logging_resolver_test.go Adds tests covering exact/wildcard ignore behavior and matcher construction/validation.
config/query_log.go Extends query log config with ignore.domains and logs configured ignore rules.
config/query_log_test.go Adds tests for logging and YAML parsing of ignore.domains.
docs/configuration.md Documents the new queryLog.ignore.domains option and provides an example config.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread config/query_log.go Outdated
Comment thread docs/configuration.md Outdated
0xERR0R added 2 commits June 5, 2026 08:47
The lone-slash guard only caught "/"; entries like "//" or "/ /" passed
validation and compiled to an empty regex, which matches every domain and
silently dropped the whole query log. Strip the surrounding slashes and reject
any entry whose inner pattern is empty after trimming.
Drop the misleading "same syntax as blocklists" wording (blocklists also
accept ABP markers and IDNA normalization that this field does not) in favor
of the actually-supported forms. Regenerate config.schema.json, which was
missing the ignore.domains field and would have failed generate-check and
emitted a schema-mismatch warning at startup.
@0xERR0R 0xERR0R added this to the v0.32.0 milestone Jun 5, 2026
@0xERR0R 0xERR0R added the 🔨 enhancement New feature or request label Jun 5, 2026
@0xERR0R
0xERR0R enabled auto-merge (squash) June 5, 2026 06:49
@codecov

codecov Bot commented Jun 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.21%. Comparing base (a0fb375) to head (ade31a2).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2084      +/-   ##
==========================================
+ Coverage   86.14%   86.21%   +0.07%     
==========================================
  Files         112      112              
  Lines        8336     8367      +31     
==========================================
+ Hits         7181     7214      +33     
+ Misses        934      932       -2     
  Partials      221      221              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@0xERR0R
0xERR0R merged commit b82199b into main Jun 5, 2026
23 checks passed
@0xERR0R
0xERR0R deleted the feat/querylog-ignore-domains branch June 5, 2026 06:54
dadezzz pushed a commit to dadezzz/infra_docker-compose that referenced this pull request Jun 20, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/0xerr0r/blocky](https://github.com/0xERR0R/blocky) | minor | `v0.31.0` → `v0.32.0` |

---

### Release Notes

<details>
<summary>0xERR0R/blocky (ghcr.io/0xerr0r/blocky)</summary>

### [`v0.32.0`](https://github.com/0xERR0R/blocky/releases/tag/v0.32.0)

[Compare Source](0xERR0R/blocky@v0.31.0...v0.32.0)

#### Changelog

##### Features

- [`c851293`](0xERR0R/blocky@c851293): feat(blocking): log the matched rule in the block reason ([#&#8203;2091](0xERR0R/blocky#2091)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`87be127`](0xERR0R/blocky@87be127): feat(cache): Shard the result cache to remove the single-lock read ceiling ([#&#8203;2097](0xERR0R/blocky#2097)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`7c6da15`](0xERR0R/blocky@7c6da15): feat(config): structurally merge config folder files ([#&#8203;1827](0xERR0R/blocky#1827)) ([#&#8203;2112](0xERR0R/blocky#2112)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`e7958e0`](0xERR0R/blocky@e7958e0): feat(lists): opt-in on-disk download cache with conditional revalidation ([#&#8203;2087](0xERR0R/blocky#2087)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`b82199b`](0xERR0R/blocky@b82199b): feat(querylog): ignore domains (exact/wildcard/regex) in query log ([#&#8203;2084](0xERR0R/blocky#2084)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`bee2d8b`](0xERR0R/blocky@bee2d8b): feat(resolver): UDP-first plain-DNS upstream and EDNS0 buffer floor ([#&#8203;2100](0xERR0R/blocky#2100)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`0b70e5c`](0xERR0R/blocky@0b70e5c): feat(resolver): add DNS rebinding protection ([#&#8203;2111](0xERR0R/blocky#2111)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`1b8e08a`](0xERR0R/blocky@1b8e08a): feat(resolver): pool DoT connections and enable TLS session resumption ([#&#8203;2098](0xERR0R/blocky#2098)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`4018d9e`](0xERR0R/blocky@4018d9e): feat: in-memory statistics subsystem with /api/stats REST endpoint ([#&#8203;2093](0xERR0R/blocky#2093)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`7abca44`](0xERR0R/blocky@7abca44): feat: support PROXY protocol on proxied DoT/DoH listeners ([#&#8203;2094](0xERR0R/blocky#2094)) ([@&#8203;kastakhov](https://github.com/kastakhov))

##### Bug fixes

- [`2496d12`](0xERR0R/blocky@2496d12): fix(dnssec): close DNSSEC validation bypass & cache-scope pollution (GHSA-x845-2f78-7v36) ([#&#8203;2119](0xERR0R/blocky#2119)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`06555e0`](0xERR0R/blocky@06555e0): fix(metrics): bound reason label cardinality for blocked responses ([#&#8203;2114](0xERR0R/blocky#2114)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`e0ea9b3`](0xERR0R/blocky@e0ea9b3): fix(resolver): eliminate recursive RLock deadlock in blocking group resolution ([#&#8203;2106](0xERR0R/blocky#2106)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`80f742e`](0xERR0R/blocky@80f742e): fix(server): answer browser CORS preflights for custom headers and Private Network Access ([#&#8203;2109](0xERR0R/blocky#2109)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`9702c8f`](0xERR0R/blocky@9702c8f): fix(stats): populate allow/denylist counts in /api/stats at startup ([#&#8203;2113](0xERR0R/blocky#2113)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))

##### Build and dependencies

- [`821e378`](0xERR0R/blocky@821e378): build(deps): bump codecov/codecov-action from 6 to 7 ([#&#8203;2089](0xERR0R/blocky#2089)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`d63f84b`](0xERR0R/blocky@d63f84b): build(deps): bump github.com/0xERR0R/expiration-cache from 0.1.0 to 0.2.0 ([#&#8203;2095](0xERR0R/blocky#2095)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`81f2b2a`](0xERR0R/blocky@81f2b2a): build(deps): bump github.com/onsi/ginkgo/v2 from 2.29.0 to 2.30.0 ([#&#8203;2108](0xERR0R/blocky#2108)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`9c5abdf`](0xERR0R/blocky@9c5abdf): build(deps): bump github.com/onsi/ginkgo/v2 from 2.30.0 to 2.31.0 ([#&#8203;2116](0xERR0R/blocky#2116)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`6c0ec5f`](0xERR0R/blocky@6c0ec5f): build(deps): bump github.com/onsi/gomega from 1.41.0 to 1.42.0 ([#&#8203;2115](0xERR0R/blocky#2115)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`4beb9fe`](0xERR0R/blocky@4beb9fe): build(deps): bump github.com/quic-go/quic-go from 0.59.1 to 0.60.0 ([#&#8203;2090](0xERR0R/blocky#2090)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`8fe2202`](0xERR0R/blocky@8fe2202): build(deps): bump golang.org/x/net from 0.55.0 to 0.56.0 ([#&#8203;2101](0xERR0R/blocky#2101)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`52fa6a4`](0xERR0R/blocky@52fa6a4): build(deps): bump golang.org/x/sys from 0.45.0 to 0.46.0 ([#&#8203;2096](0xERR0R/blocky#2096)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])

##### Misc

- [`1c9f717`](0xERR0R/blocky@1c9f717): ci(e2e): speed up e2e job via Ginkgo proc oversubscription ([#&#8203;2085](0xERR0R/blocky#2085)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`8d49922`](0xERR0R/blocky@8d49922): ci: cross-compile multi-arch docker image instead of QEMU emulation ([#&#8203;2081](0xERR0R/blocky#2081)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`355a9a1`](0xERR0R/blocky@355a9a1): docs(grafana): redesign Grafana dashboard and update integration guide ([#&#8203;2110](0xERR0R/blocky#2110)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`c791e80`](0xERR0R/blocky@c791e80): perf(e2e): probe blocky healthcheck at 250ms during start period ([#&#8203;2086](0xERR0R/blocky#2086)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`a0fb375`](0xERR0R/blocky@a0fb375): perf(lists): speed up blocklist loading (cache build + parsing) ([#&#8203;2083](0xERR0R/blocky#2083)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`316b073`](0xERR0R/blocky@316b073): perf(resolver): pre-classify client groups to cut per-query allocations ([#&#8203;2103](0xERR0R/blocky#2103)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`d502806`](0xERR0R/blocky@d502806): perf(server): let Truncate decide response compression ([#&#8203;2102](0xERR0R/blocky#2102)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))
- [`8b32512`](0xERR0R/blocky@8b32512): test(e2e): de-flake PROXY protocol and upstream init.strategy specs ([#&#8203;2099](0xERR0R/blocky#2099)) ([@&#8203;0xERR0R](https://github.com/0xERR0R))

***

#### ❤️ Support Blocky

Blocky is free and open source, developed in my spare time — no telemetry, no ads, no hidden
filtering. If it's useful to you, please consider supporting its continued development:

[GitHub Sponsors](https://github.com/sponsors/0xERR0R) ·
[thanks.dev](https://thanks.dev/u/gh/0xERR0R) ·
[Liberapay](https://liberapay.com/spx01) ·
[Ko-fi](https://ko-fi.com/0xerr0r) ·
[PayPal](https://paypal.me/spx01)

Thank you to everyone supporting Blocky! 🙏

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIyMi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Query Logging: Ignore certain domains or regex entries

2 participants