Configuring a Transparent Tor proxy

Having successfully configured a Raspberry Pi as a wireless access point I decided to see if I could use a similar approach to build a transparent Tor proxy.

Yes – I’m well aware that Tor can be abused, but I share the view that it also has a number of important legitimate uses as well.

I think I’ve succeeded in getting it to work as it appears to be doing what it should, however I’m not an expert so you need to check that the proxy really is working properly yourself before relying on it!

You also need to remember that one of the consequences of using a proxy is that although your connection may be protected this by itself won’t hide any information that your web browser or other applications may reveal about you or your location. 

It is also not necessarily that difficult to establish a link between your web browsing activity and you use of other cloud based services (such as Dropbox, iCloud and Spotify for example) that can be used to identify you.

The examples below show the commands I used on a Raspberry Pi with a USB Wireless adapter, but I have also set up a transparent proxy on an old desktop machine with a couple of network cards.

If you are using a wireless connection then need to begin by installing the firmware and configuring the wireless network to assign a static IP address to the interface you will be connecting to. 

If you are going to use a LAN connection then you just need to configure the second interface with a static IP address, skip the steps that configure a wireless access point, and then remember to substitute the right interface name in the place of wireless interface name in the subsequent steps.

nano /etc/network/interfaces

/etc/network/interfaces
auto lo
iface lo inet loopback
 
allow-hotplug eth0
iface eth0 inet dhcp
 
auto wlan0
iface wlan0 inet static
    address 172.16.0.1
    netmask 255.255.255.0

Or alternatively, if you are using a second LAN connection.

/etc/network/interfaces
auto lo
iface lo inet loopback
 
allow-hotplug eth0
iface eth0 inet dhcp
 
allow-hotplug eth1
iface eth1 inet static
    address 172.16.0.1
    netmask 255.255.255.0

Since we need to be able to connect to use the wireless network interface it needs to be configured as a wireless access point so we will start by installing the host access point package.

apt-get install hostapd
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libnl-route-3-200
The following NEW packages will be installed:
  hostapd libnl-route-3-200
0 upgraded, 2 newly installed, 0 to remove and 2 not upgraded.
Need to get 576 kB of archives.
After this operation, 1565 kB of additional disk space will be used.
Do you want to continue? [Y/n] 
  :
  :
  :
Setting up hostapd (2:2.4-1+deb9u2) ...
Processing triggers for systemd (232-25+deb9u8) ...
 

The next step is then to configure it.  Don’t forget to use your own unique SSID and password replacing <SSID> and <Password> with the SSID and password you want to use.

nano /etc/hostapd/hostapd.conf

/etc/hostapd/hostapd.conf
#
# /etc/hostapd/hostapd.conf
#
interface=wlan0
driver=nl80211
ssid=<SSID>
country_code=GB
channel=4
#
auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP
rsn_pairwise=TKIP
wpa_passphrase=<Password>  

Then we need to tell the system where to find the configuration file.

nano /etc/default/hostapd

/etc/default/hostapd
# Defaults for hostapd initscript
#
# See /usr/share/doc/hostapd/README.Debian for information about alternative
# methods of managing hostapd.
#
#DAEMON_CONF=""
DAEMON_CONF="/etc/hostapd/hostapd.conf"
 
# Additional daemon options to be appended to hostapd command:-
#       -d   show more debug messages (-dd for even more)
#       -K   include key data in debug messages
#       -t   include timestamps in some debug messages
#
# Note that -B (daemon mode) and -P (pidfile) options are automatically
# configured by the init.d script and must not be added to DAEMON_OPTS.
#
#DAEMON_OPTS=""

We need is something to allow clients to obtain a network address using DHCP, so we will install the dnsmasq package which can handle both DHCP and DNS requests (though the latter will actually be forwarded to the Tor proxy).

apt-get install dnsmasq
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  dnsmasq-base libgmp10 libhogweed4 libnetfilter-conntrack3 libnettle6
  libnfnetlink0
Suggested packages:
  resolvconf
Recommended packages:
  dns-root-data
The following NEW packages will be installed:
  dnsmasq dnsmasq-base libgmp10 libhogweed4 libnetfilter-conntrack3
  libnettle6 libnfnetlink0
