Securing Services with Tor and alt-svc

Jonah Aragon
May 6, 2019 · 6 min read

Some people called for me to write a more technically detailed/in-depth guide to setting up Tor with alt-svc after we set it up on, so while I do it all over again on our Mastodon server, I figured I’d write this post! Plus, it’ll make it easier for me if I need to do this again in the future :)

When Cloudflare introduced their Onion Service last year, it marked an important milestone in Tor adoption and connectivity. Not only did they add Tor support to nearly all their websites, which will certainly help with reducing the number of captchas seen by Tor users across the internet, it introduced a new and very interesting way to handle Tor traffic.

What we’re doing here is reimplementing Cloudflare’s setup on our own machines. The websites and services are now Tor-enabled completely transparently to all users using the Tor browser, because of an HTTP header called alt-svc.

What is alt-svc?

alt-svc is a HTTP header that allows your server to inform a web browser about alternative ways to reach your website. Initially it was developed for SPDY and now QUIC support for websites in browsers that support it, but now we can use it to tell browsers (the Tor Browser specifically) that our site is available at an .onion domain rather than a clearnet IP address.

What this means is when you connect to in your Tor browser, instead of your computer running a DNS lookup and making TCP requests to, it will see that a .onion connection is available and make TCP requests to privacy2zbidut4m4jyj3ksdqidzkw3uoip2vhvhbvwxbqux5xy5obyd.onion:443 instead, completely transparently and keeping the hostname identical!

This is highly beneficial for server administrators for the following reasons:

  1. The domain name stays the same. Instead of adding a .onion domain to Nginx, we're sending all requests using the same hostname. If you're familiar with the OSI 7 layer model, we're replacing the Transport (layer 4) TCP layer with a .onion connection while not touching anything on the Application layer (layer 7).
  2. It requires no special webserver configuration. Because the hostname stays the same, requests will reach your webserver with the same Host header. To Nginx and your web application, it should appear the same as a normal connection.

Because of this, using alt-svc is a drop-in replacement for TCP connections and should be able to be implemented on any web application stack without making any modifications to your code. All you need is Tor installed, and a single header added to Nginx.

Using alt-svc headers is not necessarily a replacement for .onion domains. It's an opportunistic use of the Tor network, not enforced. Some downsides to keep in mind:

  1. Initial connections will go through an exit node! The Tor Browser won’t know about your .onion address until it connects to the site for the first time.
  2. It isn’t quite 100% supported. It is supported in Tor Browser 8.0 and Tor Browser for Android, but not necessarily anything else. It’s an HTTP header, so it won’t work for other protocols.
  3. There’s (currently) no visual indicators a connection is secure. This is an open issue (#27590) so I hope it will be fixed soon, but currently it just appears as if you’re connecting via an exit node.

The first point is probably going to be the most concerning for most service hosters. We decided that for our purposes this didn’t matter that much: We currently host all our services in the clearnet anyways, we enforce HTTPS use for End-to-End Encryption, and we don’t need to hide ourselves. Using alt-svc is just added security for Tor users, and it functioning essentially transparently means that people don't need to change their current behaviors when visiting our websites. We're also willing to wait for visual indicators to be implemented in the browser.

If you need all your users to connect via the Tor network, or if visual security is important to your services/industry/etc, you do need to host your services on an .onion domain directly, no way around it for the moment (until perhaps alt-svc is implemented in DNS and there’s a way to enforce its use).

First thing’s first, we need to actually install Tor. I’m going to be installing Tor on Ubuntu 18.04 for the following steps. But you should consult the latest Tor instructions to make sure you’re doing things however they currently want you to, or to find guides for your own platform.

If you don’t have it installed already, install apt-transport-https:

This will allow your package manager to access all metadata and packages over HTTPS when using apt.

Now we’ll need to add the official Tor browser sources. Open /etc/apt/sources.list with your favorite editor and add the following lines to the end:

Then, add their signing key:

Now, update your packages:

Finally, we’ll install tor. We'll also install, which keeps the signing key up to date, which the Tor project recommends:

Now we can setup our .onion domain. Open /etc/tor/torrc and add the following setting:

Then, find the # This section is just for location-hidden services section and add the following configuration:

SocksPort 0 disables the socks proxy, which we don't need since we're only functioning as a service.

HiddenServiceDir /var/lib/tor/service1/ is the directory that will store our private keys, and should not be publicly accessible. It is not your web root.

HiddenServiceVersion 3 enables the new v3 onion addresses, which are more secure and longer than v2 addresses.

HiddenServicePort 443 redirects traffic to youronion[...]domain.onion:443 to, which should be your webserver. You can point this IP to another server on your LAN as necessary, or add similar lines for other ports you want to host.

HiddenServiceSingleHopMode 1 is used to optimize latency a bit. It removes two hops in the Tor circuit by moving your server closer to the "rendezvous point".

HiddenServiceNonAnonymousMode 1 is enabled because of the last setting. Removing the two hops in the circuit decreases the anonymity of your server significantly, but has no effect on the security or anonymity of your users!

The last two options are enabled because we’re assuming you’re not really running an anonymous service, rather just want to add additional security to an existing clearnet service. In that situation, trading the anonymity of your server for increased performance makes sense, but you can omit those two lines if that’s a concern for you.

SafeLogging 1 further prevents potentially sensitive information from being leaked to logs.

Now we can save the torrc file and restart Tor:

Sidenote: if you’re running Tor in an LXC container, sometimes it doesn’t start correctly, but there’s a workaround. For most people this won’t matter, but I use LXC containers heavily so this would’ve saved me a good hour of research.

You can find your hostname at /var/lib/tor/service1/hostname:

And that address should be accepting traffic on port 443. The important thing to remember is, your users will never need to use or know this address! This entire process is transparent to your users.

To enable traffic on this address, we just need to add an alt-svc header formatted like this:

Of course, replace 2tjcxjzxgql6wilo3bu777pkvigx2wqwauxf7lyvvmsotjgrqiwwg7id.onion with your own hostname.

The field “ma” (max-age) indicates how long in seconds the client should remember the existence of the alternative service and “persist” indicates whether alternative service cache should be cleared when the network is interrupted.

To add this header in Nginx, add the following to your server { ... } block:

For other webservers, consult their instructions for adding HTTP headers.

Confirm your Nginx configuration is correct:

…and reload your webserver!

Now if you view the headers of your site (using Inspect Element or a service like, you should see your alt-svc service listed, and you're good to go!


Unfortunately there’s no easy way to definitively tell if it’s working at the time of writing. alt-svc support is very new to the Tor network, but it's making great progress.

This isn’t a suitable replacement for actual hidden services, but if you operate a clearnet website, this is a great way to help speed up your site for Tor users and reduce load on the exit nodes in the network.

Almost every service is using this method already, I hope this inspires you to convert your own clearnet websites to Tor compatible ones!

Discuss this post on Privacy Forum!

Originally published at on May 6, 2019.


You are being watched,

Jonah Aragon

Written by

I’m an Apple IT professional and online privacy researcher from Minnesota. Featured in Hacker Noon, Medium, PrivacyTools.


You are being watched, provides services, tools and knowledge to protect your privacy against global mass surveillance. We are mostly syndicating interesting content from and here.

Jonah Aragon

Written by

I’m an Apple IT professional and online privacy researcher from Minnesota. Featured in Hacker Noon, Medium, PrivacyTools.


You are being watched, provides services, tools and knowledge to protect your privacy against global mass surveillance. We are mostly syndicating interesting content from and here.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store