--- /dev/null
+.. 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>`.
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
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.
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
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]
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.")
-{% 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 %}
{% endfor %}
{% endfor %}
{% endif %}
+
+
+{% if cfg.fallback and cfg.fallback.enable %}
+modules.load('fallback')
+fallback.config({
+ targets = {{ forward_servers(cfg.fallback.servers) }},
+ options = {},
+})
+{% endif %}