/ Guides

Setting up a .onion website with nginx and CentOS 7

If you’re running a website on your own server (like I do) then it is often fun to experiment and tweak with the configuration. My latest tweak was to enable this website to be accessible via Tor using the address http://bvlepedbau5ihwu3.onion (That link obviously won’t work if you’re not connected to Tor at the moment).

This blog is going to describe the steps I took to configure this site to be accessible via Tor on a .onion address using nginx on CentOS 7. I am assuming you already have a functional website setup and working so won’t be going over the installation of nginx itself.

Sudo to root

You’ll need to have root access to do most of these steps so either switch to root or use sudo.

sudo -s

Install Tor

The first step to making a site accessible via Tor is to connect your server to the Tor network.

First step, add the Tor repository to your server by creating a new repo file.

vi /etc/yum.repos.d/tor.repo{% endhighlight %}

Paste the following repository information into the newly created file.

[tor]
name=Tor repo
enabled=1
baseurl=https://deb.torproject.org/torproject.org/rpm/el/7/$basearch/
gpgcheck=1
gpgkey=https://deb.torproject.org/torproject.org/rpm/RPM-GPG-KEY-torproject.org.asc
repo_gpgcheck=1

[tor-source]
name=Tor source repo
enabled=1
autorefresh=0
baseurl=https://deb.torproject.org/torproject.org/rpm/el/7/SRPMS
gpgcheck=1
gpgkey=https://deb.torproject.org/torproject.org/rpm/RPM-GPG-KEY-torproject.org.asc
repo_gpgcheck=1

To make sure we don’t get a conflict with Tor packages in the EPEL repo add the following line to the [epel] section of /etc/yum.repos.d/epel.repo

Exclude=tor

Now refresh your package information.

yum makecache

Finally, install Tor and allow it to install any dependancies it has.

yum install tor

Configure Tor hidden service

Now Tor is installed we need to configure a hidden service. Open the configuration file for Tor

vi /etc/tor/torrc

And add the following line to enable a hidden service adjusting the values for your website,

HiddenServiceDir /var/lib/tor/kieromi_uk/
HiddenServicePort 80 127.0.0.1:9090

The first value defines where the data about the service will be stored, leave the path the same but adjust the last directory name for your website.

The second line defines the listening port and destination address and port, we want port 80 as it’s a website we’re setting up, and we then forward that to local host (127.0.0.1) on port 9090. We’ll configure nginx later on to listen on port 9090 to serve up website files, in essence we are port mapping port 80 on Tor to port 9090 on local host.

Start Tor and find out the .onion hostname

Now the configuration is done, start Tor

service tor start

Assuming it starts properly, now open up the hostname file in the directory you specified for HiddenServiceDir in the torrc file.

cat /var/lib/tor/kieromi_uk/hostname

The output is the randomly generated Onion hostname of your Tor hidden service. Publish it wherever you like for the whole world to see.

NEVER publish the private_key file (Obviously).

Configure nginx

Next step is to configure nginx to listen on the port we choose in the last step and serve up the website.

In my configuration I have a server definition for kieromi.uk listening on port 80 that redirects to another server definition listening on port 443 and serving up securely via SSL/TLS and HTTP2.

We don’t need to use SSL for Tor so let’s add a new server definition listening on port 9090 but using the same web root as the port 443 definition.

server {
    listen 127.0.0.1:9090;
    root /srv/www/kieromi.uk;
    index index.html index.htm;
    charset utf-8;
}

Naturally the exact config will vary depending on your website.

If you were hosting multiple sites you could use name based options and specify in the nginx configuration a server_name configuration thus:

server_name  bvlepedbau5ihwu3.onion;

It would probably be as easy to simply use different ports for each hidden service and not use name based configurations though.

Finally restart nginx.

service restart nginx

Huzzah!

You’re done, open up your Tor browser and try it out! With a bit of luck the site loads and you’re open for business from all those secretive Tor user types ;)

Why a separate server configuration?

You don’t necessarily need a separate server configuration, you could setup the hidden service to point to port 80 on localhost and add the .onion address to the server_name configuration so it looks something like this:

server_name  kieromi.uk, www.kieromi.uk, bvlepedbau5ihwu3.onion;

I choose not to do this though, my port 80 HTTP configuration redirects to port 443 so the website can be served securely with HTTPS. And I wouldn’t want the Tor service to load the secure server definition on port 443 because my SSL certificate would not match the .onion hostname and would generate browser errors for invalid certificates. So I have a non-HTTPS configuration on port 9090 just for Tor.

Unfortunately it isn’t possible to get an SSL certificate that a browser will trust for a .onion address, plus you don’t need SSL on Tor as it is already secure by it’s very nature.

Final remarks

My only remaining feature I’d like to do is to be able to redirect Tor users to the hidden service when they browse to the regular website URL. In theory this should be possible as all Tor exit node IPs are known and published so I should be able to detect visitors from those Tor exit nodes and redirect them to the .onion equivalent address thus keeping their traffic within Tor. Once I work that out I will publish another blog.