Files
blocky/docs/config.schema.json
T

1784 lines
53 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/0xERR0R/blocky/config/config",
"properties": {
"upstreams": {
"properties": {
"init": {
"properties": {
"strategy": {
"type": "string",
"enum": [
"blocking",
"failOnError",
"fast"
],
"description": "Startup strategy controlling how initialization failures are handled.\n\n- `blocking`: Initialization runs before DNS resolution starts; errors are logged but Blocky keeps running if possible.\n- `failOnError`: Like blocking but Blocky exits with an error if initialization fails.\n- `fast`: Blocky serves DNS immediately and runs initialization in the background.",
"default": "blocking"
}
},
"additionalProperties": false,
"type": "object",
"description": "Initialization strategy controlling when upstream resolvers are tested on startup."
},
"timeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Timeout for upstream DNS connections; a value \u003c= 0 is reset to the default.",
"default": "2s",
"examples": [
"30s",
"1h"
]
},
"groups": {
"additionalProperties": {
"items": {
"type": "string",
"description": "Upstream DNS server: [net]:host[:port][/path][#commonName] or sdns://...",
"examples": [
"tcp+udp:1.1.1.1",
"https://dns.google/dns-query",
"tcp-tls:1.1.1.1:853"
]
},
"type": "array"
},
"type": "object",
"description": "Named groups of upstream DNS resolvers; the \"default\" group is required."
},
"strategy": {
"type": "string",
"enum": [
"parallel_best",
"strict",
"random"
],
"description": "Strategy for selecting which upstream(s) to use per query (parallel_best, random, strict).\n\n- `parallel_best`: Picks 2 random weighted resolvers per query and returns the fastest answer (default).\n- `strict`: Queries upstreams in strict order; the next is tried only if the previous fails.\n- `random`: Picks one random weighted resolver per query; another is tried on failure.",
"default": "parallel_best"
},
"userAgent": {
"type": "string",
"description": "HTTP User-Agent header sent when connecting to DoH upstream servers."
},
"quic": {
"properties": {
"maxIdleTimeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Maximum idle duration before the QUIC connection is closed.",
"default": "30s",
"examples": [
"30s",
"1h"
]
},
"keepAlivePeriod": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Interval at which keep-alive packets are sent to maintain the QUIC connection.",
"default": "15s",
"examples": [
"30s",
"1h"
]
}
},
"additionalProperties": false,
"type": "object",
"description": "QUIC-specific connection settings used when DoQ upstreams are configured."
}
},
"additionalProperties": false,
"type": "object",
"description": "Upstream DNS servers and strategy configuration."
},
"connectIPVersion": {
"type": "string",
"enum": [
"dual",
"v4",
"v6"
],
"description": "IP version used for outgoing connections (dual, v4, v6).\n\n- `dual`: Use both IPv4 and IPv6.\n- `v4`: Use IPv4 only.\n- `v6`: Use IPv6 only."
},
"customDNS": {
"properties": {
"rewrite": {
"additionalProperties": {
"type": "string"
},
"type": "object",
"description": "Domain rewrite rules applied before resolution; keys are rewritten to their values."
},
"fallbackUpstream": {
"type": "boolean",
"description": "If true, the original query is sent upstream when the mapped resolver returns an empty answer.",
"default": false
},
"customTTL": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "TTL for DNS records defined in the mapping section (does not apply to zone file records).",
"default": "1h",
"examples": [
"30s",
"1h"
]
},
"mapping": {
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"items": {
"type": "string"
},
"type": "array"
}
]
},
"type": "object",
"description": "Simple domain-to-IP mappings; multiple IPs per domain separated by commas."
},
"zone": {
"type": "string",
"description": "DNS zone file content for more complex record definitions (A, AAAA, CNAME, TXT, SRV).",
"default": ""
},
"filterUnmappedTypes": {
"type": "boolean",
"description": "If true, queries for types not defined for a domain return empty; if false, they are forwarded upstream.",
"default": true
}
},
"additionalProperties": false,
"type": "object",
"description": "Custom static DNS mappings and zone definitions."
},
"conditional": {
"properties": {
"rewrite": {
"additionalProperties": {
"type": "string"
},
"type": "object",
"description": "Domain rewrite rules applied before resolution; keys are rewritten to their values."
},
"fallbackUpstream": {
"type": "boolean",
"description": "If true, the original query is sent upstream when the mapped resolver returns an empty answer.",
"default": false
},
"mapping": {
"additionalProperties": {
"type": "string"
},
"type": "object",
"description": "Domain-to-upstream mappings; queries for each domain are forwarded to its configured resolver(s)."
}
},
"additionalProperties": false,
"type": "object",
"description": "Conditional upstream resolvers for specific domains."
},
"blocking": {
"properties": {
"denylists": {
"additionalProperties": {
"items": {
"type": "string",
"description": "Source: an http(s) URL, a local file path, or an inline YAML block.",
"examples": [
"https://example.com/list.txt",
"/etc/blocky/list.txt"
]
},
"type": "array"
},
"type": "object",
"description": "Named groups of block-list sources (URLs, file paths, or inline content)."
},
"allowlists": {
"additionalProperties": {
"items": {
"type": "string",
"description": "Source: an http(s) URL, a local file path, or an inline YAML block.",
"examples": [
"https://example.com/list.txt",
"/etc/blocky/list.txt"
]
},
"type": "array"
},
"type": "object",
"description": "Named groups of allow-list sources; entries here take precedence over denylists in the same group."
},
"schedules": {
"additionalProperties": {
"properties": {
"start": {
"type": "string",
"description": "Start time in HH:MM format; omit together with end for an all-day schedule."
},
"end": {
"type": "string",
"description": "End time in HH:MM format; if before start, the window is overnight (e.g. 22:00 to 06:00)."
},
"weekdays": {
"items": {
"type": "string",
"description": "Day of week: mon, tue, wed, thu, fri, sat, sun.",
"examples": [
"mon",
"sat"
]
},
"type": "array",
"description": "Days of the week this schedule is active (mon, tue, wed, thu, fri, sat, sun)."
}
},
"additionalProperties": false,
"type": "object",
"description": "Schedule defines a time-based schedule for blocking rules."
},
"type": "object",
"description": "Named time-based schedules that can gate when list groups are active."
},
"listSchedules": {
"additionalProperties": {
"items": {
"type": "string"
},
"type": "array"
},
"type": "object",
"description": "Maps each list group name to the schedule(s) that control when it is active."
},
"clientGroupsBlock": {
"additionalProperties": {
"items": {
"type": "string"
},
"type": "array"
},
"type": "object",
"description": "Maps client identifiers (name, IP, CIDR) to the list groups that apply to them."
},
"blockType": {
"type": "string",
"description": "Response for blocked A/AAAA queries: zeroIP (0.0.0.0/::), nxDomain, or custom IPs; other types get NXDOMAIN.",
"default": "ZEROIP"
},
"blockTTL": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "TTL of blocked responses; how long clients cache the block before querying the domain again.",
"default": "6h",
"examples": [
"30s",
"1h"
]
},
"loading": {
"properties": {
"strategy": {
"type": "string",
"enum": [
"blocking",
"failOnError",
"fast"
],
"description": "Startup strategy controlling how initialization failures are handled.\n\n- `blocking`: Initialization runs before DNS resolution starts; errors are logged but Blocky keeps running if possible.\n- `failOnError`: Like blocking but Blocky exits with an error if initialization fails.\n- `fast`: Blocky serves DNS immediately and runs initialization in the background.",
"default": "blocking"
},
"concurrency": {
"type": "integer",
"description": "Maximum number of sources downloaded and processed concurrently (default: 4).",
"default": 4
},
"maxErrorsPerSource": {
"type": "integer",
"description": "Maximum parse errors per source before the source is considered invalid; -1 disables the limit.",
"default": 5
},
"refreshPeriod": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "How often sources are reloaded; a value of 0 or less disables periodic refresh (default: 4h).",
"default": "4h",
"examples": [
"30s",
"1h"
]
},
"downloads": {
"properties": {
"timeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Timeout per download attempt (default: 5s).",
"default": "5s",
"examples": [
"30s",
"1h"
]
},
"readTimeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Timeout for reading the download response body (default: 20s).",
"default": "20s",
"examples": [
"30s",
"1h"
]
},
"readHeaderTimeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Timeout for reading the download response headers (default: 20s).",
"default": "20s",
"examples": [
"30s",
"1h"
]
},
"writeTimeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Timeout for writing the downloaded file (default: 20s).",
"default": "20s",
"examples": [
"30s",
"1h"
]
},
"attempts": {
"type": "integer",
"description": "Number of download attempts before giving up (default: 3).",
"default": 3
},
"cooldown": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Pause between consecutive download attempts (default: 500ms).",
"default": "500ms",
"examples": [
"30s",
"1h"
]
},
"cachePath": {
"type": "string",
"description": "Directory for the on-disk download cache. When empty (default), downloads are\nfully stateless: nothing is written to disk and every source is downloaded in\nfull on every refresh. When set, blocky uses HTTP conditional requests and\nserves unchanged/unavailable sources from this directory."
}
},
"additionalProperties": false,
"type": "object",
"description": "HTTP(S) download settings for remote sources."
}
},
"additionalProperties": false,
"type": "object",
"description": "Controls how block/allow lists are loaded and periodically refreshed."
},
"blackLists": {
"additionalProperties": {
"items": {
"type": "string",
"description": "Source: an http(s) URL, a local file path, or an inline YAML block.",
"examples": [
"https://example.com/list.txt",
"/etc/blocky/list.txt"
]
},
"type": "array"
},
"type": "object",
"deprecated": true
},
"whiteLists": {
"additionalProperties": {
"items": {
"type": "string",
"description": "Source: an http(s) URL, a local file path, or an inline YAML block.",
"examples": [
"https://example.com/list.txt",
"/etc/blocky/list.txt"
]
},
"type": "array"
},
"type": "object",
"deprecated": true
},
"downloadTimeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"deprecated": true,
"examples": [
"30s",
"1h"
]
},
"downloadAttempts": {
"type": "integer",
"deprecated": true
},
"downloadCooldown": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"deprecated": true,
"examples": [
"30s",
"1h"
]
},
"refreshPeriod": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"deprecated": true,
"examples": [
"30s",
"1h"
]
},
"failStartOnListError": {
"type": "boolean",
"deprecated": true
},
"processingConcurrency": {
"type": "integer",
"deprecated": true
},
"startStrategy": {
"type": "string",
"enum": [
"blocking",
"failOnError",
"fast"
],
"deprecated": true
},
"maxErrorsPerFile": {
"type": "integer",
"deprecated": true
}
},
"additionalProperties": false,
"type": "object",
"description": "Blocking configuration with allow/denylists and client groups."
},
"clientLookup": {
"properties": {
"clients": {
"additionalProperties": {
"items": {
"type": "string",
"format": "ipv4"
},
"type": "array"
},
"type": "object",
"description": "Static map of client name to one or more IP addresses for manual client name assignment."
},
"upstream": {
"type": "string",
"description": "Upstream DNS server used for rDNS client name lookups (typically your router).",
"examples": [
"tcp+udp:1.1.1.1",
"https://dns.google/dns-query",
"tcp-tls:1.1.1.1:853"
]
},
"singleNameOrder": {
"items": {
"type": "integer"
},
"type": "array",
"description": "Order of preference when a router returns multiple names for a client (1-based index)."
}
},
"additionalProperties": false,
"type": "object",
"description": "Client name lookup configuration for resolving client identifiers."
},
"caching": {
"properties": {
"minTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Minimum TTL for cached entries; if the response TTL is smaller, this value is used instead.",
"examples": [
"30s",
"1h"
]
},
"maxTime": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Maximum TTL for cached entries. If \u003c0, caching is disabled. If 0, the response TTL is used.",
"examples": [
"30s",
"1h"
]
},
"cacheTimeNegative": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "TTL for negative responses (NXDOMAIN / empty). Use -1 to disable caching of negative results.",
"default": "30m",
"examples": [
"30s",
"1h"
]
},
"maxItemsCount": {
"type": "integer",
"description": "Maximum number of cache entries (soft limit). 0 means unlimited."
},
"prefetching": {
"type": "boolean",
"description": "If true, blocky preloads DNS results for frequently queried names before they expire."
},
"prefetchExpires": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Time window used to track query frequency for prefetch eligibility.",
"default": "2h",
"examples": [
"30s",
"1h"
]
},
"prefetchThreshold": {
"type": "integer",
"description": "Minimum number of queries within prefetchExpires required to trigger prefetching.",
"default": 5
},
"prefetchMaxItemsCount": {
"type": "integer",
"description": "Maximum number of domains tracked for prefetching (soft limit). 0 means unlimited."
},
"exclude": {
"items": {
"type": "string"
},
"type": "array",
"description": "Regex list of domains that are never cached."
}
},
"additionalProperties": false,
"type": "object",
"description": "DNS response caching settings."
},
"queryLog": {
"properties": {
"target": {
"type": "string",
"description": "Directory for CSV log files, file path for sqlite, or database URL for mysql/postgresql/timescale."
},
"type": {
"type": "string",
"enum": [
"console",
"none",
"mysql",
"postgresql",
"csv",
"csv-client",
"timescale",
"sqlite"
],
"description": "Log target type: mysql, postgresql, timescale, sqlite, csv, csv-client, console, or none.\n\n- `console`: Log to console output (used when no type is set).\n- `none`: Do not log any queries.\n- `mysql`: Log each query to an external MySQL or MariaDB database.\n- `postgresql`: Log each query to an external PostgreSQL database.\n- `csv`: Log to a CSV file (one per day).\n- `csv-client`: Log to a CSV file (one per day and per client).\n- `timescale`: Log each query to an external Timescale database.\n- `sqlite`: Log each query to a local SQLite database file."
},
"logRetentionDays": {
"type": "integer",
"description": "Delete log entries older than this many days. 0 disables retention cleanup."
},
"creationAttempts": {
"type": "integer",
"description": "Maximum number of attempts to create the query log writer on startup.",
"default": 3
},
"creationCooldown": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Delay between query log writer creation attempts.",
"default": "2s",
"examples": [
"30s",
"1h"
]
},
"fields": {
"items": {
"type": "string",
"enum": [
"clientIP",
"clientName",
"responseReason",
"responseAnswer",
"question",
"duration"
]
},
"type": "array",
"description": "Which fields to include in log entries; defaults to all available fields."
},
"flushInterval": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Interval at which buffered log entries are flushed in bulk to the database\n(used by the mysql, postgresql, timescale and sqlite targets).",
"default": "30s",
"examples": [
"30s",
"1h"
]
},
"ignore": {
"properties": {
"sudn": {
"type": "boolean",
"description": "If true, queries resolved as Special Use Domain Names (SUDN) are not logged.",
"default": false
},
"domains": {
"items": {
"type": "string"
},
"type": "array",
"description": "Domains whose queries are not logged. Each entry is matched against the\nquery name as an exact domain, a *.wildcard, or a /regex/."
}
},
"additionalProperties": false,
"type": "object",
"description": "Rules to suppress certain queries from being logged."
}
},
"additionalProperties": false,
"type": "object",
"description": "Query logging configuration."
},
"prometheus": {
"properties": {
"enable": {
"type": "boolean",
"description": "If true, enables the Prometheus metrics endpoint.",
"default": false
},
"path": {
"type": "string",
"description": "URL path under which the Prometheus metrics are served.",
"default": "/metrics"
}
},
"additionalProperties": false,
"type": "object",
"description": "Prometheus metrics configuration."
},
"redis": {
"properties": {
"address": {
"type": "string",
"description": "Server address and port (e.g. `localhost:6379`), a unix socket path (e.g. `/var/run/redis/redis.sock`),\nor the sentinel master name when sentinel is used. An address starting with `/` is treated as a unix socket."
},
"username": {
"type": "string",
"description": "Redis username (if authentication is required).",
"default": ""
},
"password": {
"type": "string",
"description": "Redis password (if authentication is required).",
"default": ""
},
"database": {
"type": "integer",
"description": "Redis database index to use.",
"default": 0
},
"required": {
"type": "boolean",
"description": "If true, blocky will not start when the Redis connection cannot be established.",
"default": false
},
"connectionAttempts": {
"type": "integer",
"description": "Maximum number of connection attempts before giving up.",
"default": 3
},
"connectionCooldown": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Delay between consecutive connection attempts.",
"default": "1s",
"examples": [
"30s",
"1h"
]
},
"sentinelUsername": {
"type": "string",
"description": "Sentinel username (if sentinel authentication is required).",
"default": ""
},
"sentinelPassword": {
"type": "string",
"description": "Sentinel password (if sentinel authentication is required).",
"default": ""
},
"sentinelAddresses": {
"items": {
"type": "string"
},
"type": "array",
"description": "List of Redis Sentinel host:port addresses; enables sentinel mode when non-empty."
}
},
"additionalProperties": false,
"type": "object",
"description": "Redis configuration for cache and state synchronization between instances."
},
"log": {
"properties": {
"level": {
"type": "string",
"default": "info",
"examples": [
"info",
"debug"
]
},
"format": {
"type": "string",
"enum": [
"text",
"json"
],
"description": "- `text`: Human-readable text.\n- `json`: Structured JSON.",
"default": "text"
},
"privacy": {
"type": "boolean",
"default": false
},
"timestamp": {
"type": "boolean",
"default": true
}
},
"additionalProperties": false,
"type": "object",
"description": "Logging configuration."
},
"ports": {
"properties": {
"dns": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array"
}
],
"description": "Listen address(es) for DNS over TCP and UDP (default: 53).",
"default": "53"
},
"http": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array"
}
],
"description": "Listen address(es) for HTTP (metrics, REST API, DoH)."
},
"https": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array"
}
],
"description": "Listen address(es) for HTTPS (metrics, REST API, DoH)."
},
"tls": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array"
}
],
"description": "Listen address(es) for DNS-over-TLS (DoT)."
},
"dohPath": {
"type": "string",
"description": "URL path for DoH queries.",
"default": "/dns-query"
},
"freeBind": {
"type": "boolean",
"description": "Allow binding the DNS and DoT listeners to addresses that are not yet assigned to a network\ninterface, via the Linux IP_FREEBIND socket option (e.g. for Tailscale/WireGuard/VRRP addresses\nbrought up after startup). Has no effect on wildcard binds and is ignored, with a warning, on\nnon-Linux platforms.",
"default": false
}
},
"additionalProperties": false,
"type": "object",
"description": "Listen addresses for DNS, HTTP, HTTPS, and TLS."
},
"minTlsServeVersion": {
"anyOf": [
{
"type": "string",
"enum": [
"1.0",
"1.1",
"1.2",
"1.3"
]
},
{
"type": "number"
}
],
"description": "Minimum TLS version the DoT and DoH servers use to serve encrypted DNS requests.",
"default": "1.2"
},
"certFile": {
"type": "string",
"description": "Path to the TLS certificate file for DoH and DoT; if empty, a self-signed certificate is generated."
},
"keyFile": {
"type": "string",
"description": "Path to the TLS key file for DoH and DoT; if empty, a self-signed certificate is generated."
},
"bootstrapDns": {
"anyOf": [
{
"anyOf": [
{
"type": "string"
},
{
"properties": {
"upstream": {
"type": "string"
},
"ips": {
"items": {
"type": "string"
},
"type": "array"
},
"resolvFile": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
}
]
},
{
"items": {
"anyOf": [
{
"type": "string"
},
{
"properties": {
"upstream": {
"type": "string"
},
"ips": {
"items": {
"type": "string"
},
"type": "array"
},
"resolvFile": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
}
]
},
"type": "array"
}
],
"description": "Bootstrap DNS servers used to resolve DoH/DoT upstream hostnames."
},
"hostsFile": {
"properties": {
"sources": {
"items": {
"type": "string",
"description": "Source: an http(s) URL, a local file path, or an inline YAML block.",
"examples": [
"https://example.com/list.txt",
"/etc/blocky/list.txt"
]
},
"type": "array",
"description": "Host files to load (e.g. /etc/hosts); supports local paths, URLs, and inline content."
},
"hostsTTL": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "TTL for DNS records resolved from host files.",
"default": "1h",
"examples": [
"30s",
"1h"
]
},
"filterLoopback": {
"type": "boolean",
"description": "If true, loopback addresses (127.0.0.0/8 and ::1) from host files are ignored."
},
"loading": {
"properties": {
"strategy": {
"type": "string",
"enum": [
"blocking",
"failOnError",
"fast"
],
"description": "Startup strategy controlling how initialization failures are handled.\n\n- `blocking`: Initialization runs before DNS resolution starts; errors are logged but Blocky keeps running if possible.\n- `failOnError`: Like blocking but Blocky exits with an error if initialization fails.\n- `fast`: Blocky serves DNS immediately and runs initialization in the background.",
"default": "blocking"
},
"concurrency": {
"type": "integer",
"description": "Maximum number of sources downloaded and processed concurrently (default: 4).",
"default": 4
},
"maxErrorsPerSource": {
"type": "integer",
"description": "Maximum parse errors per source before the source is considered invalid; -1 disables the limit.",
"default": 5
},
"refreshPeriod": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "How often sources are reloaded; a value of 0 or less disables periodic refresh (default: 4h).",
"default": "4h",
"examples": [
"30s",
"1h"
]
},
"downloads": {
"properties": {
"timeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Timeout per download attempt (default: 5s).",
"default": "5s",
"examples": [
"30s",
"1h"
]
},
"readTimeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Timeout for reading the download response body (default: 20s).",
"default": "20s",
"examples": [
"30s",
"1h"
]
},
"readHeaderTimeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Timeout for reading the download response headers (default: 20s).",
"default": "20s",
"examples": [
"30s",
"1h"
]
},
"writeTimeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Timeout for writing the downloaded file (default: 20s).",
"default": "20s",
"examples": [
"30s",
"1h"
]
},
"attempts": {
"type": "integer",
"description": "Number of download attempts before giving up (default: 3).",
"default": 3
},
"cooldown": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"description": "Pause between consecutive download attempts (default: 500ms).",
"default": "500ms",
"examples": [
"30s",
"1h"
]
},
"cachePath": {
"type": "string",
"description": "Directory for the on-disk download cache. When empty (default), downloads are\nfully stateless: nothing is written to disk and every source is downloaded in\nfull on every refresh. When set, blocky uses HTTP conditional requests and\nserves unchanged/unavailable sources from this directory."
}
},
"additionalProperties": false,
"type": "object",
"description": "HTTP(S) download settings for remote sources."
}
},
"additionalProperties": false,
"type": "object",
"description": "Controls how host files are loaded and periodically refreshed."
},
"refreshPeriod": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"deprecated": true,
"examples": [
"30s",
"1h"
]
},
"filePath": {
"type": "string",
"deprecated": true,
"examples": [
"https://example.com/list.txt",
"/etc/blocky/list.txt"
]
}
},
"additionalProperties": false,
"type": "object",
"description": "Local hosts file resolution settings."
},
"fqdnOnly": {
"properties": {
"enable": {
"type": "boolean",
"default": false
}
},
"additionalProperties": false,
"type": "object",
"description": "When enabled, blocky returns NXDOMAIN immediately for non-FQDN queries."
},
"filtering": {
"properties": {
"queryTypes": {
"items": {
"type": "string",
"enum": [
"A",
"AAAA",
"AFSDB",
"AMTRELAY",
"ANY",
"APL",
"ATMA",
"AVC",
"AXFR",
"CAA",
"CDNSKEY",
"CDS",
"CERT",
"CNAME",
"CSYNC",
"DHCID",
"DLV",
"DNAME",
"DNSKEY",
"DS",
"EID",
"EUI48",
"EUI64",
"GID",
"GPOS",
"HINFO",
"HIP",
"HTTPS",
"IPSECKEY",
"ISDN",
"IXFR",
"KEY",
"KX",
"L32",
"L64",
"LOC",
"LP",
"MAILA",
"MAILB",
"MB",
"MD",
"MF",
"MG",
"MINFO",
"MR",
"MX",
"NAPTR",
"NID",
"NIMLOC",
"NINFO",
"NS",
"NSAP-PTR",
"NSEC",
"NSEC3",
"NSEC3PARAM",
"NULL",
"NXNAME",
"NXT",
"None",
"OPENPGPKEY",
"OPT",
"PTR",
"PX",
"RESINFO",
"RKEY",
"RP",
"RRSIG",
"RT",
"Reserved",
"SIG",
"SMIMEA",
"SOA",
"SPF",
"SRV",
"SSHFP",
"SVCB",
"TA",
"TALINK",
"TKEY",
"TLSA",
"TSIG",
"TXT",
"UID",
"UINFO",
"UNSPEC",
"URI",
"X25",
"ZONEMD"
]
},
"type": "array",
"description": "DNS query types to drop; matching queries receive an empty answer (e.g. AAAA to block IPv6 lookups)."
}
},
"additionalProperties": false,
"type": "object",
"description": "DNS query type filtering configuration."
},
"ede": {
"properties": {
"enable": {
"type": "boolean",
"default": false
}
},
"additionalProperties": false,
"type": "object",
"description": "Extended DNS Errors (RFC 8914) configuration."
},
"ecs": {
"properties": {
"useAsClient": {
"type": "boolean",
"description": "Use the ECS client subnet as the client IP when a full-prefix ECS option is present.",
"default": false
},
"forward": {
"type": "boolean",
"description": "Forward the ECS option from the client request to upstream resolvers.",
"default": false
},
"ipv4Mask": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"description": "Subnet mask for IPv4 EDNS Client Subnet; adds ECS option when greater than zero (max 32).",
"default": "0"
},
"ipv6Mask": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"description": "Subnet mask for IPv6 EDNS Client Subnet; adds ECS option when greater than zero (max 128).",
"default": "0"
}
},
"additionalProperties": false,
"type": "object",
"description": "EDNS Client Subnet options."
},
"specialUseDomains": {
"properties": {
"rfc6762-appendixG": {
"type": "boolean",
"description": "These are \"recommended for private use\" but not mandatory.\nIf a user wishes to use one, it will most likely be via conditional\nupstream or custom DNS, which come before SUDN in the resolver chain.\nThus defaulting to `true` and returning NXDOMAIN here should not conflict.",
"default": true
},
"enable": {
"type": "boolean",
"description": "Set to false to completely disable Special Use Domain Name blocking (not recommended for remote upstreams).",
"default": true
}
},
"additionalProperties": false,
"type": "object",
"description": "Special Use Domain Names (SUDN) blocking configuration."
},
"dns64": {
"properties": {
"enable": {
"type": "boolean",
"description": "Enable DNS64 synthesis of AAAA records from A records for IPv6-only clients (RFC 6147).",
"default": false
},
"prefixes": {
"items": {
"type": "string",
"description": "CIDR network prefix.",
"examples": [
"64:ff9b::/96"
]
},
"type": "array",
"description": "IPv6 prefixes used for synthesis; valid lengths are /32, /40, /48, /56, /64, /96 (default: 64:ff9b::/96)."
},
"exclusionSet": {
"items": {
"type": "string",
"description": "CIDR network prefix.",
"examples": [
"64:ff9b::/96"
]
},
"type": "array",
"description": "IPv6 prefixes excluded from triggering synthesis. Overrides the default exclusion set; advanced use only."
}
},
"additionalProperties": false,
"type": "object",
"description": "DNS64 synthesis configuration for IPv6-only clients (RFC 6147)."
},
"dnssec": {
"properties": {
"validate": {
"type": "boolean",
"description": "Enable DNSSEC validation of DNS responses.",
"default": false
},
"trustAnchors": {
"items": {
"type": "string"
},
"type": "array",
"description": "Custom trust anchors (DNSKEY or DS records); empty uses built-in IANA root trust anchors."
},
"maxChainDepth": {
"type": "integer",
"description": "Maximum domain label depth for chain of trust validation (DoS protection).",
"default": 10
},
"cacheExpirationHours": {
"type": "integer",
"description": "How long to cache DNSSEC validation results, in hours.",
"default": 1
},
"maxNSEC3Iterations": {
"type": "integer",
"description": "RFC 5155 §10.3",
"default": 150
},
"maxUpstreamQueries": {
"type": "integer",
"description": "DoS protection: max upstream queries per validation",
"default": 30
},
"clockSkewToleranceSec": {
"type": "integer",
"description": "Clock skew tolerance in seconds for signature validation (default: 3600 = 1 hour)\nAllows validation to succeed even if system clock is off by this amount.\nMatches Unbound/BIND defaults for real-world deployments (VMs, containers, embedded systems).\nPer RFC 6781 §4.1.2: Validators should account for clock skew in deployment environments.",
"default": 3600
}
},
"additionalProperties": false,
"type": "object",
"description": "DNSSEC validation configuration."
},
"http3": {
"properties": {
"enable": {
"type": "boolean",
"description": "Enable the HTTP/3 listener on the same addresses as ports.https (requires ports.https to be set).",
"default": false
}
},
"additionalProperties": false,
"type": "object",
"description": "HTTP/3 (DoH3) server configuration."
},
"rateLimit": {
"properties": {
"enable": {
"type": "boolean",
"description": "Enable per-client DNS rate limiting.",
"default": false
},
"rate": {
"type": "integer",
"description": "Sustained query rate limit in queries per second per client.",
"default": 0
},
"burst": {
"type": "integer",
"description": "Token bucket capacity; queries above this burst are dropped. Defaults to rate × 2.",
"default": 0
},
"ipv4Prefix": {
"type": "integer",
"description": "Prefix length used to aggregate IPv4 client addresses into a single bucket.",
"default": 32
},
"ipv6Prefix": {
"type": "integer",
"description": "Prefix length used to aggregate IPv6 client addresses into a single bucket.",
"default": 64
},
"allowlist": {
"items": {
"type": "string"
},
"type": "array",
"description": "CIDRs or IPs that are never rate-limited."
}
},
"additionalProperties": false,
"type": "object",
"description": "Per-client DNS query rate limiting configuration."
},
"upstream": {
"additionalProperties": {
"items": {
"type": "string",
"description": "Upstream DNS server: [net]:host[:port][/path][#commonName] or sdns://...",
"examples": [
"tcp+udp:1.1.1.1",
"https://dns.google/dns-query",
"tcp-tls:1.1.1.1:853"
]
},
"type": "array"
},
"type": "object",
"deprecated": true
},
"upstreamTimeout": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
],
"deprecated": true,
"examples": [
"30s",
"1h"
]
},
"disableIPv6": {
"type": "boolean",
"deprecated": true
},
"logLevel": {
"type": "string",
"deprecated": true,
"examples": [
"info",
"debug"
]
},
"logFormat": {
"type": "string",
"enum": [
"text",
"json"
],
"deprecated": true
},
"logPrivacy": {
"type": "boolean",
"deprecated": true
},
"logTimestamp": {
"type": "boolean",
"deprecated": true
},
"port": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array"
}
],
"deprecated": true
},
"httpPort": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array"
}
],
"deprecated": true
},
"httpsPort": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array"
}
],
"deprecated": true
},
"tlsPort": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array"
}
],
"deprecated": true
},
"startVerifyUpstream": {
"type": "boolean",
"deprecated": true
},
"dohUserAgent": {
"type": "string",
"deprecated": true
}
},
"additionalProperties": false,
"type": "object",
"description": "Config main configuration"
}