TCP Proxy (proto)

This extension has the qualified name envoy.filters.network.tcp_proxy

Note

This extension is intended to be robust against untrusted downstream traffic. It assumes that the upstream is trusted.

Tip

This extension extends and can be used with the following extension category:

This extension must be configured with one of the following type URLs:

TCP Proxy configuration overview.

extensions.filters.network.tcp_proxy.v3.TcpProxy

[extensions.filters.network.tcp_proxy.v3.TcpProxy proto]

{
  "stat_prefix": ...,
  "cluster": ...,
  "weighted_clusters": {...},
  "on_demand": {...},
  "metadata_match": {...},
  "idle_timeout": {...},
  "access_log": [],
  "max_connect_attempts": {...},
  "backoff_options": {...},
  "hash_policy": [],
  "tunneling_config": {...},
  "max_downstream_connection_duration": {...},
  "max_downstream_connection_duration_jitter_percentage": {...},
  "access_log_flush_interval": {...},
  "flush_access_log_on_connected": ...,
  "access_log_options": {...},
  "proxy_protocol_tlvs": [],
  "proxy_protocol_tlv_merge_policy": ...,
  "upstream_connect_mode": ...,
  "max_early_data_bytes": {...},
  "check_drain_close": {...}
}
stat_prefix

(string, REQUIRED) The prefix to use when emitting statistics.

cluster

(string) The upstream cluster to connect to.

Precisely one of cluster, weighted_clusters must be set.

weighted_clusters

(extensions.filters.network.tcp_proxy.v3.TcpProxy.WeightedCluster) Multiple upstream clusters can be specified. The request is routed to one of the upstream clusters based on the weights assigned to each cluster.

Precisely one of cluster, weighted_clusters must be set.

on_demand

(extensions.filters.network.tcp_proxy.v3.TcpProxy.OnDemand) The on demand policy for the upstream cluster. It applies to both TcpProxy.cluster and TcpProxy.weighted_clusters.

metadata_match

(config.core.v3.Metadata) 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. The filter name should be specified as envoy.lb.

idle_timeout

(Duration) 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 is disabled. It is possible to dynamically override this configuration by setting a per-connection filter state object for the key envoy.tcp_proxy.per_connection_idle_timeout_ms.

Warning

Disabling this timeout is likely to yield connection leaks due to lost TCP FIN packets, etc.

access_log

(repeated config.accesslog.v3.AccessLog) Configuration for access logs emitted by this TCP proxy.

max_connect_attempts

(UInt32Value) 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.

backoff_options

(config.core.v3.BackoffStrategy) Sets the backoff strategy. If not set, the retries are performed without backoff.

hash_policy

(repeated type.v3.HashPolicy) 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.

tunneling_config

(extensions.filters.network.tcp_proxy.v3.TcpProxy.TunnelingConfig) If set, this configures tunneling, for example configuration options to tunnel TCP payload over HTTP CONNECT. If this message is absent, the payload is proxied upstream as usual. It is possible to dynamically override this configuration and disable tunneling per connection by setting a per-connection filter state object for the key envoy.tcp_proxy.disable_tunneling.

max_downstream_connection_duration

(Duration) The maximum duration of a connection. The duration is defined as the period since a connection was established. If not set, there is no maximum duration. When max_downstream_connection_duration is reached, the connection is closed. The duration must be at least 1ms.

max_downstream_connection_duration_jitter_percentage

(type.v3.Percent) Percentage-based jitter for max_downstream_connection_duration. The jitter increases the max_downstream_connection_duration by a random duration up to the provided percentage. This field is ignored if max_downstream_connection_duration is not set. If not set, no jitter is added.

access_log_flush_interval

(Duration) If both this field and access_log_flush_interval are specified, the former (deprecated field) is ignored.

Attention

This field is deprecated in favor of access_log_flush_interval.

flush_access_log_on_connected

(bool) If both this field and flush_access_log_on_connected are specified, the former (deprecated field) is ignored.

Attention

This field is deprecated in favor of flush_access_log_on_connected.

access_log_options

(extensions.filters.network.tcp_proxy.v3.TcpProxy.TcpAccessLogOptions) Additional access log options for the TCP proxy.

proxy_protocol_tlvs

(repeated config.core.v3.TlvEntry) TLVs to add to the PROXY protocol header sent upstream. Behavior when PROXY protocol state already exists (e.g., downstream TLVs from proxy_protocol listener filter) is controlled by proxy_protocol_tlv_merge_policy.

Note

To ensure the TLVs are allowed upstream, configure passthrough TLVs on the upstream proxy protocol transport. See core.v3.ProxyProtocolConfig.pass_through_tlvs for details.

proxy_protocol_tlv_merge_policy

(extensions.filters.network.tcp_proxy.v3.ProxyProtocolTlvMergePolicy) Specifies how TLVs in proxy_protocol_tlvs are merged with existing PROXY protocol state (e.g., downstream TLVs from the proxy_protocol listener filter). See ProxyProtocolTlvMergePolicy.

