Learn Envoy Proxy - Advanced Envoy Filter Chain
Episode 8 of 23

Learn Envoy Proxy - Advanced Envoy Filter Chain

This episode deepens Envoy's filter chains: HTTP filters like ext_authz and the gRPC JSON transcoder, TCP filters like the tcp_proxy passthrough, and how to order filters and do matching correctly.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Introduction

In episodes 4 and 7, you already installed the HTTP router and http_connection_manager filters. Episode 8 shows that was just the surface: advanced filter chains are Envoy's ability to assemble HTTP and TCP filter pipelines that change how requests are processed at every stage.

You'll meet ext_authz for external authentication, the gRPC JSON transcoder that converts REST to gRPC, and tcp_proxy for forwarding raw TCP traffic. More importantly, you'll understand filter ordering — because order determines behavior.

HTTP Filters and Their Pipeline

Router: The Last Filter

All HTTP filters process requests inside a pipeline that ends with router:

Pipeline HTTP dengan tiga filter
http_filters:
  - name: envoy.filters.http.cors
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
  - name: envoy.filters.http.ext_authz
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
      transport_api_version: V3
      grpc_service:
        envoy_grpc:
          cluster_name: auth_service
      with_request_body:
        max_request_bytes: 8192
  - name: envoy.filters.http.router
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

The http_filters pipeline processes requests in sequence: CORS adds headers, ext_authz asks an authentication service, and router finally forwards the request to a cluster. Filters that modify the request must be placed before filters that consume it.

ext_authz: External Authentication

ext_authz delegates authorization decisions to an external service over gRPC. Envoy sends request metadata, and the service answers allow or deny. We'll deepen the configuration details in episode 14, but the essence is: this filter doesn't decide on its own — it asks another service.

gRPC JSON Transcoder

grpc_json_transcoder converts REST JSON requests into gRPC calls — and vice versa. This lets REST clients use a gRPC backend without any changes:

Transcoder REST ke gRPC
http_filters:
  - name: envoy.filters.http.grpc_json_transcoder
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder
      proto_descriptor: /etc/envoy/api_descriptor.pb
      services:
        - orders.v1.OrdersService
      print_options:
        always_print_primitive_fields: true
  - name: envoy.filters.http.router
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

The grpc_json_transcoder configuration uses a protobuf descriptor to map REST endpoints to gRPC methods. With print_options set, the JSON response always includes fields with zero values.

TCP Filters and Passthrough

tcp_proxy for Raw Traffic

Not all traffic is HTTP. For databases, Redis, or binary protocols, use a TCP filter:

Listener TCP dengan tcp_proxy
listeners:
  - name: listener_tcp
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 13000
    filter_chains:
      - filters:
          - name: envoy.filters.network.tcp_proxy
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
              stat_prefix: mysql_tcp
              cluster: mysql_cluster

The tcp_proxy filter forwards raw TCP connections to a cluster without parsing the protocol. This is called passthrough: incoming bytes are forwarded as-is, suitable for protocols Envoy doesn't understand. Use HTTP filters when you need path-based routing, and TCP filters when the traffic is a binary protocol.

Filter Matching and Filter Ordering

Filter Chain Match

A single listener can have several filter chains selected by connection characteristics:

Dua filter chain dengan match
listeners:
  - name: listener_multi
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
      - filter_chain_match:
          server_names:
            - api.example.com
        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: api_http
              route_config:
                name: api_routes
                virtual_hosts: []
              http_filters:
                - name: envoy.filters.http.router
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
      - filter_chain_match:
          server_names:
            - db.internal
        filters:
          - name: envoy.filters.network.tcp_proxy
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
              stat_prefix: db_tcp
              cluster: db_cluster

The filter_chain_match mechanism selects a chain based on fields like server_names (TLS SNI). Connections to api.example.com are processed as HTTP, while connections to db.internal are forwarded as raw TCP.

Correct Ordering Rules

Here are some filter ordering principles to hold onto:

  • Filters that modify the request are placed earlier.
  • Filters that read earlier processing results are placed after.
  • router is always last for HTTP.
  • The more filters, the bigger the per-request overhead.
Melihat filter yang aktif
curl -s localhost:9901/config_dump | grep -o '"name": "envoy.filters[^"]*"' | sort -u

The curl localhost:9901/config_dump command lists all loaded filters. The envoy.filters grep above filters out the unique filter names — a quick way to verify the active pipeline.

Building Your Own Pipeline

A Complete Pipeline Example

To close this episode, here's a pipeline combining CORS, authentication, and routing:

Pipeline HTTP lengkap
http_filters:
  - name: envoy.filters.http.cors
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
  - name: envoy.filters.http.router
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

Note: in this example CORS is placed before router, so the CORS headers are correct before the response is sent. Filter ordering will be discussed even more deeply when we add rate limiting in episode 10 and RBAC in episode 12.

Closing

Episode 8 opened Envoy's filter toolbox: an HTTP pipeline with ext_authz and the gRPC JSON transcoder, TCP passthrough with tcp_proxy, and the matching and ordering that determine overall behavior.

Key takeaways:

  • http_filters is a pipeline; router always takes the last position.
  • ext_authz delegates authentication to an external gRPC service.
  • grpc_json_transcoder converts REST into gRPC calls.
  • tcp_proxy forwards raw bytes without parsing the protocol.
  • filter_chain_match selects chains based on SNI and connection characteristics.
  • Filter ordering determines behavior: modify first, consume later.

In the next episode, episode 9, we'll discuss dynamic configuration with xDS — the LDS, RDS, CDS, EDS, and SDS principles, Envoy as a flexible xDS client, and basic integration with control planes like Gloo, Contour, Istio, or a custom xDS server.

Learn Envoy Proxy - Advanced Envoy Filter Chain | Learn Envoy Proxy