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.)

  • Update 1: It seems there is now a draft protocol that aims to achieve exactly what I ask – called ESNI, short for Encrypted SNI – which is a collaboration between Cloudflare and Mozilla Firefox, although their implementation is restricted to DoH queries only. Jun 15 '20 at 7:35
  • ESNI has not been standardized by IETF yet, and unfortunately, isn't supported by Chrome as of writing this. Jun 15 '20 at 7:36

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

  • 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...
    – The D
    Mar 27 '17 at 8: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. Mar 27 '17 at 8: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. Mar 27 '17 at 9: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 9:26
  • 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 8:29

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.

  • +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. Mar 27 '17 at 4:18

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.

  • +1, but unfortunately as stated the server is actually hosting multiple sites, so it won't be possible that way. Mar 27 '17 at 4:17
  • @DRSDavidSoft It depends on how it is hosting multiple sites.
    – kasperd
    Mar 27 '17 at 8: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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.