Skip to main content

Domain Providers

These providers manage static, dynamic, V2Ray geosite, or AdGuard-style domain rule assets.

domain_set

Purpose

Provides a high-performance domain rule set that can be referenced by plugins such as qname and cname.

Example Configuration

- tag: core_domains
type: domain_set
args:
exps:
# Exact-name match
- "full:login.example.com"
# Suffix-domain match
- "domain:example.com"
# Keyword match
- "keyword:cdn"
# Regex match
- "regexp:^api[0-9]+\\.example\\.net$"
# Bare domain syntax is also allowed
- "static.example.org"
files:
# Merge additional rules from files
- "/etc/oxidns/domains.txt"
sets:
# Reuse another domain-capable provider
- "shared_domains"
- "shared_geosite"

Configuration Details

exps

  • Type: array; Required: no; Default: empty array
  • Purpose: Defines inline domain expressions.
  • Examples:
    • - "full:example.com"
    • - "domain:example.com"
    • - "keyword:cdn"
    • - "regexp:^api[0-9]+\\.example\\.net$"
  • Supported forms:
    • full:
    • domain:
    • keyword:
    • regexp:
    • Bare domains without a prefix
  • Runtime impact:
    • Compiled into directly matchable rules during initialization.

files

  • Type: array; Required: no; Default: empty array
  • Purpose: Lists external rule files.
  • Example: - "/etc/oxidns/domains.txt"
  • File requirements:
    • One rule per line.
    • Empty lines and comment lines are ignored.
  • Runtime impact:
    • File contents are re-read during initialization or reload_provider and compiled into the current provider's local matcher.

sets

  • Type: array; Required: no; Default: empty array
  • Purpose: References other providers with domain match capability.
  • Example: - "shared_domain_set"
  • Constraints:
    • domain_set, geosite, adguard_rule, and other domain-capable providers are allowed.
  • Runtime impact:
    • The current provider keeps stable handles to referenced providers instead of copying their rules.
    • After a downstream provider reloads, the current domain_set sees the new result without reloading itself.

Behavior

  • Initialization and reload only compile local exps and files.
  • Runtime matching checks the local matcher first and then evaluates referenced providers in sets declaration order.
  • Referenced providers are no longer flattened into copied rule text or copied compiled state.

Supported Rule Formats

  • full:example.com
  • domain:example.com
  • keyword:cdn
  • regexp:^api\\.example\\.com$
  • example.com

Typical Uses

  • Share a core domain list across multiple policies.
  • Combine local rules with shared providers behind one reusable entrypoint.
Notes
  • sets may reference any provider with domain match capability.
  • Changing provider topology, tags, or config structure still requires a full reload; reload_provider only refreshes the current provider's existing config and external data files.

dynamic_domain_set

Experimental Plugin (Introduced in v1.2.0)

dynamic_domain_set was first introduced in v1.2.0 and is currently in an experimental stage. Related configuration options may change in future releases. Before deploying in production, please evaluate the impact of learning rates and disk writes on the persistence layer.

Purpose

Provides a writable local domain rule set. It persists rules to a text file and exposes the same hot-snapshot domain matching capability as domain_set, making it suitable for learned allow or block lists driven by learn_domain.

dynamic_domain_set does not use SQLite and keeps the read-only aggregation role of domain_set separate.

Example Configuration

- tag: learned_allow
type: dynamic_domain_set
args:
path: "/etc/oxidns/learned-allow.txt"
bootstrap_rules:
- "domain:example.org"
queue_size: 1024
batch_size: 256
flush_interval_ms: 200

Configuration Details

path

  • Type: string; Required: yes
  • Purpose: Local rule file managed by this provider.
  • Runtime impact:
    • Created automatically when missing.
    • Read during startup and reload_provider.

bootstrap_rules

  • Type: array; Required: no; Default: empty array
  • Purpose: Initial rules written only when path does not exist.
  • Supports full:, domain:, keyword:, regexp:, and bare domains. Bare domains are parsed as domain:.

queue_size

  • Type: integer; Required: no; Default: 1024
  • Purpose: Bounded queue size for learned append work.

batch_size

  • Type: integer; Required: no; Default: 256
  • Purpose: Batch threshold for background append flushes.

flush_interval_ms

  • Type: integer; Required: no; Default: 200
  • Purpose: Timed flush interval for background appends.

File Format

  • One rule per line.
  • Supports full:example.com, domain:example.com, keyword:cdn, regexp:^api\\.example\\.com$, and example.com.
  • Empty lines and lines starting with # are ignored on load.
  • Domains are normalized to lowercase with trailing dots removed.

Management API

These plugin endpoints are exposed under the default management prefix as /api/plugins/<tag>/...:

MethodPathPurpose
GET/rules?limit=500&cursor=0Lists rules with total, next_cursor, and rules.
POST/rulesAdds rules. Body example: { "rules": ["example.com"], "rule_kind": "full" }.
DELETE/rulesRemoves rules. Body example: { "rules": ["full:example.com"] }.
POST/rules/clearClears the dynamic file and swaps in an empty snapshot.
POST/reloadUses the generic provider reload endpoint to re-read the file.

