Securing Services with Tor and alt-svc — Jonah

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

This is a companion discussion topic for the original entry at

Check out my latest blog post, it’s a guide on how exactly to setup the Tor alt-svc system we use for our own services :smile:

Also, we’ve implemented Tor support with this method on almost every service (every one except this forum, funnily enough)! We’ll get this forum online later tonight, it’s just a bit more complicated with how Discourse uses Docker to handle everything.


Thank you for the guide :purple_heart:, it looks a lot more easy than I thought. However I have to criticize and ask something:

  • Setting up a hidden service - I think this should link to the official instructions at least for installing to not instruct people to just copy-paste commands from a third party place in case that would cause them to run malicious instructions later.
  • Adding headers - I thought that you have to compare whether the visitor is a Tor exit node before showing them the alt-svc header or you would send <average> browser users to .onion and cause errors to them as they don’t know how to resolve onions?

It did.

Maybe this would be cleaner, but it adds a lot of complexity. Browsers disregard alternative services they can’t reach so the header simply has no effect outside Tor-enabled browsers.


I am talking about this part, I don’t think it should be outside of Tor Project. And now I also notice that you tell people to edit sources.list while they should edit /etc/apt/sources.list.d/torproject.list or whatever under sources.list.d.

There is also no explanation that you are running Ubuntu Bionic or mentioning of lsb_release -sc.

Oh, that is good to hearr, having to compare to Tor exit node lists might have made me never think of doing alt-svc.

1 Like

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!

I thought of another method:

└┌(%:~)┌- HEAD
200 OK
Cache-Control: max-age=0, private, must-revalidate
Connection: close
Date: Tue, 07 May 2019 10:11:33 GMT
ETag: W/"985d48b30bca4f3369161b9b6cc22005"
Server: Mastodon
Vary: Accept-Encoding
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Alt-Svc: h2="2tjcxjzxgql6wilo3bu777pkvigx2wqwauxf7lyvvmsotjgrqiwwg7id.onion:443"; ma=86400; persist=1
Client-Date: Tue, 07 May 2019 10:11:33 GMT
Client-Response-Num: 1
Client-SSL-Cert-Issuer: /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
Client-SSL-Cert-Subject: /
Client-SSL-Cipher: ECDHE-RSA-AES256-GCM-SHA384
Client-SSL-Socket-Class: IO::Socket::SSL
Content-Security-Policy: base-uri 'none'; default-src 'none'; frame-ancestors 'none'; font-src 'self'; img-src 'self' https: data: blob:; style-src 'self' 'unsafe-inline'; media-src 'self' https: data:; frame-src 'self' https:; manifest-src 'self'; connect-src 'self' blob: wss://; script-src 'self'
Set-Cookie: _mastodon_session=IPoH9WIZySDhz6Q00lMYK06iHIkLbLE2JPUOcyMi7Z1QKNxjMsv%2FtRM%2F849RfKSVzaNHHGV0oP6gyzWP00kzgkrq2zUojEdG7tsrKVhVL8OEpTxYjpMY%2BGHFisIjVzd3UITS60jrNZdLyo4t9qx3tMgYIYkgb%2FqAsoloUGvAryswzTqwNH02Hw%3D%3D--Q6uvrhFLT5kiMMPQ--FCW6ovsCxqx%2FcoONnvc%2FaA%3D%3D; path=/; secure; HttpOnly
Strict-Transport-Security: max-age=31536000
X-Cached: MISS
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Request-Id: bf637aaf-8e7b-491b-820e-4ecafc54d824
X-Runtime: 0.043703
X-XSS-Protection: 1; mode=block

And I was going to ask you if you see traffic from, because I am uanble to get it working, but then I thought of running HEAD|grep Alt-Svc for both which tells me that my onion is missing the port, so maybe I will have a better luck now.

HEAD is in Debian package libwww-perl by the way.

good catch. I kept looking at that area thinking something amiss with the instruction. Yes, the repo should go under sources.list.d

also isn’t “apt-key add” not preferred? reference this stackexchange question when I was searching for infos similar (also first comment points to possible duplicate question of which that top answer has some good discussion about why sources.list.d

I think the current instruction is more secure as keyservers cannot be trusted and even if somehow wrong key was somehow MITMed, it would still need to have the correct fingerprint before being added into apt keyring.

I didn’t read the StackExchange links yet, I am feeling a bit low energy at the moment.

get some rest! lol

and pay no mind to the stackexchange links, I included them for a good recently read answer/discussion about using sources.list.d instead of sources.list in case benefits of doing so needed justifying.

Thanks for that bitbucket link! I need see good infos like that in counterpoint to some method I’m try to convince self is better/best practice :blush:

1 Like