From: Vladimír Čunát Date: Wed, 15 Jul 2026 09:00:32 +0000 (+0200) Subject: Merge master into naked-http X-Git-Tag: v6.4.2~3^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9aff730bfd483b7d6dbf0a22e68d9eb2a3483a3a;p=thirdparty%2Fknot-resolver.git Merge master into naked-http --- 9aff730bfd483b7d6dbf0a22e68d9eb2a3483a3a diff --cc daemon/bindings/net.c index e5f5fa4e2,b4f139874..d20dd6210 --- a/daemon/bindings/net.c +++ b/daemon/bindings/net.c @@@ -265,8 -259,9 +269,11 @@@ static int net_listen(lua_State *L flags.http = false; } else if (k && strcasecmp(k, "doh2") == 0) { flags.tls = flags.http = true; + } else if (k && strcasecmp(k, "doh2-insecure") == 0) { + flags.tls = false; + flags.http = true; + } else if (k && strcasecmp(k, "doq") == 0) { + flags.tls = flags.quic = true; } else if (k) { flags.kind = k; if (strcasecmp(k, "doh") == 0) { diff --cc daemon/lua/kres-gen-33.lua index 96eed7734,9edee2de4..49866e98b --- a/daemon/lua/kres-gen-33.lua +++ b/daemon/lua/kres-gen-33.lua @@@ -385,8 -349,8 +385,8 @@@ struct kr_query_data_src kr_rule_fwd_flags_t flags; knot_db_val_t targets_ptr; }; -enum kr_rule_sub_t {KR_RULE_SUB_EMPTY = 1, KR_RULE_SUB_NXDOMAIN, KR_RULE_SUB_NODATA, KR_RULE_SUB_REDIRECT}; -enum kr_proto {KR_PROTO_INTERNAL, KR_PROTO_UDP53, KR_PROTO_TCP53, KR_PROTO_DOT, KR_PROTO_DOH, KR_PROTO_DOQ, KR_PROTO_COUNT}; +enum kr_rule_sub_t {KR_RULE_SUB_EMPTY = 1, KR_RULE_SUB_NXDOMAIN, KR_RULE_SUB_NODATA, KR_RULE_SUB_REDIRECT, KR_RULE_SUB_DNAME, KR_RULE_SUB_DNAME_FLAT}; - enum kr_proto {KR_PROTO_INTERNAL, KR_PROTO_UDP53, KR_PROTO_TCP53, KR_PROTO_DOT, KR_PROTO_DOH, KR_PROTO_DOQ, KR_PROTO_DOQ_CONN, KR_PROTO_DOQ_STREAM, KR_PROTO_COUNT}; ++enum kr_proto {KR_PROTO_INTERNAL, KR_PROTO_UDP53, KR_PROTO_TCP53, KR_PROTO_DOT, KR_PROTO_DOH, KR_PROTO_DOH_INSECURE, KR_PROTO_DOQ, KR_PROTO_DOQ_CONN, KR_PROTO_DOQ_STREAM, KR_PROTO_COUNT}; typedef unsigned char kr_proto_set; kr_layer_t kr_layer_t_static; _Bool kr_dbg_assertion_abort; diff --cc daemon/session2.c index 136ae745a,c451ef4a7..d1111445a --- a/daemon/session2.c +++ b/daemon/session2.c @@@ -67,21 -60,15 +67,29 @@@ static const enum protolayer_type proto PROTOLAYER_TYPE_DNS_UNSIZED_STREAM, }; + static const enum protolayer_type protolayer_grp_doh_insecure[] = { + PROTOLAYER_TYPE_TCP, + PROTOLAYER_TYPE_PROXYV2_STREAM, ++ PROTOLAYER_TYPE_DEFER, + PROTOLAYER_TYPE_HTTP, + PROTOLAYER_TYPE_DNS_UNSIZED_STREAM, + }; + -static const enum protolayer_type protolayer_grp_doq[] = { - // not yet used +static const enum protolayer_type protolayer_grp_doq_stream[] = { + PROTOLAYER_TYPE_QUIC_STREAM, + PROTOLAYER_TYPE_DNS_SINGLE_STREAM, +}; + +static const enum protolayer_type protolayer_grp_doq_conn[] = { + PROTOLAYER_TYPE_DEFER, + PROTOLAYER_TYPE_QUIC_CONN, + PROTOLAYER_TYPE_NULL, +}; + +static const enum protolayer_type protolayer_grp_doq_demux[] = { + PROTOLAYER_TYPE_UDP, + PROTOLAYER_TYPE_PROXYV2_STREAM, + PROTOLAYER_TYPE_QUIC_DEMUX, PROTOLAYER_TYPE_NULL, }; diff --cc doc/_static/config.schema.json index c0f522d85,000000000..8ccf19ba0 mode 100644,000000..100644 --- a/doc/_static/config.schema.json +++ b/doc/_static/config.schema.json @@@ -1,1898 -1,0 +1,1899 @@@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.knot-resolver.cz/documentation/v6.4.1/_static/config.schema.json", + "title": "Knot Resolver configuration JSON schema", + "description": "Version Knot Resolver 6.4.1", + "type": "object", + "properties": { + "version": { + "type": "integer", + "description": "Version of the configuration schema. By default it is the latest supported by the resolver, but couple of versions back are be supported as well.", + "default": 1 + }, + "nsid": { + "type": [ + "string", + "null" + ], + "description": "Name Server Identifier (RFC 5001) which allows DNS clients to request resolver to send back its NSID along with the reply to a DNS request.", + "default": null + }, + "hostname": { + "type": [ + "string", + "null" + ], + "description": "Internal DNS resolver hostname. Default is machine hostname.", + "default": null + }, + "rundir": { + "type": "string", + "description": "Directory where the resolver can create files and which will be it's cwd.", + "default": "/run/knot-resolver" + }, + "workers": { + "anyOf": [ + { + "type": "string", + "enum": [ + "auto" + ] + }, + { + "type": "integer", + "minimum": 1 + } + ], + "description": "The number of running kresd (Knot Resolver daemon) workers. If set to 'auto', it is equal to number of CPUs available.", + "default": 1 + }, + "management": { + "description": "Configuration of management HTTP API.", + "type": "object", + "properties": { + "unix-socket": { + "type": [ + "string", + "null" + ], + "description": "Path to unix domain socket to listen to.", + "default": null + }, + "interface": { + "type": [ + "string", + "null" + ], + "description": "IP address and port number to listen to.", + "default": null + } + }, + "default": { + "unix_socket": "/run/knot-resolver/kres-api.sock", + "interface": null + } + }, + "options": { + "description": "Fine-tuning global parameters of DNS resolver operation.", + "type": "object", + "properties": { + "glue-checking": { + "type": "string", + "enum": [ + "normal", + "strict", + "permissive" + ], + "description": "Glue records strictness checking level.", + "default": "normal" + }, + "minimize": { + "type": "boolean", + "description": "Send minimum amount of information in recursive queries to enhance privacy.", + "default": true + }, + "query-loopback": { + "type": "boolean", + "description": "Permits queries to loopback addresses.", + "default": false + }, + "reorder-rrset": { + "type": "boolean", + "description": "Controls whether resource records within a RRSet are reordered each time it is served from the cache.", + "default": true + }, + "query-case-randomization": { + "type": "boolean", + "description": "Randomize Query Character Case.", + "default": true + }, + "priming": { + "type": "boolean", + "description": "Initializing DNS resolver cache with Priming Queries (RFC 8109)", + "default": true + }, + "rebinding-protection": { + "type": "boolean", + "description": "Protection against DNS Rebinding attack.", + "default": false + }, + "refuse-no-rd": { + "type": "boolean", + "description": "Queries without RD (recursion desired) bit set in query are answered with REFUSED.", + "default": true + }, + "time-jump-detection": { + "type": "boolean", + "description": "Detection of difference between local system time and expiration time bounds in DNSSEC signatures for '. NS' records.", + "default": true + }, + "violators-workarounds": { + "type": "boolean", + "description": "Workarounds for known DNS protocol violators.", + "default": false + }, + "serve-stale": { + "type": "boolean", + "description": "Allows using timed-out records in case DNS resolver is unable to contact upstream servers.", + "default": false + } + }, + "default": { + "glue_checking": "normal", + "minimize": true, + "query_loopback": false, + "reorder_rrset": true, + "query_case_randomization": true, + "priming": true, + "rebinding_protection": false, + "refuse_no_rd": true, + "time_jump_detection": true, + "violators_workarounds": false, + "serve_stale": false + } + }, + "network": { + "description": "Network connections and protocols configuration.", + "type": "object", + "properties": { + "do-ipv4": { + "type": "boolean", + "description": "Enable/disable using IPv4 for contacting upstream nameservers.", + "default": true + }, + "do-ipv6": { + "type": "boolean", + "description": "Enable/disable using IPv6 for contacting upstream nameservers.", + "default": true + }, + "out-interface-v4": { + "type": [ + "string", + "null" + ], + "description": "IPv4 address used to perform queries. Not set by default, which lets the OS choose any address.", + "default": null + }, + "out-interface-v6": { + "type": [ + "string", + "null" + ], + "description": "IPv6 address used to perform queries. Not set by default, which lets the OS choose any address.", + "default": null + }, + "tcp-pipeline": { + "type": "integer", + "minimum": 0, + "maximum": 65535, + "description": "TCP pipeline limit. The number of outstanding queries that a single client connection can make in parallel.", + "default": 100 + }, + "edns-tcp-keepalive": { + "type": "boolean", + "description": "Allows clients to discover the connection timeout. (RFC 7828)", + "default": true + }, + "edns-buffer-size": { + "description": "Maximum EDNS payload size advertised in DNS packets. Different values can be configured for communication downstream (towards clients) and upstream (towards other DNS servers).", + "type": "object", + "properties": { + "upstream": { + "type": "string", + "pattern": "^(\\d+)(B|K|M|G)$", + "description": "Maximum EDNS upstream (towards other DNS servers) payload size.", + "default": "1232B" + }, + "downstream": { + "type": "string", + "pattern": "^(\\d+)(B|K|M|G)$", + "description": "Maximum EDNS downstream (towards clients) payload size for communication.", + "default": "1232B" + } + }, + "default": { + "upstream": "1232B", + "downstream": "1232B" + } + }, + "address-renumbering": { + "type": [ + "array", + "null" + ], + "items": { + "description": "Renumbers addresses in answers to different address space.", + "type": "object", + "properties": { + "source": { + "type": "string", + "description": "Source subnet." + }, + "destination": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Destination address prefix." + } + } + }, + "description": "Renumbers addresses in answers to different address space.", + "default": null + }, + "tls": { + "description": "TLS configuration, also affects DNS over TLS, DNS over HTTPS and DNS over QUIC.", + "type": "object", + "properties": { + "watchdog": { + "anyOf": [ + { + "type": "string", + "enum": [ + "auto" + ] + }, + { + "type": "boolean" + } + ], + "description": "Enables watchdog of changes in TLS certificate files. Requires the optional 'watchdog' dependency.", + "default": "auto" + }, + "cert-file": { + "type": [ + "string", + "null" + ], + "description": "Path to certificate file.", + "default": null + }, + "key-file": { + "type": [ + "string", + "null" + ], + "description": "Path to certificate key file.", + "default": null + }, + "sticket-secret": { + "type": [ + "string", + "null" + ], + "minLength": 32, + "description": "Secret for TLS session resumption via tickets. (RFC 5077).", + "default": null + }, + "sticket-secret-file": { + "type": [ + "string", + "null" + ], + "description": "Path to file with secret for TLS session resumption via tickets. (RFC 5077).", + "default": null + }, + "padding": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer", + "minimum": 0, + "maximum": 512 + } + ], + "description": "EDNS(0) padding of queries and answers sent over an encrypted channel.", + "default": true + } + }, + "default": { + "watchdog": true, + "cert_file": null, + "key_file": null, + "sticket_secret": null, + "sticket_secret_file": null, + "padding": true + } + }, + "proxy-protocol": { + "description": "PROXYv2 protocol configuration.", + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "Enable/disable PROXYv2 protocol.", + "default": false + }, + "allow": { + "type": [ + "array", + "null" + ], + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ] + }, + "description": "Allow usage of the PROXYv2 protocol headers by clients on the specified addresses.", + "default": null + } + }, + "default": { + "enable": false, + "allow": null + } + }, + "quic": { + "description": "DNS over QUIC configuration.", + "type": "object", + "properties": { + "max-conns": { + "type": "integer", + "minimum": 1, + "maximum": 4096, + "description": "Maximum number of active connections a single worker is allowed to accept.", + "default": 1024 + }, + "max-streams": { + "type": "integer", + "minimum": 1, + "maximum": 4096, + "description": "Maximum number of concurrent streams each connection is allowed to open. Each stream allocates > 64 KB of memory, setting this value too high might quicly consume a lot of memory. We recommend between 4 and 64.", + "default": 1024 + }, + "require-retry": { + "type": "boolean", + "description": "Require address validation for unknown source addresses. This adds a 1-RTT delay to connection establishment.", + "default": false + } + }, + "default": { + "max_conns": 1024, + "max_streams": 1024, + "require_retry": false + } + }, + "listen": { + "type": "array", + "items": { + "description": "Configuration of listening interface.", + "type": "object", + "properties": { + "interface": { + "anyOf": [ + { + "type": "null" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + } + ], + "description": "IP address or interface name with optional port number to listen to.", + "default": null + }, + "unix-socket": { + "anyOf": [ + { + "type": "null" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + } + ], + "description": "Path to unix domain socket to listen to.", + "default": null + }, + "port": { + "type": [ + "integer", + "null" + ], + "minimum": 1, + "maximum": 65535, + "description": "Port number to listen to.", + "default": null + }, + "kind": { + "type": "string", + "enum": [ + "dns", + "xdp", + "dot", + "doh-legacy", + "doh2", ++ "doh2-insecure", + "doq" + ], + "description": "Specifies DNS query transport protocol.", + "default": "dns" + }, + "freebind": { + "type": "boolean", + "description": "Used for binding to non-local address.", + "default": false + } + } + }, + "description": "List of interfaces to listen to and its configuration.", + "default": [ + { + "interface": [ + "127.0.0.1" + ], + "unix_socket": null, + "port": 53, + "kind": "dns", + "freebind": false + }, + { + "interface": [ + "::1" + ], + "unix_socket": null, + "port": 53, + "kind": "dns", + "freebind": true + } + ] + } + }, + "default": { + "do_ipv4": true, + "do_ipv6": true, + "out_interface_v4": null, + "out_interface_v6": null, + "tcp_pipeline": 100, + "edns_tcp_keepalive": true, + "edns_buffer_size": { + "upstream": "1232B", + "downstream": "1232B" + }, + "address_renumbering": null, + "tls": { + "watchdog": true, + "cert_file": null, + "key_file": null, + "sticket_secret": null, + "sticket_secret_file": null, + "padding": true + }, + "proxy_protocol": { + "enable": false, + "allow": null + }, + "quic": { + "max_conns": 1024, + "max_streams": 1024, + "require_retry": false + }, + "listen": [ + { + "interface": [ + "127.0.0.1" + ], + "unix_socket": null, + "port": 53, + "kind": "dns", + "freebind": false + }, + { + "interface": [ + "::1" + ], + "unix_socket": null, + "port": 53, + "kind": "dns", + "freebind": true + } + ] + } + }, + "views": { + "type": [ + "array", + "null" + ], + "items": { + "description": "Configuration parameters that allow you to create personalized policy rules and other.", + "type": "object", + "properties": { + "subnets": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Identifies the client based on his subnet. Rule with more precise subnet takes priority." + }, + "dst-subnet": { + "type": [ + "string", + "null" + ], + "description": "Destination subnet, as an additional condition.", + "default": null + }, + "protocols": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "enum": [ + "udp53", + "tcp53", + "dot", + "doh", + "doq" + ] + }, + "description": "Transport protocol, as an additional condition.", + "default": null + }, + "tags": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "pattern": "^(?!-)[a-z0-9-]*[a-z0-9]+$" + }, + "description": "Tags to link with other policy rules.", + "default": null + }, + "answer": { + "type": [ + "string", + "null" + ], + "enum": [ + "allow", + "refused", + "noanswer" + ], + "description": "Direct approach how to handle request from clients identified by the view.", + "default": null + }, + "options": { + "description": "Configuration options for clients identified by the view.", + "type": "object", + "properties": { + "minimize": { + "type": "boolean", + "description": "Send minimum amount of information in recursive queries to enhance privacy.", + "default": true + }, + "dns64": { + "type": "boolean", + "description": "Enable/disable DNS64.", + "default": true + }, + "price-factor": { + "type": "number", + "minimum": 0.0, + "maximum": 65535.0, + "description": "Multiplies rate-limiting and defer prices of operations, use 0 to whitelist.", + "default": 1.0 + }, + "fallback": { + "type": "boolean", + "description": "Enable/disable fallback on resolution failure.", + "default": true + } + }, + "default": { + "minimize": true, + "dns64": true, + "price_factor": 1.0, + "fallback": true + } + } + } + }, + "description": "List of views and its configuration.", + "default": null + }, + "local-data": { + "description": "Local data for forward records (A/AAAA) and reverse records (PTR).", + "type": "object", + "properties": { + "ttl": { + "type": [ + "string", + "null" + ], + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Default TTL value used for added local data/records.", + "default": null + }, + "nodata": { + "type": "boolean", + "description": "Use NODATA synthesis. NODATA will be synthesized for matching name, but mismatching type(e.g. AAAA query when only A exists).", + "default": true + }, + "addresses": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string" + } + ] + } + }, + { + "type": "string" + }, + { + "type": "string" + } + ] + }, + "description": "Direct addition of hostname and IP addresses pairs.", + "default": null + }, + "addresses-files": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Direct addition of hostname and IP addresses pairs from files in '/etc/hosts' like format.", + "default": null + }, + "records": { + "type": [ + "string", + "null" + ], + "description": "Direct addition of records in DNS zone file format.", + "default": null + }, + "rules": { + "type": [ + "array", + "null" + ], + "items": { + "description": "Local data advanced rule configuration.", + "type": "object", + "properties": { + "name": { + "anyOf": [ + { + "type": "null" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string", + "pattern": "(?=^.{,253}\\.?$)(^(?!-)[^.]{,62}[^.-](\\.(?!-)[^.]{,62}[^.-])*\\.?$)|^\\.$" + } + }, + { + "type": "string", + "pattern": "(?=^.{,253}\\.?$)(^(?!-)[^.]{,62}[^.-](\\.(?!-)[^.]{,62}[^.-])*\\.?$)|^\\.$" + } + ] + } + ], + "description": "Hostname(s).", + "default": null + }, + "subtree": { + "type": [ + "string", + "null" + ], + "enum": [ + "empty", + "nxdomain", + "redirect" + ], + "description": "Type of subtree.", + "default": null + }, + "address": { + "anyOf": [ + { + "type": "null" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string" + } + ] + } + }, + { + "type": "string" + }, + { + "type": "string" + } + ] + } + ], + "description": "Address(es) to pair with hostname(s).", + "default": null + }, + "file": { + "anyOf": [ + { + "type": "null" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + } + ], + "description": "Path to file(s) with hostname and IP address(es) pairs in '/etc/hosts' like format.", + "default": null + }, + "records": { + "type": [ + "string", + "null" + ], + "description": "Direct addition of records in DNS zone file format.", + "default": null + }, + "tags": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "pattern": "^(?!-)[a-z0-9-]*[a-z0-9]+$" + }, + "description": "Tags to link with other policy rules.", + "default": null + }, + "ttl": { + "type": [ + "string", + "null" + ], + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Optional, TTL value used for these answers.", + "default": null + }, + "nodata": { + "type": [ + "boolean", + "null" + ], + "description": "Optional, use NODATA synthesis. NODATA will be synthesized for matching name, but mismatching type(e.g. AAAA query when only A exists).", + "default": null + } + } + }, + "description": "Local data rules.", + "default": null + }, + "rpz": { + "type": [ + "array", + "null" + ], + "items": { + "description": "Configuration or Response Policy Zone (RPZ).", + "type": "object", + "properties": { + "file": { + "type": "string", + "description": "Path to the RPZ zone file." + }, + "watchdog": { + "anyOf": [ + { + "type": "string", + "enum": [ + "auto" + ] + }, + { + "type": "boolean" + } + ], + "description": "Enables files watchdog for configured RPZ file. Requires the optional 'watchdog' dependency.", + "default": "auto" + }, + "tags": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "pattern": "^(?!-)[a-z0-9-]*[a-z0-9]+$" + }, + "description": "Tags to link with other policy rules.", + "default": null + }, + "log": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "enum": [ + "ip", + "name" + ] + }, + "description": "Enables logging information whenever this RPZ matches.", + "default": null + } + } + }, + "description": "List of Response Policy Zones and its configuration.", + "default": null + } + }, + "default": { + "ttl": null, + "nodata": true, + "addresses": null, + "addresses_files": null, + "records": null, + "rules": null, + "rpz": null + } + }, + "forward": { + "type": [ + "array", + "null" + ], + "items": { + "description": "Configuration of forward subtree.", + "type": "object", + "properties": { + "subtree": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string", + "pattern": "(?=^.{,253}\\.?$)(^(?!-)[^.]{,62}[^.-](\\.(?!-)[^.]{,62}[^.-])*\\.?$)|^\\.$" + } + }, + { + "type": "string", + "pattern": "(?=^.{,253}\\.?$)(^(?!-)[^.]{,62}[^.-](\\.(?!-)[^.]{,62}[^.-])*\\.?$)|^\\.$" + } + ], + "description": "Subtree(s) to forward." + }, + "servers": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "description": "Forward server configuration.", + "type": "object", + "properties": { + "address": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ], + "description": "IP address(es) of a forward server." + }, + "transport": { + "type": [ + "string", + "null" + ], + "enum": [ + "tls" + ], + "description": "Transport protocol for a forward server.", + "default": null + }, + "pin-sha256": { + "anyOf": [ + { + "type": "null" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string", + "pattern": "^[A-Za-z\\d+/]{43}=$" + } + }, + { + "type": "string", + "pattern": "^[A-Za-z\\d+/]{43}=$" + } + ] + } + ], + "description": "Hash of accepted CA certificate.", + "default": null + }, + "hostname": { + "type": [ + "string", + "null" + ], + "pattern": "(?=^.{,253}\\.?$)(^(?!-)[^.]{,62}[^.-](\\.(?!-)[^.]{,62}[^.-])*\\.?$)|^\\.$", + "description": "Hostname of the Forward server.", + "default": null + }, + "ca-file": { + "type": [ + "string", + "null" + ], + "description": "Path to CA certificate file.", + "default": null + } + } + } + ] + }, + "description": "Forward servers configuration." + }, + "options": { + "description": "Subtree(s) forward options.", + "type": "object", + "properties": { + "authoritative": { + "type": "boolean", + "description": "The forwarding target is an authoritative server.", + "default": false + }, + "dnssec": { + "type": "boolean", + "description": "Enable/disable DNSSEC.", + "default": true + } + }, + "default": { + "authoritative": false, + "dnssec": true + } + } + } + }, + "description": "List of Forward Zones and its configuration.", + "default": null + }, + "fallback": { + "description": "Config for fallback on resolution failure.", + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "Enable/disable the fallback.", + "default": false + }, + "servers": { + "type": [ + "array", + "null" + ], + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "description": "Forward server configuration.", + "type": "object", + "properties": { + "address": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ], + "description": "IP address(es) of a forward server." + }, + "transport": { + "type": [ + "string", + "null" + ], + "enum": [ + "tls" + ], + "description": "Transport protocol for a forward server.", + "default": null + }, + "pin-sha256": { + "anyOf": [ + { + "type": "null" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string", + "pattern": "^[A-Za-z\\d+/]{43}=$" + } + }, + { + "type": "string", + "pattern": "^[A-Za-z\\d+/]{43}=$" + } + ] + } + ], + "description": "Hash of accepted CA certificate.", + "default": null + }, + "hostname": { + "type": [ + "string", + "null" + ], + "pattern": "(?=^.{,253}\\.?$)(^(?!-)[^.]{,62}[^.-](\\.(?!-)[^.]{,62}[^.-])*\\.?$)|^\\.$", + "description": "Hostname of the Forward server.", + "default": null + }, + "ca-file": { + "type": [ + "string", + "null" + ], + "description": "Path to CA certificate file.", + "default": null + } + } + } + ] + }, + "description": "Forward servers configuration for fallback.", + "default": null + } + }, + "default": { + "enable": false, + "servers": null + } + }, + "cache": { + "description": "DNS resolver cache configuration.", + "type": "object", + "properties": { + "storage": { + "type": "string", + "description": "Cache storage of the DNS resolver.", + "default": "/var/cache/knot-resolver" + }, + "size-max": { + "type": "string", + "pattern": "^(\\d+)(B|K|M|G)$", + "description": "Maximum size of the cache.", + "default": "100M" + }, + "garbage-collector": { + "description": "Use the garbage collector (kres-cache-gc) to periodically clear cache.", + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "Enable/disable cache garbage collector.", + "default": true + }, + "interval": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Time interval how often the garbage collector will be run.", + "default": "1s" + }, + "threshold": { + "type": "integer", + "minimum": 0, + "maximum": 100, + "description": "Cache usage in percent that triggers the garbage collector.", + "default": 80 + }, + "release": { + "type": "integer", + "minimum": 0, + "maximum": 100, + "description": "Percent of used cache to be freed by the garbage collector.", + "default": 10 + }, + "temp-keys-space": { + "type": "string", + "pattern": "^(\\d+)(B|K|M|G)$", + "description": "Maximum amount of temporary memory for copied keys (0 = unlimited).", + "default": "0M" + }, + "rw-deletes": { + "type": "integer", + "minimum": 0, + "description": "Maximum number of deleted records per read-write transaction (0 = unlimited).", + "default": 100 + }, + "rw-reads": { + "type": "integer", + "minimum": 0, + "description": "Maximum number of read records per read-write transaction (0 = unlimited).", + "default": 200 + }, + "rw-duration": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Maximum duration of read-write transaction (0 = unlimited).", + "default": "0us" + }, + "rw-delay": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Wait time between two read-write transactions.", + "default": "0us" + }, + "dry-run": { + "type": "boolean", + "description": "Run the garbage collector in dry-run mode.", + "default": false + } + }, + "default": { + "enable": true, + "interval": "1s", + "threshold": 80, + "release": 10, + "temp_keys_space": "0M", + "rw_deletes": 100, + "rw_reads": 200, + "rw_duration": "0us", + "rw_delay": "0us", + "dry_run": false + } + }, + "ttl-min": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Minimum time-to-live for the cache entries.", + "default": "5s" + }, + "ttl-max": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Maximum time-to-live for the cache entries.", + "default": "1d" + }, + "ns-timeout": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Time interval for which a nameserver address will be ignored after determining that it does not return (useful) answers.", + "default": "1000ms" + }, + "prefill": { + "type": [ + "array", + "null" + ], + "items": { + "description": "Prefill the cache periodically by importing zone data obtained over HTTP.", + "type": "object", + "properties": { + "origin": { + "type": "string", + "pattern": "(?=^.{,253}\\.?$)(^(?!-)[^.]{,62}[^.-](\\.(?!-)[^.]{,62}[^.-])*\\.?$)|^\\.$", + "description": "Origin for the imported data. Cache prefilling is only supported for the root zone ('.')." + }, + "url": { + "type": "string", + "description": "URL of the zone data to be imported." + }, + "refresh-interval": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Time interval between consecutive refreshes of the imported zone data.", + "default": "1d" + }, + "ca-file": { + "type": [ + "string", + "null" + ], + "description": "Path to the file containing a CA certificate bundle that is used to authenticate the HTTPS connection.", + "default": null + } + } + }, + "description": "Prefill the cache periodically by importing zone data obtained over HTTP.", + "default": null + }, + "prefetch": { + "description": "These options help keep the cache hot by prefetching expiring records or learning usage patterns and repetitive queries.", + "type": "object", + "properties": { + "expiring": { + "type": "boolean", + "description": "Prefetch expiring records.", + "default": false + }, + "prediction": { + "description": "Prefetch record by predicting based on usage patterns and repetitive queries.", + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "Enable/disable prediction.", + "default": false + }, + "window": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Sampling window length.", + "default": "15m" + }, + "period": { + "type": "integer", + "minimum": 1, + "description": "Number of windows that can be kept in memory.", + "default": 24 + } + }, + "default": { + "enable": false, + "window": "15m", + "period": 24 + } + } + }, + "default": { + "expiring": false, + "prediction": { + "enable": false, + "window": "15m", + "period": 24 + } + } + } + }, + "default": { + "storage": "/var/cache/knot-resolver", + "size_max": "100M", + "garbage_collector": { + "enable": true, + "interval": "1s", + "threshold": 80, + "release": 10, + "temp_keys_space": "0M", + "rw_deletes": 100, + "rw_reads": 200, + "rw_duration": "0us", + "rw_delay": "0us", + "dry_run": false + }, + "ttl_min": "5s", + "ttl_max": "1d", + "ns_timeout": "1000ms", + "prefill": null, + "prefetch": { + "expiring": false, + "prediction": { + "enable": false, + "window": "15m", + "period": 24 + } + } + } + }, + "dnssec": { + "description": "DNSSEC configuration.", + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "Enable/disable DNSSEC.", + "default": true + }, + "log-bogus": { + "type": "boolean", + "description": "Enable logging for each DNSSEC validation failure if '/logging/level' is set to at least 'notice'.", + "default": false + }, + "sentinel": { + "type": "boolean", + "description": "Allows users of DNSSEC validating resolver to detect which root keys are configured in resolver's chain of trust. (RFC 8509)", + "default": true + }, + "signal-query": { + "type": "boolean", + "description": "Signaling Trust Anchor Knowledge in DNSSEC Using Key Tag Query, according to (RFC 8145#section-5).", + "default": true + }, + "trust-anchors": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Trust-anchors configuration.", + "default": null + }, + "trust-anchors-files": { + "type": [ + "array", + "null" + ], + "items": { + "description": "Trust-anchor zonefile configuration.", + "type": "object", + "properties": { + "file": { + "type": "string", + "description": "Path to the zonefile that stores trust-anchors." + }, + "read-only": { + "type": "boolean", + "description": "Blocks zonefile updates according to RFC 5011.", + "default": false + } + } + }, + "description": "List of zone-files where trust-anchors are stored.", + "default": null + }, + "negative-trust-anchors": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "pattern": "(?=^.{,253}\\.?$)(^(?!-)[^.]{,62}[^.-](\\.(?!-)[^.]{,62}[^.-])*\\.?$)|^\\.$" + }, + "description": "List of domain names representing negative trust-anchors. (RFC 7646)", + "default": null + } + }, + "default": { + "enable": true, + "log_bogus": false, + "sentinel": true, + "signal_query": true, + "trust_anchors": null, + "trust_anchors_files": null, + "negative_trust_anchors": null + } + }, + "dns64": { + "description": "DNS64 (RFC 6147) configuration.", + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "Enable/disable DNS64.", + "default": false + }, + "prefix": { + "type": "string", + "description": "IPv6 prefix to be used for synthesizing AAAA records.", + "default": "64:ff9b::/96" + }, + "reverse-ttl": { + "type": [ + "string", + "null" + ], + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "TTL in CNAME generated in the reverse 'ip6.arpa.' subtree.", + "default": null + }, + "exclude-subnets": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "IPv6 subnets that are disallowed in answer.", + "default": null + } + }, + "default": { + "enable": false, + "prefix": "64:ff9b::/96", + "reverse_ttl": null, + "exclude_subnets": null + } + }, + "logging": { + "description": "Logging and debugging configuration.", + "type": "object", + "properties": { + "level": { + "type": "string", + "enum": [ + "crit", + "err", + "warning", + "notice", + "info", + "debug" + ], + "description": "Global logging level.", + "default": "notice" + }, + "target": { + "anyOf": [ + { + "type": "string", + "enum": [ + "syslog", + "stderr", + "stdout" + ] + }, + { + "type": "string", + "enum": [ + "from-env" + ] + } + ], + "description": "Global logging stream target. \"from-env\" uses $KRES_LOGGING_TARGET and defaults to \"stdout\".", + "default": "from-env" + }, + "groups": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "enum": [ + "manager", + "supervisord", + "policy-loader", + "kresd", + "cache-gc", + "files", + "metrics", + "server", + "system", + "cache", + "io", + "net", + "ta", + "tasent", + "tasign", + "taupd", + "tls", + "gnutls", + "tls_cl", + "xdp", + "doh", + "dnssec", + "hint", + "plan", + "iterat", + "valdtr", + "resolv", + "select", + "zoncut", + "cookie", + "statis", + "rebind", + "worker", + "policy", + "daf", + "timejm", + "timesk", + "graphi", + "prefil", + "primin", + "srvstl", + "wtchdg", + "nsid", + "dnstap", + "tests", + "dotaut", + "http", + "contrl", + "module", + "devel", + "renum", + "exterr", + "rules", + "prlayr", + "defer", + "doq", + "ngtcp2" + ] + }, + "description": "List of groups for which 'debug' logging level is set.", + "default": null + }, + "dnstap": { + "description": "Logging DNS requests and responses to a unix socket.", + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "Enable/disable DNS queries logging.", + "default": false + }, + "unix-socket": { + "type": [ + "string", + "null" + ], + "description": "Path to unix domain socket where dnstap messages will be sent.", + "default": null + }, + "log-queries": { + "type": "boolean", + "description": "Log queries from downstream in wire format.", + "default": false + }, + "log-responses": { + "type": "boolean", + "description": "Log responses to downstream in wire format.", + "default": false + }, + "log-tcp-rtt": { + "type": "boolean", + "description": "Log TCP RTT (Round-trip time).", + "default": false + } + }, + "default": { + "enable": false, + "unix_socket": null, + "log_queries": false, + "log_responses": false, + "log_tcp_rtt": false + } + } + }, + "default": { + "level": "notice", + "target": "stdout", + "groups": null, + "dnstap": { + "enable": false, + "unix_socket": null, + "log_queries": false, + "log_responses": false, + "log_tcp_rtt": false + } + } + }, + "monitoring": { + "description": "Metrics exposition configuration (Prometheus, Graphite)", + "type": "object", + "properties": { + "metrics": { + "type": "string", + "enum": [ + "manager-only", + "lazy", + "always" + ], + "description": "configures, whether metrics/statistics will be collected by the resolver", + "default": "lazy" + }, + "graphite": { + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "default": false + }, + "host": { + "anyOf": [ + { + "type": "null" + }, + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string", + "pattern": "(?=^.{,253}\\.?$)(^(?!-)[^.]{,62}[^.-](\\.(?!-)[^.]{,62}[^.-])*\\.?$)|^\\.$" + } + ], + "default": null + }, + "port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "default": 2003 + }, + "prefix": { + "type": "string", + "default": "" + }, + "interval": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "default": "5s" + }, + "tcp": { + "type": "boolean", + "default": false + } + }, + "description": "optionally configures where should graphite metrics be sent to", + "default": { + "enable": false, + "host": null, + "port": 2003, + "prefix": "", + "interval": "5s", + "tcp": false + } + } + }, + "default": { + "metrics": "lazy", + "graphite": { + "enable": false, + "host": null, + "port": 2003, + "prefix": "", + "interval": "5s", + "tcp": false + } + } + }, + "rate-limiting": { + "description": "Configuration of rate limiting.", + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "Enable/disable rate limiting", + "default": false + }, + "rate-limit": { + "type": [ + "integer", + "null" + ], + "minimum": 1, + "description": "Maximal number of allowed queries per second from a single host.", + "default": null + }, + "instant-limit": { + "type": "integer", + "minimum": 1, + "description": "Maximal number of allowed queries at a single point in time from a single host.", + "default": 50 + }, + "capacity": { + "type": "integer", + "minimum": 1, + "description": "Expected maximal number of blocked networks/hosts at the same time.", + "default": 524288 + }, + "slip": { + "type": "integer", + "minimum": 0, + "maximum": 32, + "description": "Number of restricted responses out of which one is sent as truncated, the others are dropped.", + "default": 2 + }, + "log-period": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Minimal time between two log messages, or '0s' to disable.", + "default": "0s" + }, + "dry-run": { + "type": "boolean", + "description": "Perform only classification and logging but no restrictions.", + "default": false + } + }, + "default": { + "enable": false, + "rate_limit": null, + "instant_limit": 50, + "capacity": 524288, + "slip": 2, + "log_period": "0s", + "dry_run": false + } + }, + "defer": { + "description": "Configuration of request prioritization (defer).", + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "Use request prioritization.", + "default": true + }, + "log-period": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Minimal time between two log messages, or '0s' to disable.", + "default": "0s" + } + }, + "default": { + "enable": true, + "log_period": "0s" + } + }, + "lua": { + "description": "Custom Lua configuration.", + "type": "object", + "properties": { + "script-only": { + "type": "boolean", + "description": "Ignore declarative configuration intended for workers and use only Lua script or script file configured in this section.", + "default": false + }, + "script": { + "type": [ + "string", + "null" + ], + "description": "Custom Lua configuration script intended for workers.", + "default": null + }, + "script-file": { + "type": [ + "string", + "null" + ], + "description": "Path to file that contains Lua configuration script for workers.", + "default": null + }, + "policy-script-only": { + "type": "boolean", + "description": "Ignore declarative configuration intended for policy-loader and use only Lua script or script file configured in this section.", + "default": false + }, + "policy-script": { + "type": [ + "string", + "null" + ], + "description": "Custom Lua configuration script intended for policy-loader.", + "default": null + }, + "policy-script-file": { + "type": [ + "string", + "null" + ], + "description": "Path to file that contains Lua configuration script for policy-loader.", + "default": null + } + }, + "default": { + "script_only": false, + "script": null, + "script_file": null, + "policy_script_only": false, + "policy_script": null, + "policy_script_file": null + } + } + } +} diff --cc lib/proto.h index f17fcad04,415effe0f..9e9d1e439 --- a/lib/proto.h +++ b/lib/proto.h @@@ -26,9 -26,9 +26,10 @@@ XX(TCP53, tcp53, "DNS TCP") \ XX(DOT, dot, "DNS-over-TLS") \ XX(DOH, doh, "DNS-over-HTTPS") \ + XX(DOH_INSECURE, doh_insecure, "Insecure DNS-over-HTTP") \ - XX(DOQ, doq, "DNS-over-QUIC") /* unused for now */ \ - // + XX(DOQ, doq_demux, "DNS-over-QUIC-demux") \ + XX(DOQ_CONN, doq_conn, "DNS-over-QUIC-conn") \ + XX(DOQ_STREAM, doq_stream, "DNS-over-QUIC-stream") \ /** DNS protocol set - mutually exclusive options, contrary to * kr_request_qsource_flags diff --cc python/knot_resolver/datamodel/network_schema.py index e017fc70c,b5c635b48..2d8a3a68d --- a/python/knot_resolver/datamodel/network_schema.py +++ b/python/knot_resolver/datamodel/network_schema.py @@@ -14,13 -16,11 +14,13 @@@ from knot_resolver.datamodel.types impo IPv6Address, ListOrItem, PortNumber, + ReadableFile, SizeUnit, + WritableFilePath, ) -from knot_resolver_manager.utils.modeling import ConfigSchema +from knot_resolver.utils.modeling import ConfigSchema - KindEnum = Literal["dns", "xdp", "dot", "doh-legacy", "doh2", "doq"] -KindEnum = Literal["dns", "xdp", "dot", "doh-legacy", "doh2", "doh2-insecure"] ++KindEnum = Literal["dns", "xdp", "dot", "doh-legacy", "doh2", "doh2-insecure", "doq"] class EdnsBufferSizeSchema(ConfigSchema): @@@ -155,11 -118,13 +155,13 @@@ class ListenSchema(ConfigSchema) if origin.port: return origin.port # default port number based on kind - elif origin.interface: - if origin.kind == "dot": + if origin.interface: + if origin.kind in ["dot", "doq"]: return PortNumber(853) - elif origin.kind in ["doh-legacy", "doh2"]: + if origin.kind in ["doh-legacy", "doh2"]: return PortNumber(443) - elif origin.kind == "doh2-insecure": ++ if origin.kind == "doh2-insecure": + return PortNumber(80) return PortNumber(53) return None