The documentation for Tor suggests running it in a chroot but I have not found this to be entirely trivial and I couldn't find any documentation on how to achieve this.
This document describes how I set up Tor 0.1.1.23 to run in a chroot on Debian GNU/Linux 3.0 (Woody) with a 2.4.18 Debian kernel, but it should be applicable to other Tor versions and most of it will be the same for other Linux distributions. The original version of these instructions was posted on the or-dev mailing list.
Another way with debian is to use debootstrap to install a complete separate environment for tor and privoxy.
Scripts for easy chrooting of Tor and Privoxy on Debian are available at www.northernsecurity.net/download/.
Installation
Unpacking and compilation
wget http://www.torproject.org/dist/tor-0.1.2.19.tar.gz.asc wget http://www.torproject.org/dist/tor-0.1.2.19.tar.gz gpg tor-0.1.2.19.tar.gz.asc tar -xzvf tor-0.1.2.19.tar.gz cd tor-0.1.2.19 umask 022 ./configure --prefix=/tor make
The prefix at the configure stage is the one used at runtime, so should be set relative to the chroot. I didn't use / as the prefix since that would result in the hard-coded paths starting with // which should work under *nix, but IIRC they break in Windows. For example, in the torrc.sample file you would have the following line: RouterFile //etc/tor/dirservers.
Copying files
sudo adduser --disabled-login --gecos "Tor user,,," tor TORCHROOT=/home/tor/chroot sudo mkdir $TORCHROOT sudo make install prefix=$TORCHROOT/tor exec_prefix=$TORCHROOT/tor
I firstly created a new user for the purposes of running Tor. Running the install within the chroot would be difficult since I would need to install a shell and other commands the makefile used, so I ran it outside, but set the install-time prefix to be different than the runtime prefix. I had to set both prefix and exec_prefix because the Makefile had exec_prefix hard-coded.
System setup
Shared libraries
Tor 0.1 needs libevent, so to install this from Peter Palfrader's backport, add the following lines to /etc/apt/sources.list
deb http://mirror.noreply.org/pub/tor woody main deb-src http://mirror.noreply.org/pub/tor woody main
Then run
sudo apt-get update sudo apt-get install libevent1 libevent-dev
To copy over the required libraries, run
ldd $TORCHROOT/tor/bin/tor
sudo mkdir $TORCHROOT/lib
sudo cp `ldd $TORCHROOT/tor/bin/tor | awk '{print $3}'` $TORCHROOT/lib
sudo cp /lib/libnss* /lib/libnsl* /lib/libresolv* /usr/lib/libnss3.so $TORCHROOT/lib
I used ldd to find out which shared libraries were needed, and copied them over to $TORCHROOT/lib. To keep things simple, I put libraries in /lib since /lib and /usr/lib are hardcoded into the Linux dynamic linker. If you put them in other places then you will need to set LD_LIBRARY_PATH (see notes). The libraries libnss* and libnsl* were not listed in the ldd output, but if they are not included then getpwnam() and gethostbyname() will fail.
Static (i.e., no external libraries)
Another way to compile tor is using special flags to reduce liability on libraries; however be aware that if another vulnerability comes out in SSL, once you have upgraded SSL you will need to recompile tor.
To achieve a "static" binary (one that requires no external libraries) you can pass other arguments to configure, for example:
LDFLAGS="-static" CFLAGS="-static" ./configure --prefix=/tor
Device nodes
sudo mkdir $TORCHROOT/dev sudo mknod -m 644 $TORCHROOT/dev/random c 1 8 sudo mknod -m 644 $TORCHROOT/dev/urandom c 1 9 sudo mknod -m 666 $TORCHROOT/dev/null c 1 3
Tor needed access to /dev/(u)random so I created these. Also /dev/null is needed if Tor is run as a daemon.
For those who are running tor on OpenBSD and have the default nodev option set on your partition where you've chrooted tor to, which in turn gives you errors about not being able to access /dev/null, you may use OpenBSD's virtual filesystem support to create a small dev filesystem for tor. This prevents normal users from doing potentially nasty things to your raw devices, had you simply removed the nodev option to get things working.
cd /home/tor sudo /bin/mkdir dev sudo /bin/dd if=/dev/zero of=devfs bs=1024 count=256 sudo /usr/sbin/vnconfig -c -v /dev/svnd0c devfs sudo /sbin/newfs /dev/svnd0c sudo /sbin/mount /dev/svnd0c dev cd dev sudo /sbin/mknod -m 444 urandom c 45 2 sudo /sbin/mknod -m 444 random c 45 0 sudo /sbin/mknod -m 666 null c 2 2
Configuration files
sudo mkdir $TORCHROOT/etc sudo sh -c "grep ^tor /etc/passwd > $TORCHROOT/etc/passwd" sudo sh -c "grep ^tor /etc/group > $TORCHROOT/etc/group" sudo cp /etc/nsswitch.conf /etc/host.conf /etc/resolv.conf /etc/hosts $TORCHROOT/etc sudo cp /etc/localtime $TORCHROOT/etc sudo mkdirhier $TORCHROOT/var/run
switch_id() calls getpwnam() which needs /etc/group and /etc/passwd so I copied these over too. Also getpwnam() and gethostbyname() needs nsswitch.conf /etc/host.conf, /etc/resolv.conf, /etc/hosts and access to /var/run. To get the timezone correct /etc/localtime is needed.
Tor configuration
sudo cp $TORCHROOT/tor/etc/tor/torrc.sample $TORCHROOT/tor/etc/tor/torrc sudo sh -c "echo -e 'User tor\nGroup tor' >> \ $TORCHROOT/tor/etc/tor/torrc"
Since chroot needs to be run as root, but Tor does not, I set the config file to switch UID/GID on startup.
Testing
sudo chroot $TORCHROOT /tor/bin/tor
which produced the following output:
[notice] Tor v0.1.2.19. This is experimental software. Do not rely on it for strong anonymity.
and terminate it with Ctrl+C
[err] Catching signal TERM, exiting cleanly.
Starting on boot
This part is quite Debian specific, but modifications to it should be applicable to other Linux distributions and *nix operating systems.
Add the following to $TORCHROOT/tor/etc/tor/torrc
PidFile /var/run/tor/tor.pid Log notice file /var/log/tor/log RunAsDaemon 1
then run
sudo wget -O /etc/init.d/tor http://www.cl.cam.ac.uk/users/sjm217/projects/tor/tor.init sudo wget -O /etc/default/tor http://www.cl.cam.ac.uk/users/sjm217/projects/tor/tor.default sudo wget -O $TORCHROOT/tor/bin/tor-chroot http://www.cl.cam.ac.uk/users/sjm217/projects/tor/tor-chroot sudo chmod 755 /etc/init.d/tor etc/default/tor $TORCHROOT/tor/bin/tor-chroot sudo update-rc.d tor defaults 19 sudo /etc/init.d/tor start
This downloads my modifications to Peter Palfrader's Debian Tor init script and a small wrapper which will perform the chroot. The scripts are not on the wiki so that they are not maliciously modified. Running update-rc.d will set up the start and stop links in the correct runlevel directories.
Setting up as a server
sudo mkdirhier $TORCHROOT/var/lib/tor sudo chown tor.tor $TORCHROOT/var/lib/tor # Set up server details, including the data directory: # "DataDirectory /var/lib/tor" sudo vim $TORCHROOT/tor/etc/tor/torrc sudo /etc/init.d/tor restart
This creates the data directory and ensures it is owned by the tor user. The default location in the torrc.sample is inside the install prefix, unlike the log and pidfile locations so I change this to be /var/lib/tor. You will also have to set up the other server configuration options (Nickname, Address, ORPort, ORBindAddress, ExitPolicy). Then mail the file $TORCHROOT/var/lib/tor/fingerprint as described here.
Notes
Presumably torify will be run outside of the chroot, but its config file location is set to be relative to the chroot by ./configure. I can't think of any neat way to fix this.
The library situation is a bit fragile. There may be some other libraries, like libnss_compat which don't show up in ldd but are required. Also there may be other files required that I haven't copied into the chroot. I have tested it as a client and it seems to work OK, but I haven't tried it as a server yet.
If you put shared libraries outside of /lib and /usr/lib you need to set LD_LIBRARY_PATH, but sudo drops the LD* environment variables for security reasons. If you want to put libraries in, say /tor/lib, you need something like: sudo su -c "export LD_LIBRARY_PATH=/tor/lib; chroot $TORCHROOT /local/bin/tor"