6

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?

kasperd
  • 29,894
  • 16
  • 72
  • 122
  • 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. – kubanczyk Jan 27 '18 at 23:36
  • @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](https://serverfault.com/a/894439/214507), 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}`. – kasperd Jan 27 '18 at 23:47
  • 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*. – kubanczyk Jan 28 '18 at 01:44
  • @kubanczyk The Host header is sent too late and is encrypted, that's why SNI was introduced in the first place. Any client too old to support SNI is likely going to be useless on the internet today for many other reasons. Besides I don't require clients to have SNI, only clients which choose to use IPv4 need SNI. Clients can connect using IPv6 and everything will work just fine without SNI. – kasperd Jan 28 '18 at 02:00

1 Answers1

17

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.

Michael Hampton
  • 237,123
  • 42
  • 477
  • 940
  • `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. – kasperd Jan 27 '18 at 22:49
  • 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. – Michael Hampton Jan 27 '18 at 23:24
  • 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`. – kasperd Jan 27 '18 at 23:41
  • 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. – Michael Hampton Jan 27 '18 at 23:42
  • 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. – kasperd Jan 28 '18 at 00:02