syntax = "proto3";

package envoy.extensions.common.dynamic_forward_proxy.v3;

import "envoy/config/cluster/v3/cluster.proto";
import "envoy/config/common/key_value/v3/config.proto";
import "envoy/config/core/v3/address.proto";
import "envoy/config/core/v3/extension.proto";
import "envoy/config/core/v3/resolver.proto";
import "envoy/type/matcher/v3/address.proto";

import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

import "envoy/annotations/deprecation.proto";
import "udpa/annotations/status.proto";
import "udpa/annotations/versioning.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.common.dynamic_forward_proxy.v3";
option java_outer_classname = "DnsCacheProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/common/dynamic_forward_proxy/v3;dynamic_forward_proxyv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Dynamic forward proxy common configuration]

// Configuration of circuit breakers for resolver.
message DnsCacheCircuitBreakers {
  // The maximum number of pending requests that Envoy will allow to the
  // resolver. If not specified, the default is 1024.
  google.protobuf.UInt32Value max_pending_requests = 1;
}

// Configuration for the dynamic forward proxy DNS cache. See the :ref:`architecture overview
// <arch_overview_http_dynamic_forward_proxy>` for more information.
// [#next-free-field: 17]
message DnsCacheConfig {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.common.dynamic_forward_proxy.v2alpha.DnsCacheConfig";

  // The name of the cache. Multiple named caches allow independent dynamic forward proxy
  // configurations to operate within a single Envoy process using different configurations. All
  // configurations with the same name *must* otherwise have the same settings when referenced
  // from different configuration components. Configuration will fail to load if this is not
  // the case.
  string name = 1 [(validate.rules).string = {min_len: 1}];

  // The DNS lookup family to use during resolution.
  //
  // [#comment:TODO(mattklein123): Figure out how to support IPv4/IPv6 "happy eyeballs" mode. The
  // way this might work is a new lookup family which returns both IPv4 and IPv6 addresses, and
  // then configures a host to have a primary and fall back address. With this, we could very
  // likely build a "happy eyeballs" connection pool which would race the primary / fall back
  // address and return the one that wins. This same method could potentially also be used for
  // QUIC to TCP fall back.]
  config.cluster.v3.Cluster.DnsLookupFamily dns_lookup_family = 2
      [(validate.rules).enum = {defined_only: true}];

  // The DNS refresh rate for unresolved DNS hosts. If not specified defaults to 60s.
  //
  // The refresh rate is rounded to the closest millisecond, and must be at least 1ms.
  //
  // Once a host has been resolved, the refresh rate will be the DNS TTL, capped
  // at a minimum of ``dns_min_refresh_rate``.
  google.protobuf.Duration dns_refresh_rate = 3
      [(validate.rules).duration = {gte {nanos: 1000000}}];

  // The minimum rate that DNS resolution will occur. Per ``dns_refresh_rate``, once a host is
  // resolved, the DNS TTL will be used, with a minimum set by ``dns_min_refresh_rate``.
  // ``dns_min_refresh_rate`` defaults to 5s and must also be >= 1s.
  google.protobuf.Duration dns_min_refresh_rate = 14
      [(validate.rules).duration = {gte {seconds: 1}}];

  // The TTL for hosts that are unused. Hosts that have not been used in the configured time
  // interval will be purged. If not specified defaults to 5m.
  //
  // .. note:
  //
  //   The TTL is only checked at the time of DNS refresh, as specified by ``dns_refresh_rate``. This
  //   means that if the configured TTL is shorter than the refresh rate the host may not be removed
  //   immediately.
  //
  //  .. note:
  //
  //   The TTL has no relation to DNS TTL and is only used to control Envoy's resource usage.
  google.protobuf.Duration host_ttl = 4 [(validate.rules).duration = {gt {}}];

  // The maximum number of hosts that the cache will hold. If not specified defaults to 1024.
  //
  // .. note:
  //
  //   The implementation is approximate and enforced independently on each worker thread, thus
  //   it is possible for the maximum hosts in the cache to go slightly above the configured
  //   value depending on timing. This is similar to how other circuit breakers work.
  google.protobuf.UInt32Value max_hosts = 5 [(validate.rules).uint32 = {gt: 0}];

  // Disable the DNS refresh on failure. If this field is set to true, it will ignore the
  // :ref:`typed_dns_resolver_config <envoy_v3_api_field_extensions.common.dynamic_forward_proxy.v3.DnsCacheConfig.dns_failure_refresh_rate>`.
  // If not specified, it defaults to false. By enabling this feature, the failed hosts will now be treated as a cache miss,
  // allowing the failed hosts to be resolved on demand.
  bool disable_dns_refresh_on_failure = 15;

  // If the DNS failure refresh rate is specified,
  // this is used as the cache's DNS refresh rate when DNS requests are failing. If this setting is
  // not specified, the failure refresh rate defaults to the dns_refresh_rate.
  config.cluster.v3.Cluster.RefreshRate dns_failure_refresh_rate = 6;

  // The config of circuit breakers for resolver. It provides a configurable threshold.
  // Envoy will use dns cache circuit breakers with default settings even if this value is not set.
  DnsCacheCircuitBreakers dns_cache_circuit_breaker = 7;

  // Always use TCP queries instead of UDP queries for DNS lookups.
  // This field is deprecated in favor of ``dns_resolution_config``
  // which aggregates all of the DNS resolver configuration in a single message.
  bool use_tcp_for_dns_lookups = 8
      [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"];

  // DNS resolution configuration which includes the underlying dns resolver addresses and options.
  // This field is deprecated in favor of
  // :ref:`typed_dns_resolver_config <envoy_v3_api_field_extensions.common.dynamic_forward_proxy.v3.DnsCacheConfig.typed_dns_resolver_config>`.
  config.core.v3.DnsResolutionConfig dns_resolution_config = 9
      [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"];

  // DNS resolver type configuration extension. This extension can be used to configure c-ares, apple,
  // or any other DNS resolver types and the related parameters.
  // For example, an object of
  // :ref:`CaresDnsResolverConfig <envoy_v3_api_msg_extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig>`
  // can be packed into this ``typed_dns_resolver_config``. This configuration replaces the
  // :ref:`dns_resolution_config <envoy_v3_api_field_extensions.common.dynamic_forward_proxy.v3.DnsCacheConfig.dns_resolution_config>`
  // configuration.
  // During the transition period when both ``dns_resolution_config`` and ``typed_dns_resolver_config`` exists,
  // when ``typed_dns_resolver_config`` is in place, Envoy will use it and ignore ``dns_resolution_config``.
  // When ``typed_dns_resolver_config`` is missing, the default behavior is in place.
  // [#extension-category: envoy.network.dns_resolver]
  config.core.v3.TypedExtensionConfig typed_dns_resolver_config = 12;

  // Hostnames that should be preresolved into the cache upon creation. This might provide a
  // performance improvement, in the form of cache hits, for hostnames that are going to be
  // resolved during steady state and are known at config load time.
  repeated config.core.v3.SocketAddress preresolve_hostnames = 10;

  // The timeout used for DNS queries. This timeout is independent of any timeout and retry policy
  // used by the underlying DNS implementation (e.g., c-areas and Apple DNS) which are opaque.
  // Setting this timeout will ensure that queries succeed or fail within the specified time frame
  // and are then retried using the standard refresh rates. Setting it to 0 will disable the Envoy DNS
  // query timeout and use the underlying DNS implementation timeout. Defaults to 5s if not set.
  google.protobuf.Duration dns_query_timeout = 11 [(validate.rules).duration = {gte {}}];

  // Configuration to flush the DNS cache to long term storage.
  config.common.key_value.v3.KeyValueStoreConfig key_value_config = 13;

  // Optional matcher to filter out DNS resolution results that match specific IP address ranges.
  // If a DNS response contains addresses matching this matcher, those addresses will be
  // removed from the response. If all addresses are removed, the resolution is treated
  // as a failure and the host will retain any previously resolved address.
  // This can be used as an SSRF protection mechanism to prevent DNS rebinding attacks
  // that resolve to internal/private IP addresses.
  type.matcher.v3.AddressMatcher resolved_address_filter = 16;
}
