Skip to content

Bind socket addresses, choose a filter chain per connection, terminate TLS, and run listener filters such as the TLS inspector.

A listener binds a socket address, accepts connections, and hands each one to the filter chain that best matches it. Configure one listener per port Arion serves, and use multiple filter chains when a single port must present different certificates, tenants, or protocols.

Enable a listener

envoy_bootstrap:
  static_resources:
    listeners:
      - name: listener_http
        address:
          socket_address: { address: 0.0.0.0, port_value: 8080 }
        filter_chains:
          - name: default_chain
            filters:
              - name: http_gateway
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                  codec_type: HTTP1
                  http_filters:
                    - name: envoy.filters.http.router
                      typed_config:
                        "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
                  route_config:
                    name: local_routes
                    virtual_hosts:
                      - name: backend
                        domains: ["*"]
                        routes:
                          - match: { prefix: "/" }
                            route: { cluster: api }

A listener needs a unique name, an address, and at least one filter chain. Each chain runs optional network filters — RBAC, connection limit, global rate limit — followed by exactly one terminal filter: an HTTP connection manager or a TCP proxy. tcp_backlog_size (default 128) sizes the accept queue, and socket_options may carry one bind-device entry (a Linux SO_BINDTODEVICE interface name).

Sockets, pipes, and internal listeners

Listeners bind TCP socket addresses. Unix pipes sit on the other side of the proxy: a cluster endpoint may use a pipe address, so Arion can accept on a TCP port and forward to a local process over a Unix socket. Inside a cluster's load_assignment:

lb_endpoints:
  - endpoint:
      address:
        pipe:
          path: /var/run/backend.sock

A listener declared with internal_listener: {} in place of an address accepts connections from inside the proxy rather than from the network; clusters reach it through endpoints with internal addresses. Binding a listener to a pipe address is rejected at startup.

Multiple filter chains

When a listener has several filter chains, Arion picks one per connection using filter_chain_match:

FieldMatches
destination_portPort the connection arrived on
prefix_rangesDestination IP, CIDR
server_namesTLS SNI, exact or *.example.com wildcard
source_prefix_rangesClient IP, CIDR
source_portsClient port

The most specific chain wins: a chain that states no rule for a criterion stays eligible, a chain whose rule fails is out, and among matches the tighter value (longer CIDR prefix, more exact SNI) is preferred. All match blocks in a listener must be unique, and a chain with no filter_chain_match is the catch-all:

filter_chains:
  - name: api_chain
    filter_chain_match:
      server_names: [api.example.com]
    # filters for api traffic ...
  - name: catch_all
    # no filter_chain_match: everything else lands here

Envoy's transport_protocol, application_protocols, source_type, and default_filter_chain fields are not supported; a config that uses them is refused at startup.

Matching on server_names requires the TLS inspector listener filter. Arion never adds it implicitly — a listener that matches on SNI without envoy.filters.listener.tls_inspector fails at startup, because the matches could never succeed.

TLS on a filter chain

TLS terminates per filter chain through a transport_socket, so each chain can present its own certificate:

filter_chains:
  - name: api_chain
    filter_chain_match:
      server_names: [api.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_certificate_sds_secret_configs:
            - name: api_server_cert
    filters:
      # terminal filter ...

Set require_client_certificate: true for mTLS. Certificates can be inlined, read from files, or referenced as SDS secrets that rotate without a restart — see TLS and mTLS and secrets and rotation.

Listener filters

Listener filters inspect the raw connection before a filter chain is chosen. Arion supports three: the TLS inspector reads the SNI from the TLS ClientHello so chain matching (and the global rate limiter's SNI-as-domain mode) can use it; proxy protocol recovers the original client address from a PROXY v1/v2 header; and the listener-level local rate limit drops connections above a token-bucket rate before any other work happens — see rate limiting for choosing a limiter.

Verify

With the admin interface on port 9901, list bound listeners:

curl -s http://127.0.0.1:9901/listeners
listener_http::0.0.0.0:8080

Limits

  • Listeners are TCP only; udp_listener_config (QUIC) is rejected.
  • One terminal filter per chain, always last; RBAC, connection limit, and global rate limit must precede it.
  • At most one bind device per listener.
  • listener_filters_timeout, use_original_dst, and per-connection buffer limits are not supported and are refused at startup.
  • Pipe addresses work for cluster endpoints, not listener binds.

Every listener field is tabulated in the listener reference.

Continue

Start typing to search the site.

↑ ↓ to move Enter to open Esc to close