0 upgraded, 7 newly installed, 0 to remove and 2 not upgraded.
Need to get 963 kB of archives.
After this operation, 2037 kB of additional disk space will be used.
Do you want to continue? [Y/n] 
  :
  :
  :
Setting up dnsmasq (2.76-5+rpt1+deb9u1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/dnsmasq.service
  -> /lib/systemd/system/dnsmasq.service.
Processing triggers for libc-bin (2.24-11+deb9u3) ...
Processing triggers for dbus (1.10.26-0+deb9u1) ...
Processing triggers for systemd (232-25+deb9u8) ...
 

We need to configure it with the name of the interface and the DHCP range to use, obviously the DHCP range must be in the same subnet that we used when assigning the static IP address to the interface earlier.

nano /etc/dnsmasq.conf

/etc/dnsmasq.conf
# Configuration file for dnsmasq.
#
  :
  :
  :
# If you want dnsmasq to listen for DHCP and DNS requests only on
# specified interfaces (and the loopback) give the name of the
# interface (eg eth0) here.
# Repeat the line for more than one interface.
#interface=
interface=wlan0
  :
  :
  :
# Uncomment this to enable the integrated DHCP server, you need
# to supply the range of addresses available for lease and 
# optionally a lease time. If you have more than one network, 
# you will need to repeat this for each network on which you  
# want to supply DHCPservice.
dhcp-range=172.16.0.1,172.16.0.63,4h
  :
  :
  :

If you reboot now, you should be able to connect to the wireless access point you have configured and obtain an IP address using DHCP, but we have not done anything to allow network traffic to go any further.  Since we plan to do this using UFW we need to install that next.

apt-get install ufw --no-install-recommends
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  dh-python iptables libip6tc0 libiptc0 libmpdec2 libpython3-stdlib
  libpython3.5-minimal libpython3.5-stdlib libxtables12 mime-support
  python3 python3-minimal python3.5 python3.5-minimal
Suggested packages:
  libdpkg-perl python3-doc python3-tk python3-venv python3.5-venv
  python3.5-doc binutils binfmt-support rsyslog
Recommended packages:
  bzip2 file xz-utils
The following NEW packages will be installed:
  dh-python iptables libip6tc0 libiptc0 libmpdec2 libpython3-stdlib
  libpython3.5-minimal libpython3.5-stdlib libxtables12 mime-support
  python3 python3-minimal python3.5 python3.5-minimal ufw
0 upgraded, 15 newly installed, 0 to remove and 2 not upgraded.
Need to get 5217 kB of archives.
After this operation, 25.3 MB of additional disk space will be used.
Do you want to continue? [Y/n] 
  :
  :
  :
Setting up ufw (0.35-4) ...
Creating config file /etc/ufw/before.rules with new version
Creating config file /etc/ufw/before6.rules with new version
Creating config file /etc/ufw/after.rules with new version
Creating config file /etc/ufw/after6.rules with new version
Created symlink /etc/systemd/system/multi-user.target.wants/ufw.service 
  -> /lib/systemd/system/ufw.service.
Processing triggers for libc-bin (2.24-11+deb9u3) ...
Processing triggers for systemd (232-25+deb9u8) ...
 

The next thing to do is to configure the firewall to deny any incoming connections by default, and then allow incoming SSH connections to allow you to connect to the proxy and manage it using SSH if required, as well as incoming DHCP requests so clients can obtain an IP address.

Note – DHCP requests use UDP and as the clients may not yet have an IP addresses you can’t specify the source address range either.

ufw default deny
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)
ufw allow in on wlan0 from 172.16.0.0/24 to any port 22 proto tcp
Rules updated
ufw allow in on wlan0 from any port 68 to any port 67 proto udp
Rules updated
ufw allow in on wlan0 from 172.16.0.0/24 to any port 53
Rules updated

We also need to allow inbound tcp traffic on port 8086 as this is the port that we will configure Tor to listen on in a minute.

ufw allow in on wlan0 from 172.16.0.0/24 to any port 8086 proto tcp
Rules updated

Finally it is time to install and configure Tor!.

