syntax = "proto3";

package envoy.config.filter.network.tcp_proxy.v2;

import "envoy/api/v2/core/address.proto";
import "envoy/api/v2/core/base.proto";
import "envoy/config/filter/accesslog/v2/accesslog.proto";
import "envoy/type/hash_policy.proto";

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

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

option java_package = "io.envoyproxy.envoy.config.filter.network.tcp_proxy.v2";
option java_outer_classname = "TcpProxyProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/tcp_proxy/v2;tcp_proxyv2";
option (udpa.annotations.file_migrate).move_to_package =
    "envoy.extensions.filters.network.tcp_proxy.v3";
option (udpa.annotations.file_status).package_version_status = FROZEN;

// [#protodoc-title: TCP Proxy]
// TCP Proxy :ref:`configuration overview <config_network_filters_tcp_proxy>`.
// [#extension: envoy.filters.network.tcp_proxy]

// [#next-free-field: 13]
message TcpProxy {
  // [#not-implemented-hide:] Deprecated.
  // TCP Proxy filter configuration using V1 format.
  message DeprecatedV1 {
    option deprecated = true;

    // A TCP proxy route consists of a set of optional L4 criteria and the
    // name of a cluster. If a downstream connection matches all the
    // specified criteria, the cluster in the route is used for the
    // corresponding upstream connection. Routes are tried in the order
    // specified until a match is found. If no match is found, the connection
    // is closed. A route with no criteria is valid and always produces a
    // match.
    // [#next-free-field: 6]
    message TCPRoute {
      // The cluster to connect to when a the downstream network connection
      // matches the specified criteria.
      string cluster = 1 [(validate.rules).string = {min_bytes: 1}];

      // An optional list of IP address subnets in the form
      // “ip_address/xx”. The criteria is satisfied if the destination IP
      // address of the downstream connection is contained in at least one of
      // the specified subnets. If the parameter is not specified or the list
      // is empty, the destination IP address is ignored. The destination IP
      // address of the downstream connection might be different from the
      // addresses on which the proxy is listening if the connection has been
      // redirected.
      repeated api.v2.core.CidrRange destination_ip_list = 2;

      // An optional string containing a comma-separated list of port numbers
      // or ranges. The criteria is satisfied if the destination port of the
      // downstream connection is contained in at least one of the specified
      // ranges. If the parameter is not specified, the destination port is
      // ignored. The destination port address of the downstream connection
      // might be different from the port on which the proxy is listening if
      // the connection has been redirected.
      string destination_ports = 3;

      // An optional list of IP address subnets in the form
      // “ip_address/xx”. The criteria is satisfied if the source IP address
      // of the downstream connection is contained in at least one of the
      // specified subnets. If the parameter is not specified or the list is
      // empty, the source IP address is ignored.
      repeated api.v2.core.CidrRange source_ip_list = 4;

      // An optional string containing a comma-separated list of port numbers
      // or ranges. The criteria is satisfied if the source port of the
      // downstream connection is contained in at least one of the specified
      // ranges. If the parameter is not specified, the source port is
      // ignored.
      string source_ports = 5;
    }

    // The route table for the filter. All filter instances must have a route
    // table, even if it is empty.
    repeated TCPRoute routes = 1 [(validate.rules).repeated = {min_items: 1}];
  }

  // Allows for specification of multiple upstream clusters along with weights
  // that indicate the percentage of traffic to be forwarded to each cluster.
  // The router selects an upstream cluster based on these weights.
  message WeightedCluster {
    message ClusterWeight {
      // Name of the upstream cluster.
      string name = 1 [(validate.rules).string = {min_bytes: 1}];

      // When a request matches the route, the choice of an upstream cluster is
      // determined by its weight. The sum of weights across all entries in the
      // clusters array determines the total weight.
      uint32 weight = 2 [(validate.rules).uint32 = {gte: 1}];

      // Optional endpoint metadata match criteria used by the subset load balancer. Only endpoints
      // in the upstream cluster with metadata matching what is set in this field will be considered
      // for load balancing. Note that this will be merged with what's provided in
      // :ref:`TcpProxy.metadata_match
      // <envoy_api_field_config.filter.network.tcp_proxy.v2.TcpProxy.metadata_match>`, with values
      // here taking precedence. The filter name should be specified as *envoy.lb*.
      api.v2.core.Metadata metadata_match = 3;
    }

    // Specifies one or more upstream clusters associated with the route.
    repeated ClusterWeight clusters = 1 [(validate.rules).repeated = {min_items: 1}];
  }

  // Configuration for tunneling TCP over other transports or application layers.
  // Currently, only HTTP/2 is supported. When other options exist, HTTP/2 will
  // remain the default.
  message TunnelingConfig {
    // The hostname to send in the synthesized CONNECT headers to the upstream proxy.
    string hostname = 1 [(validate.rules).string = {min_bytes: 1}];
  }

  // The prefix to use when emitting :ref:`statistics
  // <config_network_filters_tcp_proxy_stats>`.
  string stat_prefix = 1 [(validate.rules).string = {min_bytes: 1}];

  oneof cluster_specifier {
    option (validate.required) = true;

    // The upstream cluster to connect to.
    string cluster = 2;

    // Multiple upstream clusters can be specified for a given route. The
    // request is routed to one of the upstream clusters based on weights
    // assigned to each cluster.
    WeightedCluster weighted_clusters = 10;
  }

  // Optional endpoint metadata match criteria. Only endpoints in the upstream
  // cluster with metadata matching that set in metadata_match will be
  // considered. The filter name should be specified as *envoy.lb*.
  api.v2.core.Metadata metadata_match = 9;

  // The idle timeout for connections managed by the TCP proxy filter. The idle timeout
  // is defined as the period in which there are no bytes sent or received on either
  // the upstream or downstream connection. If not set, the default idle timeout is 1 hour. If set
  // to 0s, the timeout will be disabled.
  //
  // .. warning::
  //   Disabling this timeout has a highly likelihood of yielding connection leaks due to lost TCP
  //   FIN packets, etc.
  google.protobuf.Duration idle_timeout = 8;

  // [#not-implemented-hide:] The idle timeout for connections managed by the TCP proxy
  // filter. The idle timeout is defined as the period in which there is no
  // active traffic. If not set, there is no idle timeout. When the idle timeout
  // is reached the connection will be closed. The distinction between
  // downstream_idle_timeout/upstream_idle_timeout provides a means to set
  // timeout based on the last byte sent on the downstream/upstream connection.
  google.protobuf.Duration downstream_idle_timeout = 3;

  // [#not-implemented-hide:]
  google.protobuf.Duration upstream_idle_timeout = 4;

  // Configuration for :ref:`access logs <arch_overview_access_logs>`
  // emitted by the this tcp_proxy.
  repeated accesslog.v2.AccessLog access_log = 5;

  // [#not-implemented-hide:] Deprecated.
  DeprecatedV1 deprecated_v1 = 6 [deprecated = true];

  // The maximum number of unsuccessful connection attempts that will be made before
  // giving up. If the parameter is not specified, 1 connection attempt will be made.
  google.protobuf.UInt32Value max_connect_attempts = 7 [(validate.rules).uint32 = {gte: 1}];

  // Optional configuration for TCP proxy hash policy. If hash_policy is not set, the hash-based
  // load balancing algorithms will select a host randomly. Currently the number of hash policies is
  // limited to 1.
  repeated type.HashPolicy hash_policy = 11 [(validate.rules).repeated = {max_items: 1}];

  // [#not-implemented-hide:] feature in progress
  // If set, this configures tunneling, e.g. configuration options to tunnel multiple TCP
  // payloads over a shared HTTP/2 tunnel. If this message is absent, the payload
  // will be proxied upstream as per usual.
  TunnelingConfig tunneling_config = 12;
}
