Skip to main content
Version: 5.x

What is new in MTE Relay v5

MTE Relay v5 is a new major version with a new wire protocol. v5 servers and v5 clients work together; v4 clients cannot connect to a v5 relay. Plan the move with Upgrading from v4.

Performance against v4​

On the same hardware, v5 moves up to 37% more requests per second than v4, uses about 90% less memory per relay, and answers with up to 39% lower latency. High availability needs 1 Redis instead of 2. Every chart is in the v5 executive brief.

Release components​

ComponentCurrent v5 release
MTE Relay Server (MRS) image5.0.5
MTE API Relay (MAR) image5.0.5
mte-relay-browser engine5.0.0
mte-relay-browser-public-client5.0.0
Angular client5.0.0
Java / Android client5.3.0
Swift / iOS client5.3.0
Flutter client (SPM)5.3.0
Flutter client (CocoaPods)5.3.0
Blazor client5.0.0
Python Requests client5.0.0
Python Locust client5.0.0

Protocol​

  • Frame version 2. Every request and response travels as binary frames, each with a 12 byte header. A request is one REQUEST frame followed by DATA frames, and a response is one RESPONSE frame followed by DATA frames. An encrypted request is a single POST / with Content-Type: application/octet-stream.
  • Verified before released. Each DATA frame is one MTE or MKE operation, and neither end releases a byte of plaintext until its frame is verified.
  • One encrypted metadata object per request. Method, path, query, and headers are encoded together. Response headers are encoded the same way, and the response status is repeated inside them. While forward_browser_cookies is on, the default, the origin's Set-Cookie moves to the plain HTTP response.
  • Bounded frames. Bodies move as frames of at most MAX_FRAME_BYTES (64 KiB by default).
  • Headers first. The relay sends the response status and headers as soon as the origin answers, before the first body byte, so streamed responses such as server sent events start at once.

Security​

  • Kyber 1024 by default, with 512 and 768 available through KYBER_STRENGTH. v4 used 512.
  • Bound envelope. The encrypted method, frame version, and frame flags must match the plaintext envelope, or the relay answers 483 header_mismatch. A mismatch in the metadata or in any DATA frame is also logged as a security event. The client applies the same check to the response status.
  • Replay detection. A replayed request is refused with 479 replay_rejected and logged as a security event.
  • Rate limits on auth, pairing, and keepalive, answered 488 rate_limited with Retry-After.
  • Signed client tokens with a maximum age, checked at pair and keepalive.
  • Library profile check. Discovery publishes the MTE library profile, and a client refuses to pair with a relay whose library settings differ.

Operations​

  • New error model. Relay errors use 470 to 490 with a reason token and an X-MTE-Relay-Error header, and 500, 502, and 503 stay for true faults. See Errors and recovery.
  • Discovery. The auth answer lists the relay's limits, timers, features, and per domain settings. See Discovery.
  • Keepalive. POST /api/mte-keepalive refreshes every pair of a client in one call. See Keepalive and timeouts.
  • Control plane. An optional admin panel and API, from the same image with MODE=control: a setup wizard, live settings, fleet status, history, and rollback. See Control plane.
  • Probes. Workers answer GET /healthz and GET /readyz on a separate port, 9091 by default, with GET and HEAD. /healthz answers 200 {"status":"ok","phase":"<phase>"} for as long as the process runs. /readyz answers 200 {"status":"ready","phase":"ready"} while the relay takes traffic, or 503 with the phase and a reason otherwise.
  • Health check path. HEALTH_CHECK_PATH, off by default, mounts a 200 {"status":"ready"} answer on the relay port at a path you pick, for any Host and outside every rate limit, for a load balancer or a security scanner that cannot reach the probe port. It applies live from the control plane. See CORS and WAF.
  • Echo takes HEAD. GET /api/mte-echo and HEAD /api/mte-echo answer outside every rate limit, and the message stays a JSON string as in v4. MTE Relay and SocketX now share the same health, readiness, and echo behavior, the same discovery check order, codes, and 600 per minute budget, and the same origin rules: case insensitive, and https://*.example.com requires the scheme to match. See Discovery.
  • Request ids. X-MTE-Relay-Request-Id is set on every response and sent upstream, so one id ties client, relay, and origin logs together.
  • Sticky routing. Every framed request, pairing call, and keepalive carries X-MTE-Relay-Route, so a load balancer can hash clients to replicas, and LOCAL_STATE_CACHE can then serve pair state from memory.

Configuration​

  • DOMAIN_MAP only. The v4 single upstream variables are removed. Domain keys can be hostnames, host:port, bracketed IPv6 literals, *.suffix wildcards, or *. Keys and the request Host compare case insensitively, overlapping wildcards resolve from the most specific, and a relay that generates a missing client_id_secret warns at startup naming the hosts. SocketX uses the same member names and the same matcher. See DOMAIN_MAP.
  • One vocabulary with SocketX. LISTEN_HOST and LISTEN_PORT name the listener (PORT stays as an alias, HOSTNAME is retired because it never bound anything), MAX_PAIR_BYTES replaces MAX_PAIR_MIB (kept as an alias), DRAIN_SECONDS is the honored shutdown budget, LOG_LEVEL accepts warning, and every environment value that does not parse logs a warning naming the variable and the default in use. Log lines carry time as RFC 3339 with milliseconds and a caller field in both products, and a logged secret shows three characters then asterisks. See Environment variables.
  • More per domain settings: CORS credentials, headers, and preflight handling, preserve_host, trust_forwarded_headers, forward_browser_cookies, forward_plain_headers, per domain timers, and response coalescing.
  • Outbound domains. MTE API Relay chains use outbound: true entries in place of v4's outbound token and x-mte-upstream header.
  • New limits: MAX_REQUEST_BODY_MIB, MAX_CONTROL_BODY_MIB, and the frame, metadata, and pair bounds. See Limits and scaling.
  • New pool settings: DEFAULT_POOL_SIZE and MAX_POOL_SIZE_LIMIT for the server codec pools, and CLIENT_INITIAL_PAIRS, CLIENT_MIN_PAIRS, CLIENT_MAX_PAIRS, CLIENT_REFILL_THRESHOLD, and CLIENT_PAIR_ACQUIRE_WAIT_MS for outbound domains.

Every setting is listed on Environment variables.

Clients​

  • Browser. The mte-relay-browser engine 5.0.0 speaks frame version 2. The public client package mte-relay-browser-public-client 5.0.0 bundles it, with configureMteRelay for startup options. See the JavaScript client.
  • Angular. mte-relay-angular plugs the same engine into Angular's HttpClient. See the Angular client.
  • Mobile. v5 iOS and Android clients speak frame version 2. See each platform page.