Mastering Envoy TLS & mTLS: Step-by-Step Configuration for Secure Service Mesh
This guide explains why TLS and mTLS are essential for modern microservice communication, then walks through configuring Envoy for both simple TLS termination and full mutual TLS, covering listeners, clusters, certificate management, and provides runnable examples with verification commands.
Why TLS and mTLS?
TLS encrypts client‑server communication, preventing man‑in‑the‑middle attacks.
mTLS builds on TLS by requiring both parties to present and verify certificates, enabling mutual authentication for service‑to‑service traffic.
In a Zero‑Trust architecture, mTLS is a key mechanism to enforce “never trust, always verify”.
Envoy terminating TLS
For HTTP services, a simple TLS termination can be configured in Envoy.
$ curl 172.139.20.170:8090/header
{
"Accept": "*/*",
"User-Agent": "curl/7.29.0"
}Configuration (YAML):
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: simple_cluster
# Simple TLS configuration (8 lines)
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain: { filename: "/certs/server.crt" }
private_key: { filename: "/certs/server.key" }
clusters:
- name: simple_cluster
lb_policy: ROUND_ROBIN
type: STATIC
load_assignment:
cluster_name: simple_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 172.139.20.170, port_value: 8090 }Verification:
$ curl -k https://172.139.20.170:10000/header
{
"Accept": "*/*",
"User-Agent": "curl/7.29.0",
"X-Envoy-Expected-Rq-Timeout-Ms": "15000",
"X-Envoy-External-Address": "172.139.20.170",
"X-Forwarded-For": "172.139.20.170",
"X-Forwarded-Proto": "https",
"X-Request-Id": "f72c4dda-4cca-4d94-be59-138f219a00d2"
}Envoy terminating mTLS
For HTTP services that require mutual authentication, configure Envoy with client certificate verification.
Configuration (YAML):
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: simple_cluster
# Mutual TLS configuration (11 lines)
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
require_client_certificate: true
common_tls_context:
tls_certificates:
- certificate_chain: { filename: "/certs/server.crt" }
private_key: { filename: "/certs/server.key" }
validation_context:
trusted_ca: { filename: "/certs/ca.crt" }
clusters:
- name: simple_cluster
lb_policy: ROUND_ROBIN
type: STATIC
load_assignment:
cluster_name: simple_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 172.139.20.170, port_value: 8090 }
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain: { filename: "/certs/client.crt" }
private_key: { filename: "/certs/client.key" }
validation_context:
trusted_ca: { filename: "/certs/ca.crt" }Verification of service‑to‑service mTLS:
$ curl --cacert certs/ca.crt --cert ./certs/client.crt --key ./certs/client.key https://172.139.20.170:10000/header
{
"Accept": "*/*",
"User-Agent": "curl/7.29.0",
"X-Envoy-Expected-Rq-Timeout-Ms": "15000",
"X-Envoy-External-Address": "172.139.20.170",
"X-Forwarded-For": "172.139.20.170",
"X-Forwarded-Proto": "https",
"X-Request-Id": "796354e9-28e8-4a7e-855f-71fe31494368"
}Additional verification against the backend service:
$ curl --cacert certs/ca.crt --cert ./certs/client.crt --key ./certs/client.key https://172.139.20.170:8090/header
{
"Accept": "*/*",
"User-Agent": "curl/7.29.0"
}Conclusion
TLS and mTLS have become standard for modern service communication. For operators, mastering Envoy’s TLS configuration is essential for securing cloud‑native architectures, and by configuring DownstreamTlsContext and UpstreamTlsContext correctly, one can implement anything from simple HTTPS termination to full‑link mutual TLS.
Linux Ops Smart Journey
The operations journey never stops—pursuing excellence endlessly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
