Dominik,
On 6/25/21 10:42 AM, Froehlich, Dominik wrote:
Your code sends a 421 if the SNI and host header don't match.
Is this the recommended behavior? The RFC is pretty thin here:
" Since it is possible for a client to present a different server_name
in the application protocol, application server implementations that
rely upon these names being the same MUST check to make sure the
client did not present a different name in the application protocol."
(from https://datatracker.ietf.org/doc/html/rfc6066#section-11.1 )
Indeed it is. See the HTTP/2 RFC:
https://datatracker.ietf.org/doc/html/rfc7540#section-9.1.1.
Additionally I would recommend using single-domain certificates (if
possible), then a regular browser will never see a 421, because it will
not perform connection reuse.
My initial idea was to simply pave over any incoming headers with the SNI:
http-request set-header Host %[ssl_fc_sni] if { ssl_fc_has_sni }
This wouldn't abort the request with a 421 but I am not sure if I MUST abort it
to be compliant.
This is equivalent to routing based off the SNI directly and it's as
unsafe. If a browser reuses a TCP connection for an unrelated host you
will send the request to the wrong backend.
Regarding domain fronting, I thought I might be able to have the cake and eat
it, too if I still allowed it but only prevented it for mTLS
Requests. Maybe like this:
http-request set-header Host %[ssl_fc_sni] if { ssl_c_used }
Only performing checks when `ssl_c_used` is true should be safe. But I
*strongly* recommend sending a 421 instead of attempting to fiddle
around with the 'host' header. It's just too easy to accidentally
perform incorrect routing. It would then look like this:
http-request set-var(txn.host) hdr(host)
http-request deny deny_status 400 unless { req.hdr_cnt(host) eq 1 }
# Verify that SNI and Host header match if a client certificate is sent
http-request deny deny_status 421 if { ssl_c_used } ! {
ssl_fc_sni,strcmp(txn.host) eq 0 }
Best regards
Tim Düsterhus