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_providerand compiled into the current provider's local matcher.
- File contents are re-read during initialization or
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_setsees the new result without reloading itself.
Behavior
- Initialization and reload only compile local
expsandfiles. - Runtime matching checks the local matcher first and then evaluates referenced providers in
setsdeclaration order. - Referenced providers are no longer flattened into copied rule text or copied compiled state.
Supported Rule Formats
full:example.comdomain:example.comkeyword:cdnregexp:^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.
setsmay reference any provider with domain match capability.- Changing provider topology, tags, or config structure still requires a full
reload;reload_provideronly refreshes the current provider's existing config and external data files.
dynamic_domain_set
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
pathdoes not exist. - Supports
full:,domain:,keyword:,regexp:, and bare domains. Bare domains are parsed asdomain:.
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$, andexample.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>/...:
| Method | Path | Purpose |
|---|---|---|
GET | /rules?limit=500&cursor=0 | Lists rules with total, next_cursor, and rules. |
POST | /rules | Adds rules. Body example: { "rules": ["example.com"], "rule_kind": "full" }. |
DELETE | /rules | Removes rules. Body example: { "rules": ["full:example.com"] }. |
POST | /rules/clear | Clears the dynamic file and swaps in an empty snapshot. |
POST | /reload | Uses the generic provider reload endpoint to re-read the file. |
Behavior
contains_nameandcontains_questiononly read the current hot snapshot and never perform file I/O.- Writes from
learn_domainor the API update this provider's snapshot immediately;qnameand parentdomain_set.setsreferences 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_providerorPOST /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.
- Treat
pathas a machine-managed file owned bydynamic_domain_set. - Use separate
dynamic_domain_setinstances 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.
- Type:
selectors- Type:
array; Required: no; Default: empty array - Case-insensitive exact code filter. Also supports
code@attributeselectors. - 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@cnkeeps only rules undercategory-gamesthat carry thecnattribute.
- Type:
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
Plainbecomeskeyword:.Regexbecomesregexp:.RootDomainbecomesdomain:.Fullbecomesfull:.- Can be referenced directly by
qname,cname, andquestion, or aggregated bydomain_set. - Supports independent refresh through
reload_providerorPOST /plugins/<tag>/reload. - To pre-export selected rules into text files before runtime, use
oxidns export-dat --kind geosite.
- Selectors perform exact code matching only. The
!ingeolocation-!cnis part of the code text; it does not mean “exclude cn”. code@attributeretains only rules carrying that attribute. If one provider lists bothcodeandcode@attribute, the barecodeloads 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, includingdnstypecontains_name: a name-only projection that ignores alldnstyperules
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-sidednstype - Unsupported but skipped with summary warnings: URL/path filters,
/etc/hostsstyle 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:
importantexceptionsimportantblocks- normal exceptions
- normal blocks
Typical Uses
- Use AdGuard rules through the
qnamematcher with name-only projection semantics. - Reuse AdGuard rule files through the
questionmatcher. - Centralize complex AdGuard-style blocking semantics at the provider layer.
- Name-only matchers such as
qnameandcnameusecontains_name, sodnstype-only rules are ignored there. adguard_rulecan be referenced fromdomain_set.sets; because evaluation stays dynamic, exception precedence and request-scoped modifiers such asdnstyperemain intact.