The anti-censorship team at TunnelBear is excited to share some of the work we've been doing to combat internet censorship around the world. Over the last several months, we've been busy building support for the Encrypted Server Name Indicator (ESNI) TLS extension into our Android application. In this post we'll explore why ESNI is a crucial component of internet privacy going forward, how we built it into our Android app, and how it's helping our users suffering from censorship get access to an open internet.
The next frontier in online privacy
First, a bit of background on what happens when you click the connect button in your TunnelBear client.
In order to establish a VPN connection to one of our VPN servers, your TunnelBear client needs to know the IP address of the VPN server. To find out which server it should connect to, the client sends an HTTPS request to api.tunnelbear.com, requesting a list of servers and their IP addresses. Most of the time, this works just fine. But what happens when api.tunnelbear.com is being censored on your network?
Most censorship regimes are targeted, and only want to block certain content while allowing other content that they deem acceptable. For this type of system to work, they need to be able to determine what sort of content is contained in an online request, something which has become much harder as more and more internet traffic is encrypted by TLS. With TLS 1.3, all of the contents and most of the metadata of each request is encrypted, but there are still some fields left unencrypted. These unencrypted fields can be read by a censor and then used to justify blocking a request. One of these unencrypted fields commonly used for blocking is the Server Name Indicator (SNI) extension.
What is SNI?
So what is SNI and why do we need it if it can be used to facilitate censorship?
Many websites and services on the internet today are hosted in a shared environment, such as CloudFlare for example. Instead of every CloudFlare hosted server having its own public IP address, the servers are accessed through a smaller number of shared IPs owned by CloudFlare, which then routes requests over its own network to the appropriate server. In other words, SNI allows a single server to host multiple HTTPS websites. That said, an SNI field is unencrypted and therefore a censorship threat as this allows censors to track your online history.
The goal of ESNI is to provide a means of encrypting the SNI field such that it can't be read by a censor or other third party, but can still be used to facilitate shared hosting.
How we did this
We knew implementing ESNI would be a big project, so we wanted to run a smaller scale test first to gauge its effectiveness. Our experiment consisted of sending three test requests from our Android app on each launch: one standard API request with no censorship circumvention methods applied, one request using our existing circumvention methods, and one request using ESNI. We used a fork of OpenSSL developed by the DEfO project (Developing ESNI for OpenSSL) to make the ESNI requests. We generated a unique ID for each set of test requests so we could see which ones from each set succeed in making it to our servers, and from there we compared how effective each method is relative to the others.
The experiment was a success and showed us that for a significant portion of users, ESNI can provide a more reliable way to access our API.
The test also highlighted some device-compatibility issues with using the DEfO OpenSSL fork, because we started seeing an increase in the crash rate on certain devices. Once we determined that ESNI could help with our anti-censorship efforts, we removed the test code to minimize the impact on our users.
With the concept proven, we moved on to the next stage: supporting ESNI for every network request in the app. ESNI is still in the early stages and the Internet Engineering Task Force (IETF) has yet to finalize its specification, so very few networking libraries support it. Mozilla has built support for it into their Network Security Services (NSS) library, but since NSS only deals with low-level networking protocols, we would have had to build a separate HTTP library on top for use in our app. Instead, we decided to look at the options for updating our current HTTP library, OkHttp, to send ESNI requests. OkHttp supports multiple security providers, and after evaluating the options we decided to modify Google's Conscrypt and BoringSSL libraries to add support for ESNI.
We've made our changes open source, and hope to have our changes accepted into both libraries to make it easier for other developers to start using ESNI.
The importance of wide-scale adoption
For ESNI to be effective, it needs wide-scale adoption. While a censor can't see what site you're connecting to with ESNI enabled, they can still tell that you're using an encrypted SNI field. If TunnelBear and other anti-censorship tools are the only applications that use ESNI, it's pretty easy for a censor to assume that any traffic using ESNI is attempting to circumvent their system and should be blocked.
Unfortunately, this has already happened in mainland China, where censors are actively blocking ESNI traffic, further solidifying the need for wider adoption in other countries.
For this to work on a large scale, a big portion of internet traffic needs to be using ESNI so that TunnelBear traffic blends in. It's similar to the early days of HTTPS, where many networks that wanted to read your traffic would simply block HTTPS. That strategy becomes less and less practical as adoption increases and it starts to break more and more websites that people rely on. To help other apps easily add support for ESNI, we're open-sourcing our work that adds ESNI support to OkHttp.
You can also help speed up adoption by enabling ESNI in Firefox (instructions here). The more people that use ESNI regularly, the more effective it will be at defeating censorship and building a democratic internet for all. We hope that by adding support for ESNI into BoringSSL we can also speed up the addition of ESNI to Chromium.
What this means for censored users
ESNI alone won't prevent all censorship, but it will make it easier for users experiencing censorship to connect to TunnelBear. In our testing, we've found that results vary by ISP but ESNI is typically about the same or slightly less effective than our existing techniques for evading censorship. The more important finding however is that for approximately 25% of censored users, ESNI works when our other anti-censorship techniques fail.
It's important to note that there is no single tool that can completely evade censorship, but by skillfully combining different tools to suit the situation, we think we can come pretty close. ESNI gives us another tool we can leverage to defeat censorship.