I recently started running a Tor Relay on my Raspberry Pi II, so I thought it would be a good idea to write a tutorial on how to safely configure Tor as a relay. For this tutorial you will need to following tools:

  • A Raspberry Pi running Minibian (other Raspberry Pi Debian version should work too).
  • Internet connection (make sure you are free of firewall, I won’t be covering how to bypass your local firewall).

In this tutorial, I will cover how to set a chroot for safely running a Tor relay and how to configure Tor as a relay.

Caution: Before proceeding, make sure you are aware of the risks when running a Tor relay and be sure you are allowed to run one. Depending on your country, ISP or personal reasons you should not be running one, however, I personally recommend running a relay, because lots of people really depend on it, and it’s a nice deed.

Creating and configuring our chroot environment.

Note: If you don’t want to wait for the whole installation, you can grab a copy of my chroot here (shasum 256: 085869680d699ad893e60001fd72562d05f276d3136c109f99cfe912247460b0) and extract it to /srv/chroot-tor.

First of all, let’s make sure our clock, date and timezone are set correctly. For this, we will be using ntp;

$ apt-get install ntp

You will need to edit /etc/ntp.conf and set the correct pool zone for your country. You can get a list of the pool zones here.

Run vim /etc/ntp.conf, search for the default pools and replace them with the pools you got from the previous link. Save it and restart ntp’s daemon; service ntp restart

Next, let’s install the required packages to create our chroot environment.

$ apt-get update
$ apt-get install debootstrap

Create the chroot directory for our chroot environment and run debootstrap using the minbase variant and raspbian’s archive.

$ cd /srv/
$ mkdir chroot-tor
$ debootstrap --variant=minbase jessie ./chroot-tor http://archive.raspbian.org/raspbian/

(This might take a while)

When finished, let’s tell fstab to automatically mount (on boot) /dev/random and /dev/null to our new chroot environment;

$ export MY_CHROOT=/srv/chroot-tor
$ echo "proc $MY_CHROOT/proc proc defaults 0 0" >> /etc/fstab
$ mount proc $MY_CHROOT/proc -t proc
$ echo "sysfs $MY_CHROOT/sys sysfs defaults 0 0" >> /etc/fstab
$ mount sysfs $MY_CHROOT/sys -t sysfs

Let’s copy the required files and chroot.

$ cp /etc/hosts $MY_CHROOT/etc/hosts
$ cp /proc/mounts $MY_CHROOT/etc/mtab
$ chroot $MY_CHROOT /bin/bash

We now have our chroot environment fully running.

Installing and configuring Tor

Inside your chroot, run;

$ apt-get update
$ apt-get install tor

Create a Tor user; adduser --disabled-login --gecos "Tor user,,," tor

In /etc/tor/torrc at the following configuration at the end of the file (make sure you change Nickname and Contactinfo);

User tor
DataDirectory /var/lib/tor2
GeoIPFile /tor/share/tor/geoip
RunAsDaemon 1

ORPort 443
Exitpolicy reject *:*
Nickname <your nickname>
ContactInfo foo@somewhere.com

Create the following directories;

$ mkdir -p /var/run/tor
$ mkdir -p /var/lib/tor
$ mkdir -p /var/lib/tor2
$ mkdir -p /var/log/tor

Change the owner of the previous created directory;

$ chown tor:tor /var/run/tor
$ chown tor:tor /var/lib/tor
$ chown tor:tor /var/lib/tor2
$ chown tor:tor /var/log/tor

Restart Tor’s service with; service tor restart. You can check the logs if everything is going well using; tailf /var/log/tor/log

Starting Tor on boot

Save the following script to /etc/init.d/tor to the main system;

#! /bin/sh

# Modification to Peter Palfrader's Debian Tor init script
#  by Steven J. Murdoch (http://www.cl.cam.ac.uk/users/sjm217/)

set -e

TORCHROOT=/srv/chroot-tor

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=$TORCHROOT/usr/bin/tor-chroot
EXECDAEMON=$TORCHROOT/tor/bin/tor
NAME=tor
DESC="tor daemon"
#TORLOG=$TORCHROOT/var/log/tor/log
TORPID=$TORCHROOT/var/run/tor/tor.pid
RUNTORLOG=/var/log/tor/log
RUNTORPID=/var/run/tor/tor.pid
DEFAULTSFILE=/etc/default/$NAME
WAITFORDAEMON=10
ARGS=""

