Why Do Envoy Gateways Return 404 When :authority and SNI Mismatch in HTTP/2?
In many Envoy‑based gateways, enabling HTTP/2 can cause intermittent 404 errors because the :authority header and the TLS SNI value differ, especially when using wildcard certificates and multi‑domain routing, and this article explains the root cause and multiple mitigation strategies.
Problem Background
In most Envoy‑based gateways, enabling HTTP/2 may lead to occasional 404 responses. The logs show that the domain in the :authority header does not match the domain indicated by the SNI (Server Name Indication) during TLS handshake. The issue is especially common when a wildcard certificate is used and multiple domain routes are configured.
Root Cause
HTTP/2 reuses a single TCP/TLS connection for multiple requests. Browsers will reuse a connection to domain B on the same connection that was originally established for domain A if:
The two domains resolve to the same IP address.
The certificate presented for domain A is a wildcard that also matches domain B, or domain B appears in the certificate’s SAN list.
When a request for domain B is sent over the connection created for domain A, the gateway sees a mismatch between SNI (which is still domain A) and the :authority header (domain B), resulting in a 404 because Envoy’s routing is typically one‑to‑one between SNI and route configuration.
Solution 1 – Reuse the Same Filter Chain for Domains Sharing a Certificate
Configure domains that share the same wildcard certificate to use the same filter chain. This eliminates the SNI/authority mismatch because the same routing configuration applies to both domains.
Drawbacks:
If a certificate is updated, all filter chains that share it must be rebuilt, causing downstream connections to drop.
The control plane becomes more complex; for example, when using Gateway API, a one‑to‑one mapping between filter chain and listener is no longer possible.
Solution 2 – Return HTTP 421 (Misdirected Request) via Lua Filter
Use a Lua filter to detect when the SNI does not match the :authority header and respond with status 421. Example snippet:
@type: "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
inlineCode: |
function envoy_on_request(request_handle)
local streamInfo = request_handle:streamInfo()
if streamInfo:requestedServerName() ~= "" then
if (string.sub(streamInfo:requestedServerName(), 1, 2) == "*." and not string.find(request_handle:headers():get(":authority"), string.sub(streamInfo:requestedServerName(), 2))) then
request_handle:respond({[":status"] = "421"}, "Misdirected Request")
end
if (string.sub(streamInfo:requestedServerName(), 1, 2) ~= "*." and streamInfo:requestedServerName() ~= request_handle:headers():get(":authority")) then
request_handle:respond({[":status"] = "421"}, "Misdirected Request")
end
end
endDrawbacks:
Connection reuse benefits are lost, which may degrade page‑load performance for workloads that rely on HTTP/2 multiplexing.
HTTP 421 is not supported by some older Chromium‑based Android apps; returning 421 can cause business‑critical errors.
Solution 3 – Share Routing Configuration Across Filter Chains
Instead of separate filter chains per SNI, share a common routing configuration (RDS, VHDS, or SRDS) among all filter chains.
3.1 Based on RDS
All HTTPS filter chains reference the same RDS resource. This can cause the RDS to become very large, preventing efficient delta‑xDS updates and increasing CPU usage on the Envoy main thread whenever any part of the RDS changes.
3.2 Based on VHDS (Virtual Host Discovery Service)
VHDS fetches routing only when a request’s domain is not found locally. Heavy 404 traffic can overload the control plane because each miss triggers a pull from the xDS server.
3.3 Based on SRDS (Scoped RDS)
Envoy already supports routing slices based on request headers. Extending SRDS to slice by domain (including wildcard support) allows per‑domain routing while keeping a shared configuration.
// [#next-free-field: 6]
message ScopedRoutes {
// ... other fields ...
message HostValueExtractor {
google.protobuf.UInt32Value max_recompute_num = 1;
}
message LocalPortValueExtractor {}
oneof type {
HeaderValueExtractor header_value_extractor = 1;
HostValueExtractor host_value_extractor = 101;
LocalPortValueExtractor local_port_value_extractor = 102;
}
repeated FragmentBuilder fragments = 1 [(validate.rules).repeated = {min_items: 1}];
}Security Considerations When Sharing Routes
Different filter chains may enforce distinct authentication policies (e.g., mTLS client certificates, IP‑based RBAC). Exposing all routes to every filter chain can bypass these policies, creating a security risk.
A safer approach is for the control plane to detect when a domain requires a specific authentication filter chain and enforce protection accordingly. For example, Higress adds an allow_server_names field to VirtualHost so that a request is only allowed if its SNI matches an allowed list:
message VirtualHost {
// ... other fields ...
// If non‑empty, a list of server names (such as SNI) that are allowed to access this VirtualHost.
// Requests with other SNI values receive a 421 response.
repeated string allow_server_names = 101;
}Community Feedback and RFC Context
Some traditional HTTP proxies (e.g., httpd) do not route based on mismatched :authority and SNI, while Nginx has an open issue discussing potential security concerns. The Nginx maintainer responded that there is no real security issue, citing RFC 6066, which predates HTTP/2 multiplexing.
RFC 6066 states that a client should not request a different server name after the TLS handshake. However, HTTP/2 introduced connection reuse, allowing a client to send requests for different hostnames over the same TLS connection. The 421 status code was introduced to signal that a server cannot safely handle such a request.
Conclusion
Although the original RFC considered cross‑domain requests on a single SNI connection incorrect, modern web performance demands make HTTP/2 connection reuse essential. Properly configuring Envoy—whether by sharing filter chains, returning 421, or using scoped routing—can resolve the 404 issue while balancing performance, compatibility, and security.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Native
We publish cloud-native tech news, curate in-depth content, host regular events and live streams, and share Alibaba product and user case studies. Join us to explore and share the cloud-native insights you need.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
