Securing Envoy

Envoy provides a number of features to secure traffic in and out of your network, and between proxies and services within your network.

Transport Layer Security (TLS) can be used to secure all types of HTTP traffic, including WebSockets.

Envoy also has support for transmitting and receiving generic TCP traffic with TLS.

Envoy also offers a number of other HTTP-based protocols for authentication and authorization such as JWT, RBAC and OAuth.

Warning

The following guide takes you through individual aspects of securing traffic.

To secure traffic over a network that is untrusted, you are strongly advised to make use of encryption and mutual authentication wherever you control both sides of the connection or where relevant protocols are available.

Here we provide a guide to using mTLS which provides both encryption and mutual authentication.

When using TLS, you are strongly encouraged to validate all certificates wherever possible.

It is your responsibility to ensure the integrity of your certificate chain, and outside the scope of this guide.

Upstream and downstream TLS contexts

Machines connecting to Envoy to proxy traffic are “downstream” in relation to Envoy.

Specifying a TLS context that clients can connect to is achieved by setting the DownstreamTLSContext in the transport_socket of a listener.

You will also need to provide valid certificates.

 1static_resources:
 2
 3  listeners:
 4  - name: listener_0
 5    address:
 6      socket_address:
 7        address: 0.0.0.0
 8        port_value: 10000
 9    filter_chains:
10    - filters:
11      - name: envoy.filters.network.http_connection_manager
12        typed_config:
13          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
14          stat_prefix: ingress_http
15          http_filters:
16          - name: envoy.filters.http.router
17          route_config:
18            name: local_route
19            virtual_hosts:
20            - name: local_service
21              domains: ["*"]
22              routes:
23              - match:
24                  prefix: "/"
25                route:
26                  host_rewrite_literal: www.envoyproxy.io
27                  cluster: service_envoyproxy_io
28      transport_socket:
29        name: envoy.transport_sockets.tls
30        typed_config:
31          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
32          common_tls_context:
33            tls_certificates:
34            - certificate_chain:
35                filename: certs/servercert.pem
36              private_key:
37                filename: certs/serverkey.pem

Connecting to an “upstream” TLS service is conversely done by adding an UpstreamTLSContext to the transport_socket of a cluster.

39  clusters:
40  - name: service_envoyproxy_io
41    type: LOGICAL_DNS
42    # Comment out the following line to test on v6 networks
43    dns_lookup_family: V4_ONLY
44    load_assignment:
45      cluster_name: service_envoyproxy_io
46      endpoints:
47      - lb_endpoints:
48        - endpoint:
49            address:
50              socket_address:
51                address: www.envoyproxy.io
52                port_value: 443
53    transport_socket:
54      name: envoy.transport_sockets.tls
55      typed_config:
56        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext

Validate an endpoint’s certificates when connecting

When Envoy connects to an upstream TLS service, it does not, by default, validate the certificates that it is presented with.

You can use the validation_context to specify how Envoy should validate these certificates.

Firstly, you can ensure that the certificates are from a mutually trusted certificate authority:

42                port_value: 443
43    transport_socket:
44      name: envoy.transport_sockets.tls
45      typed_config:
46        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
47        common_tls_context:
48          validation_context:
49            trusted_ca:
50              filename: certs/cacert.pem
51            match_typed_subject_alt_names:
52            - san_type: DNS

You can also ensure that the “Subject Alternative Names” for the cerficate match.

This is commonly used by web certificates (X.509) to identify the domain or domains that a certificate is valid for.

42                port_value: 443
43    transport_socket:
44      name: envoy.transport_sockets.tls
45      typed_config:
46        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
47        common_tls_context:
48          validation_context:
49            trusted_ca:
50              filename: certs/cacert.pem
51            match_typed_subject_alt_names:
52            - san_type: DNS

Note

If the “Subject Alternative Names” for a certificate are for a wildcard domain, eg *.example.com, this is what you should use when matching with match_typed_subject_alt_names.

Note

See here to view all of the possible configurations for certificate validation.

Use mutual TLS (mTLS) to enforce client certificate authentication

With mutual TLS (mTLS), Envoy also provides a way to authenticate connecting clients.

At a minimum you will need to set require_client_certificate and specify a mutually trusted certificate authority:

27                  cluster: service_envoyproxy_io
28      transport_socket:
29        name: envoy.transport_sockets.tls
30        typed_config:
31          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
32          require_client_certificate: true
33          common_tls_context:
34            validation_context:
35              trusted_ca:
36                filename: certs/cacert.pem
37              match_typed_subject_alt_names:
38              - san_type: DNS
39                matcher:
40                  exact: proxy-postgres-frontend.example.com
41            tls_certificates:

You can further restrict the authentication of connecting clients by specifying the allowed “Subject Alternative Names” in match_typed_subject_alt_names, similar to validating upstream certificates described above.

27                  cluster: service_envoyproxy_io
28      transport_socket:
29        name: envoy.transport_sockets.tls
30        typed_config:
31          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
32          require_client_certificate: true
33          common_tls_context:
34            validation_context:
35              trusted_ca:
36                filename: certs/cacert.pem
37              match_typed_subject_alt_names:
38              - san_type: DNS
39                matcher:
40                  exact: proxy-postgres-frontend.example.com
41            tls_certificates:

Note

See here to view all of the possible configurations for certificate validation.

Use mutual TLS (mTLS) to connect with client certificates

When connecting to an upstream with client certificates you can set them as follows:

46  clusters:
47  - name: service_envoyproxy_io
48    type: LOGICAL_DNS
49    # Comment out the following line to test on v6 networks
50    dns_lookup_family: V4_ONLY
51    load_assignment:
52      cluster_name: service_envoyproxy_io
53      endpoints:
54      - lb_endpoints:
55        - endpoint:
56            address:
57              socket_address:
58                address: www.envoyproxy.io
59                port_value: 443
60    transport_socket:
61      name: envoy.transport_sockets.tls
62      typed_config:
63        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
64        common_tls_context:
65          tls_certificates:
66          - certificate_chain:
67              filename: certs/clientcert.pem
68            private_key:
69              filename: certs/clientkey.pem

Provide multiple TLS domains at the same IP address with SNI

SNI is an extension to the TLS protocol which allows multiple domains served from the same IP address to be secured with TLS.

To secure specific domains on a listening connection with SNI, you should set the filter_chain_match of the listener:

27                  cluster: service_envoyproxy_io
28      filter_chain_match:
29        server_names:
30        - my-service-name.example.com
31      transport_socket:
32        name: envoy.transport_sockets.tls
33        typed_config:
34          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
35          common_tls_context:

See here for more info about creating multiple endpoints with SNI

Connect to an endpoint with SNI

When connecting to a TLS endpoint that uses SNI you should set sni in the configuration of the UpstreamTLSContext.

This will usually be the DNS name of the service you are connecting to.

55                port_value: 443
56    transport_socket:
57      name: envoy.transport_sockets.tls
58      typed_config:
59        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
60        sni: www.envoyproxy.io

When connecting to an Envoy endpoint that is protected by SNI, this must match one of the server_names set in the endpoint’s filter_chain_match, as described above.