upstream_connect_mode

(extensions.filters.network.tcp_proxy.v3.UpstreamConnectMode) Specifies when to establish the upstream connection.

When not specified, defaults to IMMEDIATE for backward compatibility.

Attention

Server-first protocols (e.g., SMTP, MySQL, POP3) require IMMEDIATE mode.

max_early_data_bytes

(UInt32Value) Maximum bytes of early data to buffer from the downstream connection before the upstream connection is established.

If not set, the TCP proxy will read-disable the downstream connection until the upstream connection is established (legacy behavior).

If set, enables receive_before_connect mode where the filter allows the filter chain to read downstream data before the upstream connection exists. The data is buffered and forwarded once the upstream connection is ready. When the buffer exceeds this limit, the downstream connection is read-disabled to prevent excessive memory usage.

This field is required when upstream_connect_mode is not IMMEDIATE.

Note

Use this carefully with server-first protocols. The upstream may send data before receiving anything from downstream, which could fill the early data buffer.

check_drain_close

(BoolValue) If set to true, the TCP proxy checks if the downstream connection was marked as drained after each read or write. When drain close is requested for the listener’s traffic direction, the downstream connection is closed with FlushWrite.

This is disabled by default for backward compatibility.

extensions.filters.network.tcp_proxy.v3.TcpProxy.WeightedCluster

[extensions.filters.network.tcp_proxy.v3.TcpProxy.WeightedCluster proto]

Allows specification of multiple upstream clusters along with weights indicating the percentage of traffic forwarded to each cluster. The cluster selection is based on these weights.

{
  "clusters": []
}
clusters

(repeated extensions.filters.network.tcp_proxy.v3.TcpProxy.WeightedCluster.ClusterWeight, REQUIRED) Specifies the upstream clusters associated with this configuration.

extensions.filters.network.tcp_proxy.v3.TcpProxy.WeightedCluster.ClusterWeight

[extensions.filters.network.tcp_proxy.v3.TcpProxy.WeightedCluster.ClusterWeight proto]

{
  "name": ...,
  "weight": ...,
  "metadata_match": {...}
}
name

(string, REQUIRED) Name of the upstream cluster.

weight

(uint32) 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.

metadata_match

(config.core.v3.Metadata) 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 TcpProxy.metadata_match, with values here taking precedence. The filter name should be specified as envoy.lb.

extensions.filters.network.tcp_proxy.v3.TcpProxy.TunnelingConfig

[extensions.filters.network.tcp_proxy.v3.TcpProxy.TunnelingConfig proto]

Configuration for tunneling TCP over other transports or application layers. Tunneling is supported over HTTP/1.1 and HTTP/2. The upstream protocol is determined by the cluster configuration.

{
  "hostname": ...,
  "use_post": ...,
  "headers_to_add": [],
  "propagate_response_headers": ...,
  "post_path": ...,
  "propagate_response_trailers": ...,
  "request_id_extension": {...},
  "request_id_header": ...,
  "request_id_metadata_key": ...,
  "formatters": []
}
hostname

(string, REQUIRED) The hostname to send in the synthesized CONNECT headers to the upstream proxy. This field evaluates command operators if present; otherwise, the value is used as-is.

For example, dynamically set the hostname using downstream SNI:

tunneling_config:
  hostname: "%REQUESTED_SERVER_NAME%:443"

For example, dynamically set the hostname using dynamic metadata:

tunneling_config:
  hostname: "%DYNAMIC_METADATA(tunnel:address)%"
use_post

(bool) Use the POST method instead of the CONNECT method to tunnel the TCP stream. The protocol: bytestream header is not set for HTTP/2 to comply with the specification.

The upstream proxy is expected to interpret the POST payload as raw TCP.

headers_to_add

(repeated config.core.v3.HeaderValueOption) Additional request headers to send to the upstream proxy. This is mainly used to trigger the upstream to convert POST requests back to CONNECT requests.

Neither :-prefixed pseudo-headers like :path nor the host header can be overridden.

propagate_response_headers

(bool) Save response headers to the downstream connection’s filter state for consumption by network filters. The filter state key is envoy.tcp_proxy.propagate_response_headers.

post_path

(string) The path used with the POST method. The default path is /. If this field is specified and use_post field is not set to true, the configuration will be rejected.

propagate_response_trailers

(bool) Save response trailers to the downstream connection’s filter state for consumption by network filters. The filter state key is envoy.tcp_proxy.propagate_response_trailers.

request_id_extension

(extensions.filters.network.http_connection_manager.v3.RequestIDExtension) The configuration of the request ID extension used for generation, validation, and associated tracing operations when tunneling.

If this field is set, a request ID is generated using the specified extension. If this field is not set, no request ID is generated.