test -x $DAEMON || exit 0

# Include tor defaults if available
if [ -f $DEFAULTSFILE ] ; then
    . $DEFAULTSFILE
fi

wait_for_deaddaemon () {
    pid=$1
    sleep 1
    if test -n "$pid"
    then
        if kill -0 $pid 2>/dev/null
        then
            echo -n "."
            cnt=0
            while kill -0 $pid 2>/dev/null
            do
                cnt=`expr $cnt + 1`
                if [ $cnt -gt $WAITFORDAEMON ]
                then
                    echo " FAILED."
                    return 1
                fi
                sleep 1
                echo -n "."
            done
        fi
    fi
    return 0
}

case "$1" in
  start)
    if [ "$RUN_DAEMON" != "yes" ]; then
        echo "Not starting $DESC (Disabled in $DEFAULTSFILE)."
    else
        echo -n "Starting $DESC: "
        start-stop-daemon --start --quiet --oknodo \
            --pidfile $TORPID \
            --exec $DAEMON -- $ARGS
        echo "$NAME."
    fi
    ;;
  stop)
    echo -n "Stopping $DESC: "
    pid=`cat $TORPID 2>/dev/null` || true
    if test ! -f $TORPID -o -z "$pid"
    then
        echo "not running (there is no $TORPID)."
    elif start-stop-daemon --stop --quiet --pidfile $TORPID --exec $EXECDAEMON
    then
        wait_for_deaddaemon $pid
        echo "$NAME."
    elif kill -0 $pid 2>/dev/null
    then
        echo "FAILED (Is $pid not $NAME?  Is $EXECDAEMON a different binary now?)."
    else
        echo "FAILED ($DAEMON died: process $pid not running; or permission denied)."
    fi
    ;;
  reload|force-reload)
    echo -n "Reloading $DESC configuration: "
    pid=`cat $TORPID 2>/dev/null` || true
    if test ! -f $TORPID -o -z "$pid"
    then
        echo "not running (there is no $TORPID)."
    elif start-stop-daemon --stop --signal 1 --quiet --pidfile $TORPID --exec $EXECDAEMON
    then
        echo "$NAME."
    elif kill -0 $pid 2>/dev/null
    then
        echo "FAILED (Is $pid not $NAME?  Is $EXECDAEMON a different binary now?)."
    else
        echo "FAILED ($DAEMON died: process $pid not running; or permission denied)."
    fi
    ;;
  restart)
    $0 stop
    sleep 1
    $0 start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|reload|force-reload}" >&2
    exit 1
    ;;
esac

exit 0

Now save the following script to /etc/default/tor;

# Modification to Peter Palfrader's Debian Tor init script
#  by Steven J. Murdoch (http://www.cl.cam.ac.uk/users/sjm217/)

# Defaults for tor initscript
# sourced by /etc/init.d/tor
# installed at /etc/default/tor by the maintainer scripts

#
# This is a POSIX shell fragment
#
RUN_DAEMON="yes"

#
# Uncomment this if you want to get coredumps
#
# ulimit -c unlimited

And the following to your chroot environment at /usr/bin/tor-chroot

#! /bin/sh

# Script to start Tor in a chroot
#  Steven J. Murdoch (http://www.cl.cam.ac.uk/users/sjm217/)

TORCHROOT=/srv/chroot-tor
/usr/sbin/chroot $TORCHROOT /usr/bin/tor $*

Change permissions with chmod 755 /etc/init.d/tor /etc/default/tor /srv/chroot-tor/usr/bin/tor-chroot

And now you can run /etc/init.d/tor start|stop|restart|reload|force-reload Make sure you run update-rc.d tor defaults 19 to set up the start and stop links in the correct runlevel directories to make autostart while booting.

References

  1. Tor Project for using Tor in a chroot: https://trac.torproject.org/projects/tor/wiki/doc/TorInChroot
  2. Tor Project for setting up a Tor Relay: https://www.torproject.org/docs/tor-doc-relay.html.en