配置 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