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

3
  • 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. Commented Jun 15, 2020 at 7:35
  • ESNI has not been standardized by IETF yet, and unfortunately, isn't supported by Chrome as of writing this. Commented Jun 15, 2020 at 7:36
  • Update 2: It seems that ESNI is now being deprecated in favor of ECH (Encrypted Client Hello) now, still an IETF draft unfortunately. Requires DNS-over-HTTPS to work apparantly. Commented May 21 at 8:47

3 Answers 3

17

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

8
  • 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
    Commented Mar 27, 2017 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. Commented Mar 27, 2017 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. Commented Mar 27, 2017 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? Commented Mar 27, 2017 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
    Commented Apr 17, 2018 at 8:29
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.

1
  • +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. Commented Mar 27, 2017 at 4: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.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .