配置 Envoy 作为边缘代理
Envoy 是一个生产就绪的边缘代理,但是,默认设置是为服务网格用例量身定制的,在使用 Envoy 作为边缘代理时需要调整一些值。
TCP 代理应该配置
HTTP 代理还应该配置
use_remote_address 为 true(避免使用来自外部客户端的 HTTP 头,详情请参见 HTTP 头部清理),
HTTP/2 最大并发流限制 和 HTTP/3 最大并发流限制 为 100
HTTP/2 初始流窗口大小限制 为 64 KiB,
HTTP/2 初始连接窗口大小限制 为 1 MiB。
headers_with_underscores_action 设置 为 REJECT_REQUEST,以保护将“_”和“-”视为可互换的上游服务。
如果 Envoy 配置了 RBAC 过滤器或根据 URL 路径进行路由选择,建议启用以下路径规范化选项,以最大程度地降低路径混淆漏洞的可能性。路径混淆漏洞发生在参与请求的各方使用不同的路径表示时。
启用 merge_slashes 设置。
此外,path_with_escaped_slashes_action 设置 应根据以下建议设置
如果预期下游客户端使用 RFC 3986 符合规范的规范化路径(例如 gRPC 客户端),则为 REJECT_REQUEST。
如果下游客户端支持 HTTP 重定向(例如浏览器),则为 UNESCAPE_AND_REDIRECT。此选项通过强制所有参与方(下游客户端、Envoy 和上游服务器)使用相同路径重新发出请求,来最大程度地减少路径混淆的可能性。请注意,gRPC 请求仍将被拒绝,错误代码为 INTERNAL (13),因为 gRPC 客户端不支持重定向。
对于不符合 RFC 3986 且需要编码斜杠的服务器,则为 KEEP_UNCHANGED。
对于已知将转义和未转义斜杠等效对待的服务器,则为 UNESCAPE_AND_FORWARD。如果中间件执行基于路径的访问控制,选择此选项可能会增加路径混淆漏洞的可能性。
以下是上述建议的 YAML 示例(取自 Google VRP 边缘服务器配置)
overload_manager:
refresh_interval: 0.25s
resource_monitors:
- name: "envoy.resource_monitors.fixed_heap"
typed_config:
"@type": type.googleapis.com/envoy.extensions.resource_monitors.fixed_heap.v3.FixedHeapConfig
# TODO: Tune for your system.
max_heap_size_bytes: 2147483648 # 2 GiB
actions:
- name: "envoy.overload_actions.shrink_heap"
triggers:
- name: "envoy.resource_monitors.fixed_heap"
threshold:
value: 0.95
- name: "envoy.overload_actions.stop_accepting_requests"
triggers:
- name: "envoy.resource_monitors.fixed_heap"
threshold:
value: 0.98
admin:
address:
socket_address:
address: 127.0.0.1
port_value: 9090
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 443
listener_filters:
# Uncomment if Envoy is behind a load balancer that exposes client IP address using the PROXY protocol.
# - name: envoy.filters.listener.proxy_protocol
# typed_config:
# "@type": type.googleapis.com/envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol
- name: "envoy.filters.listener.tls_inspector"
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
per_connection_buffer_limit_bytes: 32768 # 32 KiB
filter_chains:
- filter_chain_match:
server_names: ["example.com", "www.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_certificates:
- certificate_chain: {filename: "certs/servercert.pem"}
private_key: {filename: "certs/serverkey.pem"}
alpn_protocols: ["h2,http/1.1"]
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
use_remote_address: true
normalize_path: true
merge_slashes: true
path_with_escaped_slashes_action: UNESCAPE_AND_REDIRECT
common_http_protocol_options:
idle_timeout: 3600s # 1 hour
headers_with_underscores_action: REJECT_REQUEST
http2_protocol_options:
max_concurrent_streams: 100
initial_stream_window_size: 65536 # 64 KiB
initial_connection_window_size: 1048576 # 1 MiB
stream_idle_timeout: 300s # 5 mins, must be disabled for long-lived and streaming requests
request_timeout: 300s # 5 mins, must be disabled for long-lived and streaming requests
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
virtual_hosts:
- name: default
domains: ["*"]
routes:
- match: {prefix: "/"}
route:
cluster: service_foo
idle_timeout: 15s # must be disabled for long-lived and streaming requests
clusters:
- name: service_foo
per_connection_buffer_limit_bytes: 32768 # 32 KiB
load_assignment:
cluster_name: some_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8080
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options:
initial_stream_window_size: 65536 # 64 KiB
initial_connection_window_size: 1048576 # 1 MiB
layered_runtime:
layers:
- name: static_layer_0
static_layer:
envoy:
resource_limits:
listener:
example_listener_name:
connection_limit: 10000
overload:
global_downstream_max_connections: 50000