syntax = "proto3";

package envoy.extensions.filters.listener.proxy_protocol.v3;

import "envoy/config/core/v3/proxy_protocol.proto";

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

option java_package = "io.envoyproxy.envoy.extensions.filters.listener.proxy_protocol.v3";
option java_outer_classname = "ProxyProtocolProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/proxy_protocol/v3;proxy_protocolv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Proxy Protocol Filter]
// PROXY protocol listener filter.
// [#extension: envoy.filters.listener.proxy_protocol]

// [#next-free-field: 7]
message ProxyProtocol {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.listener.proxy_protocol.v2.ProxyProtocol";

  // Controls where TLV values are stored when rules match.
  enum TlvLocation {
    // Store TLV values in dynamic metadata.
    DYNAMIC_METADATA = 0;

    // Store TLV values in filter state as a single map-like object.
    FILTER_STATE = 1;
  }

  message KeyValuePair {
    // Specifies the encoding scheme that is used to encode the TLV value before it is
    // stored in dynamic metadata or filter state.
    enum ValueStringEncoding {
      // Unspecified encoding scheme. Defaults to ``SANITIZED_UTF8``.
      UNSPECIFIED = 0;

      // The TLV value will be sanitized to a valid UTF-8 string before being stored:
      // any invalid UTF-8 sequences will be replaced with the ``!`` character.
      SANITIZED_UTF8 = 1;

      // The raw TLV value will be encoded as a `Base64 <https://datatracker.ietf.org/doc/html/rfc4648#section-4>`_
      // string (with padding) before being stored. This is useful for binary TLV values that
      // are not valid UTF-8 strings.
      BASE64 = 2;
    }

    // The namespace — if this is empty, the filter's namespace will be used.
    string metadata_namespace = 1;

    // The key to use within the namespace.
    string key = 2 [(validate.rules).string = {min_len: 1}];

    // The value encoding scheme that is used to encode the TLV value before it is stored in
    // dynamic metadata or filter state. If not set, defaults to ``SANITIZED_UTF8``, which
    // sanitizes the TLV value to a valid UTF-8 string.
    //
    // .. note::
    //
    //   This option only applies to the legacy untyped dynamic metadata and filter state.
    //   For the new typed dynamic metadata, the raw TLV value bytes are stored as is and
    //   no encoding is applied.
    ValueStringEncoding value_string_encoding = 3;
  }

  // A Rule defines what metadata to apply when a header is present or missing.
  message Rule {
    // The type that triggers the rule - required
    // TLV type is defined as uint8_t in proxy protocol. See `the spec
    // <https://www.haproxy.org/download/2.1/doc/proxy-protocol.txt>`_ for details.
    uint32 tlv_type = 1 [(validate.rules).uint32 = {lt: 256}];

    // If the TLV type is present, apply this metadata KeyValuePair.
    KeyValuePair on_tlv_present = 2;
  }

  // The list of rules to apply to requests.
  repeated Rule rules = 1;

  // Allow requests through that don't use proxy protocol. Defaults to false.
  //
  // .. attention::
  //
  //   This breaks conformance with the specification.
  //   Only enable if ALL traffic to the listener comes from a trusted source.
  //   For more information on the security implications of this feature, see
  //   https://www.haproxy.org/download/2.1/doc/proxy-protocol.txt
  //
  // .. attention::
  //
  //   Requests of 12 or fewer bytes that match the proxy protocol v2 signature
  //   and requests of 6 or fewer bytes that match the proxy protocol v1
  //   signature will timeout (Envoy is unable to differentiate these requests
  //   from incomplete proxy protocol requests).
  bool allow_requests_without_proxy_protocol = 2;

  // This config controls which TLVs can be passed to filter state if it is Proxy Protocol
  // V2 header. If there is no setting for this field, no TLVs will be passed through.
  //
  // .. note::
  //
  //   If this is configured, you likely also want to set
  //   :ref:`core.v3.ProxyProtocolConfig.pass_through_tlvs <envoy_v3_api_field_config.core.v3.ProxyProtocolConfig.pass_through_tlvs>`,
  //   which controls pass-through for the upstream.
  config.core.v3.ProxyProtocolPassThroughTLVs pass_through_tlvs = 3;

  // The PROXY protocol versions that won't be matched. Useful to limit the scope and attack surface of the filter.
  //
  // When the filter receives PROXY protocol data that is disallowed, it will reject the connection.
  // By default, the filter will match all PROXY protocol versions.
  // See https://www.haproxy.org/download/2.1/doc/proxy-protocol.txt for details.
  //
  // .. attention::
  //
  //   When used in conjunction with the :ref:`allow_requests_without_proxy_protocol <envoy_v3_api_field_extensions.filters.listener.proxy_protocol.v3.ProxyProtocol.allow_requests_without_proxy_protocol>`,
  //   the filter will not attempt to match signatures for the disallowed versions.
  //   For example, when ``disallowed_versions=V2``, ``allow_requests_without_proxy_protocol=true``,
  //   and an incoming request matches the V2 signature, the filter will allow the request through without any modification.
  //   The filter treats this request as if it did not have any PROXY protocol information.
  repeated config.core.v3.ProxyProtocolConfig.Version disallowed_versions = 4;

  // The human readable prefix to use when emitting statistics for the filter.
  // If not configured, statistics will be emitted without the prefix segment.
  // See the :ref:`filter's statistics documentation <config_listener_filters_proxy_protocol>` for
  // more information.
  string stat_prefix = 5;

  // Controls where TLV values are stored when rules match. Defaults to DYNAMIC_METADATA.
  TlvLocation tlv_location = 6;
}