Behavior

  • contains_name and contains_question only read the current hot snapshot and never perform file I/O.
  • Writes from learn_domain or the API update this provider's snapshot immediately; qname and parent domain_set.sets references see the new result without reload.
  • Learned appends are asynchronous and batched by default; API add/delete/clear waits for file persistence and snapshot replacement.
  • External manual file edits require reload_provider or POST /api/plugins/<tag>/reload; v1 does not include a file watcher.
  • remove/clear rewrites the managed file; API rewrites are not guaranteed to preserve hand-written comments.
Notes
  • Treat path as a machine-managed file owned by dynamic_domain_set.
  • Use separate dynamic_domain_set instances for allow and block lists.

geosite

Purpose

Loads reusable domain rules from v2ray-rules-dat geosite.dat.

Example Configuration

- tag: geosite_cn
type: geosite
args:
file: "/etc/oxidns/geosite.dat"
selectors:
- "cn"
- "geolocation-!cn"

Configuration Details

  • file
    • Type: string; Required: yes
    • Path to geosite.dat.
  • selectors
    • Type: array; Required: no; Default: empty array
    • Case-insensitive exact code filter. Also supports code@attribute selectors.
    • Multiple selectors are merged as a union.
    • Omit it or pass [] to load the full union of every entry in the dat file.
    • Example: category-games@cn keeps only rules under category-games that carry the cn attribute.

Composition Examples

Split domain policy by code and use each provider directly from a matcher:

plugins:
- tag: geosite_cn
type: geosite
args:
file: "/etc/oxidns/geosite.dat"
selectors: ["cn"]

# `geolocation-!cn` is a geosite.dat code, not a generic exclusion expression.
- tag: geosite_non_cn
type: geosite
args:
file: "/etc/oxidns/geosite.dat"
selectors: ["geolocation-!cn"]

- tag: match_cn_domain
type: qname
args: ["$geosite_cn"]

- tag: match_non_cn_question
type: question
args: ["$geosite_non_cn"]

Filter a code by attribute. Available codes and attributes depend on the dat release in use:

- tag: geosite_games_cn
type: geosite
args:
file: "/etc/oxidns/geosite.dat"
selectors:
- "category-games@cn"

- tag: match_games_cn
type: qname
args: ["$geosite_games_cn"]

Combine geosite data with local rules behind one reusable entrypoint:

- tag: domestic_domains
type: domain_set
args:
exps:
- "full:internal.example"
sets:
- "geosite_cn"

- tag: match_domestic_domain
type: qname
args: ["$domestic_domains"]

Behavior

  • Plain becomes keyword:.
  • Regex becomes regexp:.
  • RootDomain becomes domain:.
  • Full becomes full:.
  • Can be referenced directly by qname, cname, and question, or aggregated by domain_set.
  • Supports independent refresh through reload_provider or POST /plugins/<tag>/reload.
  • To pre-export selected rules into text files before runtime, use oxidns export-dat --kind geosite.
Selector Notes
  • Selectors perform exact code matching only. The ! in geolocation-!cn is part of the code text; it does not mean “exclude cn”.
  • code@attribute retains only rules carrying that attribute. If one provider lists both code and code@attribute, the bare code loads every rule in that code.
  • Startup and provider reload fail when the requested selectors match no entry or produce no rules. Use oxidns export-dat --kind geosite --selector <selector> first to verify a selector against the data file.

adguard_rule

Purpose

Provides a reusable subset of AdGuard Home DNS rule evaluation as a provider.

This provider exposes two semantics:

  • contains_question: full request-question evaluation, including dnstype
  • contains_name: a name-only projection that ignores all dnstype rules

Example Configuration

- tag: ad_rules
type: adguard_rule
args:
rules:
# Basic blocking rule
- "||ads.example.com^"
# Exception rule
- "@@||safe.ads.example.com^"
# Complex inline rule with dnstype / important / denyallow
- "||cdn.example.com^$dnstype=A|AAAA,important,denyallow=cdn-safe.example.com"
files:
# External AdGuard-format rule files
- "/etc/oxidns/adguard.txt"

Behavior

  • Supports: basic domain rules, @@, important, badfilter, denyallow, and request-side dnstype
  • Unsupported but skipped with summary warnings: URL/path filters, /etc/hosts style rules, cosmetic filters, dnsrewrite, $client, $ctag, and unknown modifiers
  • Initialization and reload stream rule files; skipped rules are summarized by reason with at most five samples retained for each reason
  • Full precedence order:
    • important exceptions
    • important blocks
    • normal exceptions
    • normal blocks

Typical Uses

  • Use AdGuard rules through the qname matcher with name-only projection semantics.
  • Reuse AdGuard rule files through the question matcher.
  • Centralize complex AdGuard-style blocking semantics at the provider layer.
Notes
  • Name-only matchers such as qname and cname use contains_name, so dnstype-only rules are ignored there.
  • adguard_rule can be referenced from domain_set.sets; because evaluation stays dynamic, exception precedence and request-scoped modifiers such as dnstype remain intact.