Configuring Envoy as an edge proxy

Envoy is a production-ready edge proxy, however, the default settings are tailored for the service mesh use case, and some values need to be adjusted when using Envoy as an edge proxy.

TCP proxies should configure:

HTTP proxies should additionally configure:

If Envoy is configured with RBAC filter or makes route selection based on URL path it is recommended to enable the following path normalization options to minimize probability of path confusion vulnerabilities. Path confusion vulnerabilities occur when parties participating in request use different path representations.

Additionally the path_with_escaped_slashes_action setting should be set according to following recommendations:

  • REJECT_REQUEST if dowstream clients are expected to use rfc3986 compliant normalized paths (i.e. gRPC clients).

  • UNESCAPE_AND_REDIRECT if downstream client supports HTTP redirect (i.e. a browser). This option minimizes possibility of path confusion by forcing request to be re-issued with the same path across all parties: downstream client, Envoy and upstream server. Note that gRPC requests will still be rejected with the INTERNAL (13) error code, as gRPC clients do not support redirect.

  • KEEP_UNCHANGED for servers that are not rfc3986 compliant and require encoded slashes.

  • UNESCAPE_AND_FORWARD for servers that are known to treat escaped and unescaped slashes equivalently. Choosing this option may increase probablity of path confusion vulnerabilities if intermediaries perform path based access control.

The following is a YAML example of the above recommendation (taken from the Google VRP edge server configuration):

  1. overload_manager:
  2. refresh_interval: 0.25s
  3. resource_monitors:
  4. - name: "envoy.resource_monitors.fixed_heap"
  5. typed_config:
  6. "@type": type.googleapis.com/envoy.extensions.resource_monitors.fixed_heap.v3.FixedHeapConfig
  7. # TODO: Tune for your system.
  8. max_heap_size_bytes: 2147483648 # 2 GiB
  9. actions:
  10. - name: "envoy.overload_actions.shrink_heap"
  11. triggers:
  12. - name: "envoy.resource_monitors.fixed_heap"
  13. threshold:
  14. value: 0.95
  15. - name: "envoy.overload_actions.stop_accepting_requests"
  16. triggers:
  17. - name: "envoy.resource_monitors.fixed_heap"
  18. threshold:
  19. value: 0.98
  20. admin:
  21. address:
  22. socket_address:
  23. address: 127.0.0.1
  24. port_value: 9090
  25. static_resources:
  26. listeners:
  27. - address:
  28. socket_address:
  29. address: 0.0.0.0
  30. port_value: 443
  31. listener_filters:
  32. - name: "envoy.filters.listener.tls_inspector"
  33. # Uncomment if Envoy is behind a load balancer that exposes client IP address using the PROXY protocol.
  34. # - name: envoy.filters.listener.proxy_protocol
  35. # typed_config:
  36. # "@type": type.googleapis.com/envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol
  37. per_connection_buffer_limit_bytes: 32768 # 32 KiB
  38. filter_chains:
  39. - filter_chain_match:
  40. server_names: ["example.com", "www.example.com"]
  41. transport_socket:
  42. name: envoy.transport_sockets.tls
  43. typed_config:
  44. "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
  45. common_tls_context:
  46. tls_certificates:
  47. - certificate_chain: {filename: "certs/servercert.pem"}
  48. private_key: {filename: "certs/serverkey.pem"}
  49. filters:
  50. - name: envoy.filters.network.http_connection_manager
  51. typed_config:
  52. "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
  53. stat_prefix: ingress_http
  54. use_remote_address: true
  55. normalize_path: true
  56. merge_slashes: true
  57. path_with_escaped_slashes_action: UNESCAPE_AND_REDIRECT
  58. common_http_protocol_options:
  59. idle_timeout: 3600s # 1 hour
  60. headers_with_underscores_action: REJECT_REQUEST
  61. http2_protocol_options:
  62. max_concurrent_streams: 100
  63. initial_stream_window_size: 65536 # 64 KiB
  64. initial_connection_window_size: 1048576 # 1 MiB
  65. stream_idle_timeout: 300s # 5 mins, must be disabled for long-lived and streaming requests
  66. request_timeout: 300s # 5 mins, must be disabled for long-lived and streaming requests
  67. http_filters:
  68. - name: envoy.filters.http.router
  69. route_config:
  70. virtual_hosts:
  71. - name: default
  72. domains: ["*"]
  73. routes:
  74. - match: {prefix: "/"}
  75. route:
  76. cluster: service_foo
  77. idle_timeout: 15s # must be disabled for long-lived and streaming requests
  78. clusters:
  79. - name: service_foo
  80. per_connection_buffer_limit_bytes: 32768 # 32 KiB
  81. load_assignment:
  82. cluster_name: some_service
  83. endpoints:
  84. - lb_endpoints:
  85. - endpoint:
  86. address:
  87. socket_address:
  88. address: 127.0.0.1
  89. port_value: 8080
  90. typed_extension_protocol_options:
  91. envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
  92. "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
  93. explicit_http_config:
  94. http2_protocol_options:
  95. initial_stream_window_size: 65536 # 64 KiB
  96. initial_connection_window_size: 1048576 # 1 MiB
  97. layered_runtime:
  98. layers:
  99. - name: static_layer_0
  100. static_layer:
  101. envoy:
  102. resource_limits:
  103. listener:
  104. example_listener_name:
  105. connection_limit: 10000
  106. overload:
  107. global_downstream_max_connections: 50000