Apache 2.4.64, SNI, and 421 Misdirected Request: cause and fix

After upgrading to Apache 2.4.64 (or after applying linux vendors updates) many sites behind a reverse proxy started returning 421 Misdirected Request. The practical cause is simple: when your proxy makes an HTTPS connection to Apache, Apache now expects a correct TLS SNI value that matches the HTTP host. If the proxy omits SNI or sends a different name than the Host header, Apache can reject the request with 421. This change exposed default proxy settings that used to work by accident.

What the 421 error means

The HTTP 421 Misdirected Request status means the request reached a server that is not configured to respond for the combination of scheme and authority that you used. Browsers often reuse HTTP/2 connections across hosts if the server allows it, but Apache 2.4.64 tightened the checks so that connections without a matching SNI and Host are rejected. That is why you can see the error only on some requests or only on some subdomains after the update. The error message is the following:

Misdirected Request

The client needs a new connection for this request as the requested host name does not match the Server Name Indication (SNI) in use for this connection.

Who is affected

You are affected if a reverse proxy connects to Apache over HTTPS and does not pass SNI to the backend. This is common for nginx in front of Apache, HAProxy with HTTPS backends, and some CDNs or load balancers that re-encrypt to the origin. Panels that pair nginx and Apache (for example EA-Nginx on cPanel, Plesk, Hestia, and similar) were among the first to report 421 after the update.

Fix: send the correct SNI to Apache and keep it consistent with Host

The fix is to enable SNI on the upstream HTTPS hop and make its value match the HTTP Host that Apache should serve. Keep the connection private (VPC, VLAN, VPN, or same host) if you do not want the name visible outside your network. Do not roll back the Apache security update. Configure your proxy once and the 421 errors stop.

nginx to Apache over HTTPS

Enable SNI toward the backend and keep Host consistent.

location / {
    proxy_pass              https://backend.example.com;
    proxy_set_header        Host $host;
    proxy_ssl_server_name   on;      # send SNI
    proxy_ssl_name          $host;   # SNI value
[..]
}

HAProxy to Apache over HTTPS

Pass the Host header as the SNI value on the TLS connection to Apache. Add verification settings that match your policy.

backend app
    http-request set-header X-Forwarded-Proto https
    server app1 127.0.0.1:443 ssl sni req.hdr(Host)

Apache to Apache with mod_proxy over HTTPS

Use an https URL whose hostname is the site you want to serve so that Apache sends that name as SNI to the backend.

SSLProxyEngine on
ProxyPass        / https://site.example.com/
ProxyPassReverse / https://site.example.com/

How to test and confirm

From the proxy host, curl the backend using the public hostname and the backend IP to confirm that SNI and Host agree. Watch your Apache error log for messages about missing SNI or a vhost mismatch while you test.

curl -vk https://example.com/ --resolve example.com:443:127.0.0.1

FAQ

The 421 you see is produced by the stricter SNI and authority checks added around 2.4.64 and enforced by HTTP/2 handling. The cure is to send a correct SNI on the upstream connection and keep it consistent with Host.

Do I need to verify the backend certificate for SNI to matter? No. Apache uses SNI during the TLS handshake to pick the correct SSL vhost and certificate before it even reads the HTTP request. Certificate verification by the proxy is a separate operational choice. The important part for avoiding 421 is that the SNI you send and the Host header you send resolve to the same Apache vhost.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *