Infrastructure Security

Envoy Proxy Security Hardening for Production Deployments

Envoy powers service meshes and API gateways across the industry. Its default configuration prioritizes connectivity over security. Here is how to fix that.

Bob
Cloud Security Architect
4 min read

Envoy proxy has become the data plane of choice for modern infrastructure. It powers Istio, AWS App Mesh, and numerous custom API gateways. Its extensibility is its strength, but it also means the default configuration leaves significant security decisions to the operator.

A freshly deployed Envoy accepts all traffic, has no authentication requirements, and logs minimally. Turning this into a production-ready security boundary requires deliberate configuration.

TLS Configuration

Enforce TLS Everywhere

Envoy should terminate TLS for all external-facing listeners and originate TLS for all upstream connections. Configure downstream TLS in your listener definition:

listeners:
  - name: https_listener
    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
            common_tls_context:
              tls_params:
                tls_minimum_protocol_version: TLSv1_2
                cipher_suites:
                  - ECDHE-ECDSA-AES128-GCM-SHA256
                  - ECDHE-RSA-AES128-GCM-SHA256
              tls_certificates:
                - certificate_chain:
                    filename: /etc/envoy/certs/server.crt
                  private_key:
                    filename: /etc/envoy/certs/server.key

Certificate Rotation With SDS

Use the Secret Discovery Service (SDS) instead of file-based certificates. SDS allows certificate rotation without restarting Envoy. This is critical for production environments where certificate rotation should not cause downtime.

Client Certificate Validation

For service-to-service communication, enable mutual TLS:

require_client_certificate: true
validation_context:
  trusted_ca:
    filename: /etc/envoy/certs/ca.crt

This ensures that only clients presenting certificates signed by your CA can connect. Combined with RBAC policies, this provides strong service identity verification.

Access Control

RBAC Filter

Envoy's RBAC (Role-Based Access Control) filter is the primary mechanism for controlling access to routes and endpoints. Configure it to allow or deny requests based on client identity, source IP, request headers, and URL paths.

http_filters:
  - name: envoy.filters.http.rbac
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC
      rules:
        action: ALLOW
        policies:
          admin-api:
            permissions:
              - url_path:
                  path:
                    prefix: /admin
            principals:
              - authenticated:
                  principal_name:
                    exact: spiffe://cluster/ns/admin/sa/admin-service

External Authorization

For complex authorization decisions, use Envoy's ext_authz filter to delegate to an external authorization service. This keeps authorization logic out of Envoy configuration and in a purpose-built service that can evaluate policies against user attributes, resource ownership, and other contextual factors.

Rate Limiting

Local Rate Limiting

Envoy's local rate limit filter enforces limits per Envoy instance. This is simpler to configure but does not coordinate across multiple Envoy instances:

http_filters:
  - name: envoy.filters.http.local_ratelimit
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
      stat_prefix: http_local_rate_limiter
      token_bucket:
        max_tokens: 100
        tokens_per_fill: 100
        fill_interval: 60s

Global Rate Limiting

For coordinated rate limiting across a fleet of Envoy instances, use the global rate limit service. Envoy sends rate limit check requests to a centralized service that tracks counters in Redis.

This is more complex to deploy but essential for preventing abuse in scaled environments where any single Envoy instance sees only a fraction of total traffic.

Request Validation

Header Size Limits

Limit maximum header sizes to prevent header-based denial-of-service:

http_connection_manager:
  max_request_headers_kb: 32

Connection Limits

Restrict the number of concurrent connections per listener to prevent resource exhaustion:

per_connection_buffer_limit_bytes: 32768
listener_filters_timeout: 15s

Circuit Breaking

Configure circuit breakers on upstream clusters to prevent cascading failures when a backend becomes unhealthy:

circuit_breakers:
  thresholds:
    - max_connections: 100
      max_pending_requests: 100
      max_requests: 100
      max_retries: 3

Access Logging

Enable Comprehensive Logging

Configure access logs with enough detail for security analysis:

access_log:
  - name: envoy.access_loggers.file
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
      path: /var/log/envoy/access.log
      log_format:
        json_format:
          timestamp: "%START_TIME%"
          method: "%REQ(:METHOD)%"
          path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
          response_code: "%RESPONSE_CODE%"
          client_ip: "%DOWNSTREAM_REMOTE_ADDRESS%"
          user_agent: "%REQ(USER-AGENT)%"
          tls_version: "%DOWNSTREAM_TLS_VERSION%"
          upstream_host: "%UPSTREAM_HOST%"

Forward Logs to SIEM

Stream Envoy access logs to your security information and event management system. Create detection rules for brute force attempts, unusual path patterns, client certificate failures, and unexpected TLS versions.

Admin Interface Security

Envoy's admin interface provides runtime statistics, configuration dumps, and operational controls. It should never be exposed to untrusted networks:

admin:
  address:
    socket_address:
      address: 127.0.0.1
      port_value: 9901

Bind the admin interface to localhost and access it through port forwarding or a bastion host. The admin interface can modify runtime configuration, trigger configuration dumps that may include secrets, and provide detailed internal state information useful to attackers.

How Safeguard.sh Helps

Safeguard.sh tracks the security posture of your Envoy deployments and the services they protect. It scans Envoy container images for vulnerabilities in the proxy binary and its dependencies, monitors for CVEs that affect your specific Envoy version, and provides SBOM generation for your entire service mesh infrastructure. When an Envoy CVE is disclosed, Safeguard.sh identifies every deployment in your environment running the affected version.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.