Understanding Envoy Proxy Security Hardening
Envoy proxy security hardening is the systematic process of reducing the attack surface of an Envoy deployment by tightening configuration, enabling protective filters, and enforcing strict operational defaults. Out of the box, Envoy provides a powerful, flexible data plane, but its default settings prioritize compatibility and ease of use over strict security. Hardening transforms a standard Envoy setup into a hardened ingress/egress gateway that resists common threats such as protocol-level attacks, unauthorized access, credential exposure, and resource exhaustion.
This tutorial covers the core areas you need to lock down: TLS termination and mTLS, administrative interface protection, authorization and rate limiting, network binding, secure logging, filter sandboxing, and request validation. Each section includes practical YAML configuration snippets that you can adapt directly to your own envoy.yaml or dynamic control-plane resources.
Why Security Hardening Matters
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →Envoy often sits at a critical network boundary—as a front proxy for Kubernetes ingress, a service mesh sidecar, or an edge gateway. A weak configuration exposes you to:
- TLS downgrades and protocol smuggling – attackers can force weaker ciphers or exploit HTTP parsing quirks.
- Admin interface takeover – the default admin endpoint can expose full configuration, metrics, and even trigger shutdowns if left open.
- Denial-of-service via resource exhaustion – missing rate limits or circuit breakers allow a single misbehaving client to cascade failure.
- Sensitive data leakage – poorly tuned access logs may print headers, cookies, or metadata into plaintext log sinks.
- Internal service bypass – missing authorization rules let attackers reach services they shouldn’t.
Applying the practices below turns Envoy into a robust, defense-in-depth layer that actively protects your services rather than merely proxying traffic.
How to Implement Security Hardening
1. Enforce Strict TLS and mTLS
Always terminate TLS at the Envoy listener and enforce a minimum TLS version along with strong cipher suites. For east‑west service mesh traffic, use mutual TLS (mTLS) to authenticate both client and server. The following snippet shows a downstream listener that requires TLS 1.2+ and restricts ciphers to modern, secure suites:
static_resources:
listeners:
- name: ingress_listener
address:
socket_address: { address: 0.0.0.0, port_value: 443 }
filter_chains:
- filter_chain_match:
server_names: ["api.example.com"]
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
tls_maximum_protocol_version: TLSv1.3
cipher_suites:
- ECDHE-ECDSA-AES256-GCM-SHA384
- ECDHE-RSA-AES256-GCM-SHA384
- 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"
require_client_certificate: false # set to true for mTLS
filters:
- name: envoy.filters.network.http_connection_manager
...
For upstream connections (Envoy → backend), configure an UpstreamTlsContext similarly, and set require_client_certificate: true on downstream when you want mTLS. In a service mesh, automate certificate rotation via SDS (Secret Discovery Service) instead of static files.
2. Lock Down the Administration Interface
Envoy's admin interface is a powerful HTTP endpoint (default port 9901) that returns configuration dumps, metrics, and even allows runtime changes. It must never be exposed to untrusted networks. Best practices include:
- Bind admin to the loopback address only.
- Require authentication via a static secret header or mutual TLS.
- Disable the admin endpoint entirely if not needed (set
admin: {}empty, but note that this also disables health checks – consider alternative health-check listeners).
admin:
address:
socket_address: { address: 127.0.0.1, port_value: 9901 }
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: "/var/log/envoy_admin.log"
config_overrides:
# Optional: require a static shared secret in X-Admin-Secret header
mutate_config_headers:
- key: X-Admin-Secret
value: "your-long-random-secret"
In production, consider moving admin operations to a separate, authenticated listener that uses mTLS and restrict access via network policies.
3. Apply Network-Level Binding Restrictions
Never bind listeners to 0.0.0.0 unless strictly necessary. Prefer explicit IP addresses or restrict via Linux capabilities and firewall rules. For Kubernetes, use hostPort or containerPort combined with NetworkPolicy.
listener:
address:
socket_address: { address: 192.168.1.10, port_value: 443 }
Additionally, use the bind_to_port option (default true) to require explicit binding. Avoid exposing Envoy on the same port as application pods without TLS.
4. Enable RBAC and Authorization Filters
Envoy’s Role-Based Access Control (RBAC) HTTP filter lets you define fine-grained permissions based on source IP, headers, JWT claims, or mTLS principal. Use it to enforce zero-trust at the proxy layer. The example below allows only requests from the subnet 10.0.0.0/8 with a valid X-Team header:
http_filters:
- name: envoy.filters.http.rbac
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC
rules:
action: ALLOW
policies:
restrict_access:
permissions:
- and_rules:
rules:
- header:
name: X-Team
present_match: true
- header:
name: X-Team
string_match:
exact: "backend"
principals:
- source_ip:
address_prefix: 10.0.0.0
prefix_len: 8
shadow_rules:
action: DENY
policies: {} # log-only denied requests if needed
Combine RBAC with external authorization (ext_authz filter) for JWT validation or OPA policies.
5. Implement Rate Limiting and Circuit Breaking
Protect your backends from abuse by applying rate limits at the listener or route level. Use the envoy.filters.http.rate_limit filter or route-specific rate_limits actions. Circuit breakers on clusters prevent cascading failures.
route_config:
virtual_hosts:
- name: api_services
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: backend_service
rate_limits:
- actions:
- remote_address: {}
...
clusters:
- name: backend_service
connect_timeout: 3s
circuit_breakers:
thresholds:
- priority: DEFAULT
max_connections: 500
max_pending_requests: 100
max_requests: 1000
max_retries: 3
For global rate limiting, deploy a dedicated rate limit service and reference it via the rate_limit_service configuration.
6. Secure Access Logging and Avoid Sensitive Data Leakage
Access logs are invaluable for auditing, but they can accidentally expose headers, cookies, or query parameters. Hardening means carefully selecting log format strings and sanitizing or omitting sensitive fields.
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"
format: |
[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% "%UPSTREAM_HOST%" %DURATION%
# Omit headers like Cookie, Authorization, Set-Cookie by not including them
Use %REQ(header-name)% sparingly. Never log the Authorization header or Cookie in plaintext. Consider using Envoy's sanitization filter (envoy.filters.http.header_sanitization) to strip sensitive headers before logging.
7. Validate Requests and Prevent HTTP Smuggling
Envoy has strong HTTP parsing defaults, but you should still enforce strict validation. Disable HTTP/1.0 if not needed, reject malformed headers, and enable request smuggling detection.
http_connection_manager:
http_protocol_options:
accept_http_10: false
normalize_path: true
merge_slashes: true
strip_any_host_port: true
common_http_protocol_options:
idle_timeout: 60s
headers_with_underscores_action: REJECT_REQUEST
route_config: ...
Set headers_with_underscores_action to REJECT_REQUEST because many backends treat underscores as hyphens, creating injection risks. Enable envoy.filters.http.header_validation to block non-RFC compliant characters.
8. Sandbox Custom Filters (WASM/Lua)
If you extend Envoy with WebAssembly (WASM) or Lua scripts, isolate them in a sandbox with restricted capabilities. Avoid giving Lua scripts access to HTTP callouts unless necessary, and always use the envoy.filters.http.wasm filter with minimal capability sets.
- name: envoy.filters.http.wasm
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
config:
vm_config:
runtime: "envoy.wasm.runtime.v8"
code:
local:
filename: "/etc/envoy/filter.wasm"
sandbox_config:
# Restrict access to network, file system, environment variables
http_callout_config:
enabled: false
capabilities: []
Always review WASM modules for vulnerabilities and keep them updated. Prefer built-in filters over custom code where possible.
Best Practices Summary
- Keep Envoy updated – run the latest stable release to patch known CVEs (Envoy publishes regular security advisories).
- Use minimal configurations – disable protocols and filters you don’t need (e.g., HTTP/1.0, TCP proxy without TLS).
- Run as non-root – in Docker/Kubernetes, drop capabilities and run Envoy with a dedicated user (e.g.,
envoyuser). - Apply network policies – restrict which pods can reach the admin port and which backends Envoy can talk to.
- Monitor and alert – ship admin and access logs to a SIEM, and alert on denied RBAC events or anomalous rate-limit hits.
- Test hardening regularly – use Envoy’s
--mode validateflag and run configuration linting in CI. Conduct penetration tests against your proxy. - Treat configuration as code – version your Envoy YAML/JSON and use dynamic control-plane features (xDS) to deploy changes securely.
Conclusion
Envoy proxy security hardening is not a one-time task—it’s an ongoing discipline that evolves with your architecture and the threat landscape. By enforcing strict TLS, locking down the admin interface, applying authorization and rate limiting, binding to restricted interfaces, sanitizing logs, and validating every request, you transform Envoy from a simple proxy into a formidable security control point. Combine these measures with regular updates, non-root execution, and network segmentation to build a resilient, defense-in-depth ingress and service mesh layer. Start with the most impactful items—TLS and admin protection—and gradually adopt the remaining practices to continuously reduce your exposure.