Last updated: 2026-05-15
Envoy TLS Configuration
Envoy handles TLS in two directions: downstream (terminating TLS from clients, configured on listeners) and upstream (originating TLS to backends, configured on clusters). Both use a common_tls_context block with the same structure; only the wrapper type differs.
Envoy's config is Protobuf-defined; the YAML below is the standard static file format.
Downstream TLS (Listener)
To terminate TLS on a listener, add a transport_socket with DownstreamTlsContext:
static_resources:
listeners:
- name: listener_https
address:
socket_address:
address: 0.0.0.0
port_value: 443
filter_chains:
- transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
require_client_certificate: false
common_tls_context:
tls_params:
tls_minimum_protocol_version: TLSv1_2
tls_maximum_protocol_version: TLSv1_3
cipher_suites:
- ECDHE-ECDSA-AES128-GCM-SHA256
- ECDHE-RSA-AES128-GCM-SHA256
- ECDHE-ECDSA-AES256-GCM-SHA384
- ECDHE-RSA-AES256-GCM-SHA384
- ECDHE-ECDSA-CHACHA20-POLY1305
- ECDHE-RSA-CHACHA20-POLY1305
tls_certificates:
- certificate_chain:
filename: /etc/envoy/ssl/server.crt
private_key:
filename: /etc/envoy/ssl/server.key
validation_context:
trusted_ca:
filename: /etc/envoy/ssl/ca.crt
Setting require_client_certificate: true enables mutual TLS: clients must present a certificate signed by trusted_ca.
cipher_suites applies only to TLS 1.2. TLS 1.3 ciphers are fixed by BoringSSL (AES-256-GCM-SHA384, CHACHA20-POLY1305-SHA256, AES-128-GCM-SHA256) and are not configurable.
Upstream TLS (Cluster)
To originate TLS to a backend, add a transport_socket with UpstreamTlsContext on the cluster. Always configure validation_context; skipping it means Envoy encrypts the connection but doesn't verify the backend's certificate.
clusters:
- name: backend
type: STRICT_DNS
load_assignment:
cluster_name: backend
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: backend.internal
port_value: 8443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
tls_params:
tls_minimum_protocol_version: TLSv1_2
tls_certificates:
- certificate_chain:
filename: /etc/envoy/ssl/client.crt
private_key:
filename: /etc/envoy/ssl/client.key
validation_context:
trusted_ca:
filename: /etc/envoy/ssl/ca.crt
match_typed_subject_alt_names:
- san_type: DNS
matcher:
exact: backend.internal
match_typed_subject_alt_names pins the expected SAN on the backend's certificate. Without it, Envoy verifies the CA chain but not the hostname, equivalent to verify-ca rather than verify-full.
Mutual TLS
For mTLS in both directions, combine the settings:
- Listener:
require_client_certificate: true+validation_contextwith the client CA - Cluster:
tls_certificateswith the client certificate and key +validation_contextfor the server
In service mesh deployments where a single CA (Vault, cert-manager, etc.) issues all certificates, the same certificate pair is often used for both client and server roles on each workload.
See RFC 8446 ยง4.3.2 for the TLS Certificate Request specification, and Wikipedia: Mutual authentication for a general overview.
Security Notes
Envoy uses BoringSSL, Google's fork of OpenSSL, which was created after Heartbleed was patched and has never been vulnerable to it. The cipher suite and protocol configuration in this guide addresses the following known TLS vulnerabilities:
- POODLE (CVE-2014-3566, 2014): SSL 3.0 is not supported in BoringSSL.
- BEAST (CVE-2011-3389, 2011): Mitigated by recommending TLS 1.2 as the minimum; AEAD-only ciphers eliminate the CBC padding oracle.
- CRIME (CVE-2012-4929, 2012): TLS compression is not supported in BoringSSL.
- Lucky13 (2013): AEAD-only cipher list eliminates CBC padding timing side-channels entirely.
- FREAK (CVE-2015-0204, 2015): EXPORT-grade ciphers are not supported in BoringSSL.
- LOGJAM (CVE-2015-4000, 2015): Short-key DHE is excluded; only ECDHE key exchange is recommended.
- Sweet32 (CVE-2016-2183, 2016): 3DES is excluded from the cipher list; deprecated in BoringSSL.
- ROBOT (CVE-2017-13099, 2017): Static RSA key exchange is excluded; only ECDHE is recommended.
- Downgrade attacks: TLS_FALLBACK_SCSV is supported in BoringSSL.
The following are not addressable through TLS configuration alone:
- Heartbleed (CVE-2014-0160, 2014): Not applicable. BoringSSL forked from OpenSSL after Heartbleed was fixed and has never been vulnerable.
- BREACH (CVE-2013-3587, 2013): Exploits HTTP-level response compression. Mitigated at the application or service mesh layer; TLS configuration cannot prevent it.
- DROWN (CVE-2016-0800, 2016): Not applicable. BoringSSL does not support SSLv2.
Verification
The Envoy admin interface shows all loaded certificates:
curl http://localhost:9901/certs
This returns certificate details including SANs and expiry dates. Test the TLS handshake directly:
openssl s_client -connect localhost:443 -CAfile /etc/envoy/ssl/ca.crt