HTTP status code to signal bad or missing Host header

8,186

RFC 6066 doesn't specify or even recommend any particular HTTP error in the case that the hostname sent via SNI doesn't match the HTTP Host header. It does recommend that the server abort the TLS handshake if the SNI hostname is not one that it provides service for. From section 3:

If the server understood the ClientHello extension but does not recognize the server name, the server SHOULD take one of two actions: either abort the handshake by sending a fatal-level unrecognized_name(112) alert or continue the handshake.

Since such a malformed request can get past the TLS handshake and need to be rejected in HTTP, an HTTP response code is necessary. Of all those that exist, only one really fits the situation:

6.5.1. 400 Bad Request

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

This is, in fact, the response that RFC 7230 specifies. From section 5.4 describing the Host header:

A server MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message that lacks a Host header field and to any request message that contains more than one Host header field or a Host header field with an invalid field-value.

I'm going to recommend strongly against using 502 for this. Its semantics indicate that something is wrong on the server side and that the request would succeed if tried later.

Share:
8,186

Related videos on Youtube

kasperd
Author by

kasperd

Updated on September 18, 2022

Comments

  • kasperd
    kasperd over 1 year

    Is there an HTTP status code which is appropriate to use for clients which send a bad hostname (or none at all) through SNI or the HTTP Host header?

    An older question address how and why such requests happen in the first place as well as how you can technically deal with them in Apache. It does however not address the choice of status code for the response.

    In the past I have implemented an HTTP proxy which would send status code 502 and an html page explaining why the error message was produced. My rationale for using 502 was an expectation that I would mainly see it due to misconfigurations which meant the proxy could not find a suitable backend. In reality it turned out to be much more frequent to simply see completely bogus hostnames.

    Is there another status code which is more appropriate and clearly signals to the client that the server on this IP address does not recognize the value sent through SNI and/or the Host header?

    • Naveed Abbas
      Naveed Abbas over 6 years
      Why care about SNI matching specifically? SNI benefits the client, and only the client. Client asks for the certificate that does exist but it authenticates a mismatched domain name? So? Surely no harm for server. Just give the clients the opportunity to authenticate that weird way; maybe they fancy getting the content of google.com authenticated by the certificate of facebook.com. Who knows. Only the Host header is a genuine security concern in this question.
    • kasperd
      kasperd over 6 years
      @kubanczyk I have a proxy which uses SNI to find the right server which will terminate the TLS connection. Without a correct hostname in SNI from the client the proxy has nowhere to terminate the TLS connection. Until now it would just close such TCP connections without sending anything. But by using Michael's answer, I could instead terminate those TLS connections on a host that replies with a fixed 7 byte TLS message {0x15, 0x03, 0x03, 0x00, 0x02, 0x02, 0x70}.
    • Naveed Abbas
      Naveed Abbas over 6 years
      This is the purpose of 'Host' header, not the intended use of SNI. If you look at SNI, but ignore the 'Host' header, you are not RFC compliant. If you require SNI, you're breaking backward compatibility with older clients. SNI indicates client wants a specific certificate, not a specific website.
  • kasperd
    kasperd over 6 years
    unrecognized_name should be trivial for me to implement and an unambiguous improvement compared to how I treat that scenario currently. As for the HTTP code my proxy does not necessarily know if the problem lies on the client side or server side of the proxy, could even be misconfigured DNS records. So your answer sounds good in general but I'll evaluate that part a bit more closely before I apply it to my specific use case.
  • Michael Hampton
    Michael Hampton over 6 years
    I think the major takeaway here is that it should be clear to the client that the problem exists at the client side. unrecognized_name and 400 do this.
  • kasperd
    kasperd over 6 years
    My concern about using status code 400 is that the problem is not necessarily on the client. The problem could be due to misconfigured DNS records. Also code 400 does not unambiguously communicate to the client that the Host header is what the server doesn't like. I implemented unrecognized_name as suggested (I had an old piece of code lying around that just needed a very minor change to do exactly that). And at least in Chromium it is treated more or less identical to a network connectivity problem, but at least the error message says ERR_SSL_UNRECOGNIZED_NAME_ALERT.
  • Michael Hampton
    Michael Hampton over 6 years
    You always have the option of describing the problem more specifically in the response body. HTTP's error codes aren't granular enough for what you want.
  • kasperd
    kasperd over 6 years
    I have been sending such a description in the response body all along, though only for HTTP. Looks like there isn't anything more granular in the current standard than 400. I can't tell from the wording if invalid field-value is just supposed to cover anything syntactically incorrect or if it is also supposed to cover perfectly valid DNS names that just happens to not have been configured on the server.