apt-get install tor --no-install-recommends
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libevent-2.0-5
Suggested packages:
  mixmaster torbrowser-launcher socat tor-arm apparmor-utils obfsproxy
  obfs4proxy
Recommended packages:
  tor-geoipdb torsocks
The following NEW packages will be installed:
  libevent-2.0-5 tor
0 upgraded, 2 newly installed, 0 to remove and 2 not upgraded.
Need to get 1538 kB of archives.
After this operation, 4221 kB of additional disk space will be used.
  :
  :
  :
Setting up tor (0.2.9.16-1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/tor.service 
  -> /lib/systemd/system/tor.service.
Processing triggers for libc-bin (2.24-11+deb9u3) ...
Processing triggers for systemd (232-25+deb9u8) ...
 

We will configure Tor to log messages to /var/log/tor/notices.log and then add a new section at the bottom of the configuration file to configure it to listen for transparent proxy connections on port 8086 and DNS requests on port 53.

nano /etc/tor/torrc

/etc/tor/torrc
  :
  :
  :
Log notice file /var/log/tor/notices.log
  :
  :
  :
VirtualAddrNetwork 10.192.0.0/10
AutomapHostsSuffixes .onion,.exit
AutomapHostsOnResolve 1
TransPort 172.16.0.1:8086
DNSPort 172.16.0.1:53

The next step to redirect all inbound tcp traffic on wlan0 to port 8086 and redirect any inbound udp traffic on prot 53 to port 53 (which is the port that Tor is listening to for DNS requests).

nano /etc/ufw/before.rules

/etc/ufw/before.rules
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
#   ufw-before-input
#   ufw-before-output
#   ufw-before-forward
#
 
# Redirect packets from wlan0 to port 8086
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A PREROUTING -i wlan0 -p udp -m udp --dport 53 -j REDIRECT --to-ports 53
-A PREROUTING -i wlan0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j REDIRECT --to-ports 8086
COMMIT

 
# Don't delete these required lines, otherwise there will be errors
  :
  :
  :

We also need to make a couple of other changes to try prevent any leakage of information from either DNS or DHCP.  The first change should stop the client getting anything other than the most basic information in the response from the proxy to a DHCP request.

nano /etc/dhcp/dhclient.conf

/etc/dhcp/dhclient.conf
# Configuration file for /sbin/dhclient.
#
# This is a sample configuration file for dhclient. See dhclient.conf's
#       man page for more information about the syntax of this file
#       and a more comprehensive list of the parameters understood by
#       dhclient.
#
# Normally, if the DHCP server provides reasonable information and does
#       not leave anything out (like the domain name, for example), then
#       few changes must be made to this file, if any.
#
 
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
 
send host-name = gethostname();
request subnet-mask, broadcast-address, time-offset, routers;
#
       domain-name, domain-name-servers, domain-search, host-name,
#       dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn, dhcp6.sntp-servers,
#       netbios-name-servers, netbios-scope, interface-mtu,
#       rfc3442-classless-static-routes, ntp-servers;
 
#send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;

Note – The comma after routers has been changed to a semi-colon…

This next change should ensure that all DNS requests are redirected to the wireless interface and so routed via Tor.  I originally defined the name server to be the localhost address, but changed this as it broke DNS lookups on the proxy itself.

nano /etc/resolv.conf

/etc/resolv.conf
nameserver 172.16.0.1

Note – Any other entries in this file should be commented out or deleted.

Finally we can enable the firewall and reboot for all our changes to take effect.

ufw enable
Firewall is active and enabled on system startup

reboot

To check that it is working connect to the wireless access point you configured when setting up hostapd and try browsing to check.torproject.com – if it works it should tell you that you are using Tor!

That was fun but a lot of work, hopefully it was worth the effort.

I’ve only tested this on a Raspbian (stretch) and Debian (jessie) but it I’d expect the same proceess would work on recent versions of Ubuntu as well.


Raspberry Pi is a trademark of the Raspberry Pi Foundation

This entry was posted in Debian, Networking, Raspbian, Ubuntu and tagged , , . Bookmark the permalink.

1 Response to Configuring a Transparent Tor proxy

  1. psychocod3r says:

    Very useful tutorial. Thank you.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.