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.