]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
Merge master into naked-http
authorVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 15 Jul 2026 09:00:32 +0000 (11:00 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 5 Aug 2026 06:35:56 +0000 (08:35 +0200)
1  2 
daemon/bindings/net.c
daemon/io.c
daemon/lua/kres-gen-33.lua
daemon/session2.c
doc/_static/config.schema.json
lib/proto.h
python/knot_resolver/datamodel/network_schema.py

index e5f5fa4e202c929503fa8255333ac0b3a0b387a6,b4f139874246fbc8136e6d96a05cc7b66be1257d..d20dd62108b13e2d76491763df32510a45dc0d33
@@@ -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/io.c
Simple merge
index 96eed7734724ead30fad4f5564f5cceea5eb0ec1,9edee2de41e4e0f87dfd771595e7cf67bce329e3..49866e98bd3c0f2ece6caf0c2c0aeb1e42be4448
@@@ -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;
index 136ae745a9d6c801dd3dfa439246dc9061928900,c451ef4a7af008250dcb56fd1567f653213ca489..d1111445a5372041cccd7c6b76deadd341db0e27
@@@ -67,21 -60,15 +67,29 @@@ static const enum protolayer_type proto
        PROTOLAYER_TYPE_DNS_UNSIZED_STREAM,
  };
  
 -static const enum protolayer_type protolayer_grp_doq[] = {
 -      // not yet used
+ 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_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,
  };
  
index c0f522d855d894b0cedb7b36efdcf6a7d0f1d63c,0000000000000000000000000000000000000000..8ccf19ba0c08e6e84362b406b24277a5e130b4e1
mode 100644,000000..100644
--- /dev/null
@@@ -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 f17fcad0423204f6bf94075f3f00201cb3c40c6a,415effe0f0ffd72bc7260b53ff059f443201cfb6..9e9d1e43935a0cd33cf1b9542375c070be428b8d
      XX(TCP53, tcp53, "DNS TCP") \
      XX(DOT, dot, "DNS-over-TLS") \
      XX(DOH, doh, "DNS-over-HTTPS") \
 -    XX(DOQ, doq, "DNS-over-QUIC") /* unused for now */ \
 -    //
+     XX(DOH_INSECURE, doh_insecure, "Insecure DNS-over-HTTP") \
 +    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
index e017fc70c2d4a107f33520e9e7ac035d6cba80c7,b5c635b4881c4d2a52522e1ed20dd67b90104eab..2d8a3a68dbb2101ac6968e3c50c4903c08e0a5bb
@@@ -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