The tcp_proxy network filter forwards a connection's bytes to an upstream cluster without interpreting them. Use it for anything that is not HTTP — databases, message brokers, plain TLS passthrough — or when you want L4 forwarding with none of the HTTP machinery.
Enable it
tcp_proxy is the terminal filter of a filter chain, in place of the HTTP connection manager:
listeners:
- name: listener_tcp
address:
socket_address: { address: 0.0.0.0, port_value: 8081 }
filter_chains:
- name: tcp_chain
filters:
- name: tcp
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
cluster: backend
The filter takes a cluster and, optionally, access logs. Everything about the upstream side — endpoints, load balancing, health checks, upstream TLS — comes from the cluster.
Weighted clusters
Split connections across clusters by weight instead of naming one:
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
weighted_clusters:
clusters:
- name: backend-v1
weight: 90
- name: backend-v2
weight: 10
Each entry carries only name and weight; the split is per connection, not per request.
Route by SNI
Because filter chain selection happens before any filter runs, a listener with the TLS inspector can steer TLS connections to different clusters by SNI — without terminating TLS. Each chain omits a transport_socket, so the encrypted stream passes through untouched:
listeners:
- name: listener_tls_passthrough
address:
socket_address: { address: 0.0.0.0, port_value: 8443 }
listener_filters:
- name: envoy.filters.listener.tls_inspector
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
enable_ja3_fingerprinting: false
filter_chains:
- name: api_chain
filter_chain_match:
server_names: [api.example.com]
filters:
- name: tcp
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
cluster: api
- name: default_chain
filters:
- name: tcp
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
cluster: backend
Add a transport_socket to a chain to terminate TLS at Arion instead, and combine tcp_proxy with the RBAC, connection limit, or global rate limit network filters ahead of it. The Route TCP at L4 guide builds a complete L4 front end; its production notes cover the SNI split.
TCP or HTTP?
Reach for tcp_proxy when Arion should not parse the stream: non-HTTP protocols, end-to-end TLS where the backend must see the client hello, or minimum-overhead port forwarding. Use the HTTP connection manager whenever you need per-request behaviour — routing by path or header, retries, HTTP filters, per-request logs.
Verify
With an echo server as the upstream:
printf 'ping\n' | nc -q1 127.0.0.1 8081pingLimits
- One
clusterorweighted_clustersper filter; the choice is fixed per chain. - Idle and connection-duration timeouts on the filter are not supported — bound connections with the cluster's settings and the connection limit filter.
- CONNECT tunneling (
tunneling_config),max_connect_attempts, and hash-based endpoint selection are not supported and are refused at startup. - Per-entry
metadata_matchon weighted clusters is not supported.
The field table is in the TCP proxy reference.