nginx & Tor

What follows is a blow-by-blow guide for configuring a UNIX home computer (as a webserver) to host a site permanently on a hidden slice of the internet, frequently referred to as: "the darknet".

  1. Background
  2. nginx
  3. Tor
  4. Shallot

Background

In the headlines (Oct 2013), the owners of the "The Silk Road" (a site which facilitated drug transactions) and "Freedom Hosting" (a webhoster) were arrested and their servers seized. The Feds boast to have knocked 1/2 of all darknet sites out of commission by taking-down "Freedom Hosting".

Tor assigns sites on the darknet the .onion pseudo TLD (Top Level Domain), and they are accessed with the Tor Browser Bundle (or a non-Tor browser configured for a Tor proxy). In a regular browser - when an .onion link is clicked, a "Server not found" error is displayed. Many of these onionland sites remind me of the old (early 1990s) "underground" internet, but some are extremely disturbing: "Buy counterfeit currency", "Hire a hit man", kiddie porn, etc.

Perhaps, this is the time to colonize the darknet for good rather than silly or just plain evil?

Tor was designed to provide anonymity, i.e. to conceal a user's public IP address. Like any technology, a hidden internet can be used for beneficial or destructive ends. Dissidents from China and Iran employ it to evade censorship - or jail. Now, a number of US journalists avail themselves of it to avoid being surveilled or slapped with FISA warrants by Uncle Sam. On my onion site, I host a political blog, computer writings and onion links to freedom of (political) speech sites. Arguably - with nginx (pronounced Engine X) and Tor around, no one with a fat, broadband pipe to the internet (and a modicum of patience) needs to shell-out cash for an account at a webhosting service.

One question frequently asked is: "If IPs, assigned by a user's ISP, regularly change, how can an onion domain, hosted on the computer, continue to resolve to THAT computer?". For access to the darknet, clients and servers enter the Tor proxy, and the IP of 127.0.0.1 is attached to both devices. Tor performs name resolution for onion domains, based on the exchange of public keys - not public nameservers. Unlike DNS, an IP and a hostname are not bound-together. A server, assigned an onion domain by Tor, remains permanently associated with it, provided that the same private key is present. Onion domains resolve to the computers hosting them for clients on the Tor network - but only after a series of complicated, network negotiations is performed.

nginx

Grab the sources for nginx. The latest stable release is recommended: http://nginx.org/download. Download the sources with wget (or use a browser), then extract them.

$ cd ~/

$ wget http://nginx.org/download/nginx-1.X.X.tar.gz

$ tar xzvf nginx-1.X.X.tar.gz

Move to the nginx source directory.

$ cd ~/nginx-1.X.X

Create a minimal "config.sh" script. The use of this script will facilitate upgrades (and/or the addition of compile options) at a later date. In a text editor, add the following:

./configure \
"--prefix=$HOME/nginx" \
"--user=$USER" \
"--without-http_rewrite_module"

note
The "--prefix=$HOME/nginx" option installs nginx under your UNIX account - rather than system-wide. "--without-http_rewrite_module" prevents the rewrite engine from being built. To build a functional rewrite, install libpcre from the package manager (or the ports collection) of your operating system and remove "--without-http_rewrite_module" from the config.sh.

Run the config script.

$ sh config.sh

Build and install nginx.

$ make

$ make install

note
To accelerate building nginx - on a machine with multiple processors or cores, "make -j9" will compile 9 threads simultaneously.


Configure nginx for run-time

In a text-editor, open up ~/nginx/conf/nginx.conf. To execute nginx - as a non-root user, the webserver needs to run on 127.0.0.1 (localhost), bound to a non-privileged port - typically 8080. However, any un-used, non-privileged port will work. Search for the "server {...}" block, and add the bolded entry below.

worker_processes 1;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;
charset utf-8;
index index.html;

log_format main '$remote_addr $host $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log logs/access.log main;
error_log logs/error.log;
error_page 500 502 503 504;
sendfile on;
keepalive_timeout 60s;
server_tokens off;
etag off;

server {
listen 127.0.0.1:8080;
server_name localhost;
root html/;
}
}


Execute nginx

$ ~/nginx/sbin/nginx

To pull-up the verification message: "Welcome to nginx!", click http://127.0.0.1:8080. Place the webcontent (html, images, audio and video files, etc.) that you wish to serve into ~/nginx/html.

Tor

Since onion domains are not resolvable by internet nameservers, installing Tor is required to generate a private key, write an onion hostname and help kick-off the process of name resolution.

Grab and unpack the sources for the standalone version of Tor. The latest stable release is advised. https://www.torproject.org/download/download.html

$ wget https://www.torproject.org/dist/tor-0.2.X.X-rc.tar.gz

$ tar xzvf tor-0.2.X.X-rc.tar.gz

$ cd tor-0.2.X.X


Configure, compile and install Tor

note
Verify that $HOME/bin exists and that it's in your $PATH statement.

$ ./configure --prefix="$HOME/tor" --exec-prefix="$HOME"

$ make

$ make install

note
To build Tor without the man pages, add "--disable-asciidoc" to the configure options above.

Create a directory to hold the new, onion hostname and private key, and copy the torrc.sample to ~/.torrc.

$ mkdir -p ~/tor/var/lib/tor/hidden_service

$ cp ~/tor/etc/tor/torrc.sample ~/.torrc

Open up ~/.torrc in a text editor and copy the following to it, but substitute your own UNIX username for "username", below.

HiddenServiceDir /home/username/tor/var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:8080


Execute tor

$ ~/bin/tor

The new onion hostname is located in ~/tor/var/lib/tor/hidden_service as "hostname" along with a "private_key". Open the file "hostname":

$ cat ~/tor/var/lib/tor/hidden_service/hostname

To bring-up the new site, copy and paste the onion hostname into the address bar of the Tor browser. The site is now available to clients of the Tor network. It would be best to backup the private key and store it elsewhere. In case of a disk crash - without any backup, a new key will be generated when Tor is re-started, and a different hostname assigned.

notes
You may copy and paste your onion hostname as the value of the "server_name" Directive in ~/nginx/conf/nginx.conf. Above, replace "localhost" with the new, onion hostname. To initialize both nginx and Tor at boot, add the following cronjob with "crontab -e".

@reboot $HOME/nginx/sbin/nginx
@reboot $HOME/bin/tor

Finally, here's a strong piece of advice: A computer that remains connected to the internet 24/7 is strongly encouraged. Should the computer hosting the onion domain go offline for an extended period of time - list sites and search engines will remove their links to it, and the site will receive few hits.

Custom hostnames

The onion hostnames generated by Tor are "opaque, non-mnemonic, 16-character alpha-semi-numeric hashes", i.e. a random-slaw of letters and numbers. However - with shallot, it's possible to create a semi-customized hostname, but only a part of the address (the first part) is practical to customize.

Download shallot, compile it then run it to create the first part of the hostname as "kheper".

$ wget https://github.com/katmagic/Shallot/archive/master.zip

$ unzip Shallot-master.zip

$ cd Shallot-master

$ ./configure

$ make

$ ./shallot ^kheper

Copy and paste the entirety of the RSA key spit-out from shallot to STDOUT into a new file named "private_key". Once the "private_key" is copied to $HOME/tor/var/lib/tor/hidden_service and tor restarted, a new, onion hostname will appear in $HOME/tor/var/lib/tor/hidden_service/hostname.