Cloud Native 9 min read

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.

Linux Ops Smart Journey
Linux Ops Smart Journey
Linux Ops Smart Journey
Mastering Envoy TLS & mTLS: Step-by-Step Configuration for Secure Service Mesh

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.

cloud nativemicroservicesservice meshTLSEnvoymTLS
Linux Ops Smart Journey
Written by

Linux Ops Smart Journey

The operations journey never stops—pursuing excellence endlessly.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.