7

A server with IP address a.b.c.d is hosting multiple SSL websites.

When connecting to each website, a proper browser sends a request which include the destination host in an uncrypted clear text known as SNI, such as example.com.

After a successful SSL connection, the rest of the data are transmitted with the corresponding certificate.

The problem is, the SNI sent by the browser will be loggable by any MITM, and thus blockable by a government.

How do I prevent the other end from finding out which website I'm visitting on the server?

(Obviously not by using VPN or proxies.)

David Refoua
  • 153
  • 1
  • 13
  • **Update 1:** It seems there is now a draft protocol that aims to achieve exactly what I ask _– called [**ESNI**](https://cloudflare.com/learning/ssl/what-is-encrypted-sni/)_, short for _Encrypted_ SNI – which is a collaboration between [Cloudflare](https://blog.cloudflare.com/esni/) and [Mozilla Firefox](https://blog.mozilla.org/security/2018/10/18/encrypted-sni-comes-to-firefox-nightly/), although their implementation is [restricted to DoH queries](https://bugzilla.mozilla.org/show_bug.cgi?id=1500289) only. – David Refoua Jun 15 '20 at 07:35
  • **ESNI** has not been standardized by IETF yet, and unfortunately, isn't supported by Chrome as of writing this. – David Refoua Jun 15 '20 at 07:36

3 Answers3

16

It is not possible to hide the SNI information if the server requires it to serve the proper certificate. There was discussion on encrypting this information in TLS 1.3. But this idea was abandoned since this would require establishing an additional encryption layer and thus adding additional overhead to the connection establishment. Apart from that this information might leak anyway due to DNS lookups and of course also through the certificate the server sends, which is in plain too. Thus if you want to better protect your privacy you need to use an additional encryption layer yourself, like a VPN.

For more details see also

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
  • 1
    Couldn't a hash/challenge-based exchange be performed to determine the name without making it visible in cleartext? For example (and ignoring DNS): if a user wants "foo.com", so their browser connects to the server with the site, asks for a challenge, then tells the server "I want the website matching sha256("foo.com" + challenge)" (thus preventing replay attacks and feasible hash brute-forcing). Of course the challenge value has to be trustworthy (i.e. no MITM impersonation) but I think that would work... – Dai Mar 27 '17 at 08:22
  • 1
    I don't think this would really help. If the MITM knows the name of all domains hosted on the server (which will in my opinion usually be the case), and the number of domains is reasonably small, the MITM can brute-force the challenge using the list of possible domain names. Computation time for this would be negligible. – Elias Holzmann Mar 27 '17 at 08:48
  • 2
    @TheD: asking the server for a challenge would be yet another handshake and thus too much overhead. Instead the client could itself create a random string and send `random + hash(random+name)` to the server where the server then checks any configured name if it fits. But, apart from the additional load on the server to figure out which name to use it would still be easy to guess for an attacker which knows which hosts are available at this IP, like sk_pleasant explained already. – Steffen Ullrich Mar 27 '17 at 09:12
  • 1
    @theD Wouldn't that require the server to then sha256 every possible website name it's responsible for with the challenge to see which one you're asking for? – Shadur Mar 27 '17 at 09:26
  • @Steffen Great explanation! Just a quick addition on the DNS leaks, I actually encrypt those queries with DNSSEC or DNSCrypt Proxy, which prevents them from being leaked. I do agree that adding additional overhead complicates stuff, however does TLS implement any method to hide the SNI *after* the proper certificate is presented, so I can disable my VPN? – David Refoua Mar 27 '17 at 14:31
  • 1
    @DRSDavidSoft: SNI is needed so that the server can select the proper certificate. So it must be included in the ClientHello even when attempting a session resume since the resume might fail in which case the server needs to send the right certificate again. – Steffen Ullrich Mar 27 '17 at 14:57
  • 3
    Actually this *is* possible in theory; if a domain were for example to have a DNS record for SNI encryption, it could provide a public key to use in doing so, with the assumption that all hardware at the other end can decrypt using the corresponding private key. With a suitable random component it wouldn't produce predictable cipher-text. This relies on secure DNS, but that is something that is slowly starting to spread. – Haravikk Apr 17 '18 at 08:29
  • 1
    Final 1.3 (rfc8446) 2018-08 encrypts the server cert (and client cert if used), but not SNI. In 2020-06 an extension for ESNI is still draft. – dave_thompson_085 Jun 11 '20 at 02:15
3

How do I prevent the other end from finding out which website I'm visitting on the server?

(Obviously not by using VPN or proxies.)

You've identified the primary method.

Theoretically, you can send one host name as part of SNI, and a different one in the http Host header. However, Apache at least prevents you from doing this.

Xiong Chiamiov
  • 9,384
  • 2
  • 34
  • 76
  • +1, but while the destination server is not using Apache, further research shows that this method is actually a vulnerability, thus not viable to use. – David Refoua Mar 27 '17 at 04:18
3

You may be able to send the request without SNI.

As long as the target server doesn't have an SSL network applications (e.g. non-decrypting SSL load balancer or reverse proxy) that uses SNI to redirect connections to the right server, and server have a single SAN or wildcard certificate that covers all the services hosted there, the server should be able handle requests without SNI.

Lie Ryan
  • 31,089
  • 6
  • 68
  • 93
  • +1, but unfortunately as stated the server is actually hosting *multiple* sites, so it won't be possible that way. – David Refoua Mar 27 '17 at 04:17
  • @DRSDavidSoft It depends on how it is hosting multiple sites. – kasperd Mar 27 '17 at 08:11
  • 1
    @DRS David Soft: it is possible to serve multiple vhost without SNI. The only requirement is that all the vhosts share a single SAN/wildcard certificate, and all of the vhosts accepts TLS termination by a single machine. SNI is only needed when you want to be able to reverse proxy/load balance without first decrypting traffic. If the reverse proxy/load balancer handles decrypted traffic (either by doing TLS termination, or by standing behind a TLS terminator), they will use the Host header instead of SNI. – Lie Ryan Mar 27 '17 at 12:03