When a request ID is generated, it is also stored in the downstream connection’s dynamic metadata under the namespace envoy.filters.network.tcp_proxy with the key tunnel_request_id to allow emission from TCP proxy access logs via the %DYNAMIC_METADATA(envoy.filters.network.tcp_proxy:tunnel_request_id)% formatter.

Tip

This extension category has the following known extensions:

request_id_header

(string) The request header name to use for emitting the generated request ID on the tunneling HTTP request.

If not specified or set to an empty string, the default header name x-request-id is used.

Note

This setting does not alter the internal request ID handling elsewhere in Envoy and only controls the header emitted on the tunneling request.

request_id_metadata_key

(string) The dynamic metadata key to use when storing the generated request ID. The metadata is stored under the namespace envoy.filters.network.tcp_proxy.

If not specified or set to an empty string, the default key tunnel_request_id is used. This enables customizing the key used by access log formatters such as %DYNAMIC_METADATA(envoy.filters.network.tcp_proxy:<key>)%.

formatters

(repeated config.core.v3.TypedExtensionConfig) Specifies a collection of Formatter plugins that can be used in substitution formatters in headers_to_add. See the formatters extensions documentation for details.

extensions.filters.network.tcp_proxy.v3.TcpProxy.OnDemand

[extensions.filters.network.tcp_proxy.v3.TcpProxy.OnDemand proto]

{
  "odcds_config": {...}
}
odcds_config

(config.core.v3.ConfigSource) Optional configuration for the on-demand cluster discovery service. If not specified, on-demand cluster discovery is disabled. When specified, the filter pauses a request to an unknown cluster and begins a cluster discovery process. When discovery completes (successfully or not), the request is resumed.

extensions.filters.network.tcp_proxy.v3.TcpProxy.TcpAccessLogOptions

[extensions.filters.network.tcp_proxy.v3.TcpProxy.TcpAccessLogOptions proto]

{
  "access_log_flush_interval": {...},
  "flush_access_log_on_connected": ...,
  "flush_access_log_on_start": ...
}
access_log_flush_interval

(Duration) The interval for flushing access logs. By default, the TCP proxy flushes a single access log when the connection is closed. If this field is set, the TCP proxy flushes access logs periodically at the specified interval. The interval must be at least 1ms.

flush_access_log_on_connected

(bool) If set to true, the access log is flushed when the TCP proxy successfully establishes a connection with the upstream. If the connection fails, the access log is not flushed.

flush_access_log_on_start

(bool) If set to true, the access log is flushed when the TCP proxy accepts a connection.

Enum extensions.filters.network.tcp_proxy.v3.UpstreamConnectMode

[extensions.filters.network.tcp_proxy.v3.UpstreamConnectMode proto]

Specifies when the TCP proxy establishes the upstream connection.

IMMEDIATE

(DEFAULT) ⁣Establish the upstream connection immediately when the downstream connection is accepted. This is the default behavior and provides the lowest latency.

ON_DOWNSTREAM_DATA

⁣Wait for initial data from the downstream connection before establishing the upstream connection. This allows preceding filters to inspect the initial data (e.g., extracting SNI from TLS ClientHello) before the upstream connection is established.

This mode requires max_early_data_bytes to be set.

Warning

This mode is not suitable for server-first protocols (e.g., SMTP, MySQL, POP3) where the server sends the initial greeting. For such protocols, use IMMEDIATE mode.

ON_DOWNSTREAM_TLS_HANDSHAKE

⁣Wait for the downstream TLS handshake to complete before establishing the upstream connection. This allows access to the full TLS connection information, including client certificates and negotiated parameters, which can be used for routing decisions or passed as metadata to the upstream.

This mode requires max_early_data_bytes to be set (can be zero to disable buffering).

Note

This mode is only effective when the downstream connection uses TLS. For non-TLS connections, it behaves the same as IMMEDIATE.

Enum extensions.filters.network.tcp_proxy.v3.ProxyProtocolTlvMergePolicy

[extensions.filters.network.tcp_proxy.v3.ProxyProtocolTlvMergePolicy proto]

Specifies how TLVs in proxy_protocol_tlvs are merged with existing PROXY protocol state (e.g., downstream TLVs parsed by the proxy_protocol listener filter).

ADD_IF_ABSENT

(DEFAULT) ⁣Add configured TLVs only if no PROXY protocol state exists (e.g., no downstream TLVs). If state exists, ignore configured TLVs and use only the existing TLVs. This is the default for backward compatibility.

OVERWRITE_BY_TYPE_IF_EXISTS_OR_ADD

⁣Overwrite existing TLVs (e.g., downstream TLVs) by type with configured TLVs. Non-conflicting TLVs from both sources are preserved. If no state exists, add all configured TLVs. Source/destination addresses from existing state are preserved.

APPEND_IF_EXISTS_OR_ADD

⁣Append configured TLVs to existing TLVs (e.g., downstream TLVs), preserving all TLVs from both sources (PROXY protocol v2 allows duplicate types). If no state exists, add all configured TLVs. Source/destination addresses from existing state are preserved.