將 Envoy 設定為邊緣代理

Envoy 是一個已準備好用於生產環境的邊緣代理,然而,預設設定是為服務網格的使用案例量身定制的,當將 Envoy 用作邊緣代理時,需要調整一些數值。

TCP 代理應配置

HTTP 代理應額外配置

如果 Envoy 配置了 RBAC 篩選器或根據 URL 路徑進行路由選擇,建議啟用以下路徑正規化選項,以最小化路徑混淆漏洞的可能性。當參與請求的各方使用不同的路徑表示時,會發生路徑混淆漏洞。

此外,應根據以下建議設定 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