將 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