Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is SNI actually used and supported in browsers?

I can find various information about SNI (see Wikipedia), but I can't find any statistics about actual support in browsers.

The best I could find out is that it should work on Windows XP with SP3.

Does anyone know if SNI can actually be used in practice?

like image 613
Aljosa Mohorovic Avatar asked Mar 01 '11 12:03

Aljosa Mohorovic


People also ask

Do all browsers support SNI?

Because SNI is relatively new, not all browsers support SNI. If the browser does not support SNI, it is presented with a default SSL certificate.

Which browsers do not support SNI?

IE6 and IE7 in XP appear to be the largest old browsers that don't support SNI. It also appears to matter which server software you are using. With Apache, browsers without SNI support will just get the first configured website (and a hostname mismatch warning probably).

Does Chrome use SNI?

Server Name Indication (SNI) is not currently supported. However, there is an open request for this feature. Users can't use multiple sign-in access if TLS inspection is enabled.

Does Firefox support SNI?

Starting in Firefox 73, users can easily use DNS-over-HTTPS (DoH) and Encrypted Server Name Indication (SNI) for better privacy without extra software. These newer DNS security features help protect user privacy during web activity.


1 Answers

I can share my experience and approach to switching from one-IP-per certificate in a virtual hosting environment (multiple domains per server) to a load balanced environment with one IP for all domains.

We looked at our Analytics (over 1 million unique visitors / month), which is mostly North American male users looking to buy auto parts online, and found on March 8th, 2014 that approximately 4 % of users were on Windows XP using Internet Explorer (others were minor -- worst case 4.5 % of total users would be affected by not supporting SNI). Keep in mind that we have no "control" over these users so we can't tell them to switch browsers. This percentage is also dropping fairly quickly, at least in the US.

We first decided that it was "OK" for non SNI customers to have a somewhat different experience than customers supporting SNI.

Our approach was to detect server-side (using UA string) which browser/operating system combination does not support SNI (as other people mentioned: Wikipedia article on SNI support). All our domains (~ 120) would have an A record pointing to a single load-balanced IP. We had a second IP (also load balanced) for a domain we can call generic-autoparts.com.

So the setup is [I'm not associated with any domains I use as examples below]:

mikesautoparts.com --> A Nameserver Record of IP X
dansautoparts.com --> A Nameserver Record of IP X
jensautoparts.com --> A Nameserver Record of IP X
... etc

generic-autoparts.com --> A Nameserver Record of IP Y

If a customer hits http://www.dansautoparts.com, and supports SNI, nothing happens. He browses dansautoparts.com, and when it comes time to check out, he uses https://www.dansautoparts.com.

If a customer hits http://www.dansautoparts.com, and we detect that he does not support SNI, we immediately redirect the customer to http://generic-autoparts.com/dansautoparts.com. He shops on there, and at checkout he uses https://generic-autoparts.com/dansautoparts.com

Now, if a customer hits https://www.dansautoparts.com DIRECTLY (link in e-mail, indexed page in search engines), you are out of luck. They'll get a nasty certificate error. In our case, we made sure all e-mails our system sent didn't use https, and we knew that search engines had not indexed our https pages.

Each environment has different challenges and potential trade-offs. We found that this worked well in our case and customers would "accept" (or not notice) getting redirected to http://generic-autoparts.com/[ORIGINAL DOMAIN].com . We also kept checkout secure through generic-autoparts.com.

Let's say 20 % of nonSNI users notice the redirect, it seems fishy, and they leave. In our case, that's 0.8 - 0.9 % (based on March 8th, 2014 numbers) of users and we were willing to "live" with that. I don't have specific data on this right now, but overall sales held steady. [EDIT 3/28/2014: We saw no impact to sales after we switched 100 % of our customers]

Implementation Update July 8th, 2014

Turns out that it's impossible to detect every UA Agent string statically on the server. We implemented the following JavaScript to detect the browser's SNI capability. The general approach is to do a JSONP request against a domain that requires SNI (Apache supports this through "SSLStrictSNIVHostCheck on"). If the JSONP request fails by timing out, we redirect the customer to the nonSNI domain.

To further complicate matters, we do not want to redirect everyone just because the SNI_TEST_DOMAIN is down. If the JSONP request fails (by timing out since there's no way to detect a JSONP failure directly), we verify that the server is available by doing an HTTP "health-check" request. In addition, we do not want to run this javascript code on every page load, since that increases the chance of some strange timeout and incorrectly redirecting many customers, so we set a session variable once the SNI check is done so it won't happen again as the customer navigates the sites.

We know that we get certain false checks that fails due to the JSONP timeout being unreliable, but since implementing this we are getting no complaints from customers.

var redirect='http://REPLACE_WITH_NON_SNI_URL';  var sni_https_timeout, sni_http_timeout; var https_req = $.ajax({     url : 'https://SNI_TEST_DOMAIN.com/snitest.php',     dataType : "jsonp", }).done(function() {         window.clearTimeout(sni_https_timeout);         var request = $.ajax({         url: "index.php?ua=sni_check_done",        type: "POST"     }); })  sni_https_timeout = window.setTimeout(function() {     var http_req = $.ajax({         url : 'http://SNI_TEST_DOMAIN/sni_healthcheck.php',         dataType : "jsonp"     }).done(function()         {             window.clearTimeout(sni_http_timeout);             window.setTimeout(function()             {                 window.location = redirect;             },         200);     });      sni_http_timeout = window.setTimeout(function() { sni_http_fail(); }, 8000);  }, 8000);  function sni_http_fail() {     var request = $.ajax({         url: "index.php?ua=sni_check_done",         type: "POST"     }); } 

snitest.php / sni_healthcheck.php:

<?php if (array_key_exists('callback', $_GET)) {     header( 'Content-type: application/javascript' );     echo "{$_GET['callback']}();\n"; } 
like image 81
ronneseth Avatar answered Sep 22 '22 08:09

ronneseth