]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
fallback: add YAML config + docs docs-fallback-bwj41e/deployments/7448 fallback 1733/head
authorVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 21 Aug 2025 12:26:09 +0000 (14:26 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 21 Aug 2025 14:11:57 +0000 (16:11 +0200)
doc/user/config-fallback.rst [new file with mode: 0644]
doc/user/config-performance.rst
python/knot_resolver/datamodel/config_schema.py
python/knot_resolver/datamodel/forward_schema.py
python/knot_resolver/datamodel/templates/forward.lua.j2

diff --git a/doc/user/config-fallback.rst b/doc/user/config-fallback.rst
new file mode 100644 (file)
index 0000000..7a45abb
--- /dev/null
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-3.0-or-later
+
+.. _config-serve-stale:
+
+Fallback on resolution failure
+==============================
+
+This allows switching to a fallback forwarding configuration on queries where the resolver is unable to contact upstream servers.
+
+.. code-block:: yaml
+
+        fallback:
+          enable: true
+          servers:
+            - address: [ 2001:148f:fffe::1, 193.17.47.1 ]
+              transport: tls
+              hostname: odvr.nic.cz
+
+The ``servers:`` has the same schema as in :ref:`forwarding <config-forward>`.
+
+If you use fallback within a fleet of servers,
+you will probably want to avoid queries cycling in there,
+i.e. disable the fallback option for them in :ref:`views <config-views>`.
index 1d3604d8cec7dc730d42caa73ab310c27ecaf6f7..481d357d32988d083c84e0c46dc8bfb7b0a3b22d 100644 (file)
@@ -29,6 +29,7 @@ impact than cache settings and number of workers.
    config-cache-predict
    config-cache-prefill
    config-serve-stale
+   config-fallback
    config-rfc7706
    config-priming
    config-edns-keepalive
index 2cc2680c9203cc15d6dad21f0633f0a1ac7ecdf8..54155001b42466bc2ef3dbc94f205f50dd8b4b09 100644 (file)
@@ -8,7 +8,7 @@ from knot_resolver.datamodel.cache_schema import CacheSchema
 from knot_resolver.datamodel.defer_schema import DeferSchema
 from knot_resolver.datamodel.dns64_schema import Dns64Schema
 from knot_resolver.datamodel.dnssec_schema import DnssecSchema
-from knot_resolver.datamodel.forward_schema import ForwardSchema
+from knot_resolver.datamodel.forward_schema import ForwardSchema, FallbackSchema
 from knot_resolver.datamodel.globals import Context, get_global_validation_context, set_global_validation_context
 from knot_resolver.datamodel.local_data_schema import LocalDataSchema, RPZSchema, RuleSchema
 from knot_resolver.datamodel.logging_schema import LoggingSchema
@@ -102,6 +102,7 @@ class KresConfig(ConfigSchema):
         views: List of views and its configuration.
         local_data: Local data for forward records (A/AAAA) and reverse records (PTR).
         forward: List of Forward Zones and its configuration.
+        fallback: Config for fallback on resolution failure.
         cache: DNS resolver cache configuration.
         dnssec: Disable DNSSEC, enable with defaults or set new configuration.
         dns64: Disable DNS64 (RFC 6147), enable with defaults or set new configuration.
@@ -125,6 +126,7 @@ class KresConfig(ConfigSchema):
         views: Optional[List[ViewSchema]] = None
         local_data: LocalDataSchema = LocalDataSchema()
         forward: Optional[List[ForwardSchema]] = None
+        fallback: FallbackSchema = FallbackSchema()
         cache: CacheSchema = lazy_default(CacheSchema, {})
         dnssec: Union[bool, DnssecSchema] = True
         dns64: Union[bool, Dns64Schema] = False
@@ -148,6 +150,7 @@ class KresConfig(ConfigSchema):
     views: Optional[List[ViewSchema]]
     local_data: LocalDataSchema
     forward: Optional[List[ForwardSchema]]
+    fallback: FallbackSchema
     cache: CacheSchema
     dnssec: Union[Literal[False], DnssecSchema]
     dns64: Union[Literal[False], Dns64Schema]
index 6b693e6be475c4dccdca895ab3c640bbcc75153f..79064fe8c55e1634aec0bfa016d99db1c21d0e95 100644 (file)
@@ -74,3 +74,20 @@ class ForwardSchema(ConfigSchema):
 
         if self.options.authoritative and is_transport_tls(self.servers):
             raise ValueError("Forwarding to authoritative servers using TLS protocol is not supported.")
+
+
+class FallbackSchema(ConfigSchema):
+    """
+    Configuration for fallback after resolution failure.
+
+    ---
+    enable: Enable/disable the fallback.
+    servers: Forward servers configuration for fallback.
+    """
+
+    enable: bool = False
+    servers: Union[List[IPAddressOptionalPort], List[ForwardServerSchema], None] = None
+
+    def _validate(self) -> None:
+        if self.enable and self.servers is None:
+            raise ValueError("Fallback enabled without configuring servers.")
index 24311da183ade67b39ba0f451b7348777688d624..bc4d73ef6b57743ab0f149917b8176d88156bf5a 100644 (file)
@@ -1,4 +1,4 @@
-{% from 'macros/forward_macros.lua.j2' import policy_rule_forward_add %}
+{% from 'macros/forward_macros.lua.j2' import policy_rule_forward_add, forward_servers %}
 
 {% if cfg.forward %}
 {% for fwd in cfg.forward %}
@@ -7,3 +7,12 @@
 {% endfor %}
 {% endfor %}
 {% endif %}
+
+
+{% if cfg.fallback and cfg.fallback.enable %}
+modules.load('fallback')
+fallback.config({
+  targets = {{ forward_servers(cfg.fallback.servers) }},
+  options = {},
+})
+{% endif %}