Transparent HTTP/DNS Anonymity, Encryption and Filtering with Tor, Privoxy, Squid, DansGuardian and dnsmasq on ClearOS

Warning: There is a problem with UDP-based DNS query interception and a fix will be posted shortly! See comments for more info.

In this article we will use Tor and Privoxy with dnsmasq and netfilter on ClearOS to transparently encrypt and anonymize web and DNS traffic on an entire private network or a single host without necessarily having to reconfigure any of its constituents. We will also cover daisy-chaining Squid to speed up browsing and DansGuardian to provide content filtering against browser attacks and on-the-fly virus scanning via ClamAV.

For your convenience I have provided a virtual machine image with these modifications at the end of the article.

Introduction: Pros

There are a number of reasons one might choose to use this method over locally installing Tor, which may include:

  • Browsers do not require configuration
  • Not all software that makes use of HTTP supports using proxies
  • Anonymous software updates
  • Composition of network to be protected frequently changes (guests with laptops etc.)
  • Squid cache "speeds up" slow Tor requests
  • Clients may lack technical skill required to properly implement Tor locally and utilize it wisely
  • Users with multiple browsers installed can not inadvertently break network policy simply by switching or installing new browsers
  • The side-benefits of running behind ClearOS: drop-in IPS, transparent gw-gw VPN with IPSEC, PPTP server etc.
  • Centralized content filtering against browser exploits, phishing sites etc.
  • On-the-fly anti-virus protection with ClamAV
  • Allows packet inspectors like BotHunter to inspect torified traffic for malicious activity

Introduction: Cons

  • Traffic sent over Tor tends to be very slow. Reducing the number of hops increases speed but decreases anonymity.
  • TLS/SSL still requires browser configuration
  • Traffic other than DNS and HTTP on ports 53 and 80 must be configured to use the prox(y/ies).
  • Communication between hosts and the gateway is not Tor encrypted, of particular concern on wireless networks.

Introduction: whatis

  • ClearOS - A full-featured, easy-to-use turnkey Linux router distribution. It is based on CentOS (RHEL) and provides a simple web-based configuration front-end to help drive its powerful network services. Personal favourites include Intrusion Prevention, bandwidth and QoS management, connection failover and load balancing.
  • Tor - Tor provides anonymity for networked applications by routing traffic through encrypted, multi-layered tunnels between nodes operated by Tor supporters.
  • Privoxy - From their website: "Privoxy is a non-caching web proxy with advanced filtering capabilities for enhancing privacy, modifying web page data and HTTP headers, controlling access, and removing ads and other obnoxious Internet junk."
  • Squid - A versatile caching proxy. It is available with a webconfig interface for ClearOS users through the default repositories.
  • dnsmasq - A multi-talented DHCP, caching-forwarding DNS and TFTP/PXE/BOOTP server that is a default component of ClearOS installations.
  • DansGuardian - A content filtering proxy that also gives us the ability to plug in virus scanning with ClamAV.
  • ClamAV - An anti-virus solution designed to run on UNIX servers to provide filter-style scanning in applications as diverse as MTAs and PHP uploads.

Introduction: The Objective

By the end of this article we will have a working router, either on dedicated physical hardware or as a virtual machine running on a host. In both scenarios it will be possible to transparently route all HTTP and DNS traffic through Tor from any hosts configured to use the ClearOS box as their gateway. By running a virtual machine on a single host one can effectively put a self-contained firewall appliance between one's self and the upstream network. In fact, this method allows those with more than one NIC installed to eliminate an existing embedded firewall/router appliance and serve an entire private network without significantly altering the host machine's configuration. Protected, portable hotspots can be created with little more than a laptop and a switch or secondary wifi card simply by bridging the virtual machine's internal and external interfaces with the appropriate NICs.

We will be using netfilter and NAT to transparently redirect requests destined for remote servers to proxies running locally on the router:

We will be daisy-chaining a series of proxies together. One may choose to omit one or two depending on available resources and your intent. For the purposes of this article, we will cover configuring all three of the following; if you choose to omit a proxy you must adjust your configuration (including port forwarding for transparency) to reflect this.

  • Privoxy - This is the proxy we will be connecting to Tor, it is not optional. Default port tcp/8118.
  • Squid - Provides caching. Optional, module is required as a dependency for DansGuardian in ClearOS repos but does not need to be enabled to use it if bypassing the content filter webconfig panel. Default port tcp/3128
  • DansGuardian - Content filtering, ClamAV anti-virus module. Both optional. Default port tcp/8080.

Introduction: Prerequisites

You must start this process with a working ClearOS installation. You can use my ClearOS virtual machines for paravirtualized Xen or hardware emulators to set up a test environment. If you will be installing ClearOS on dedicated hardware you may find my personal installation checklist helpful, if a bit dated. For a production environment I recommend going with the Xen paravirtualized image but if your objective is to create a more portable solution the HVM image with VirtualBox is an alright pick.*

* See VirtualBox (Windows) for instructions on converting the raw disk image into a VDI.

Configuration: ClearOS: Networking

How you configure your networking on the ClearOS host will depend on whether you are virtualizing or using real hardware, how many NICs the physical server has and whether you intend to replace your existing gateway. The specifics go beyond the scope of this article but the end result must be the same: hosts on the private network must at least be configured to use the ClearOS installation as their gateway.

It is possible to put the ClearOS box behind an existing NATted router by creating a separate subnet for its LAN side. For example, the existing network is and you have a ClearOS VM on your desktop with two virtual network interfaces bound to your one physical interface. You would configure the external interface of the ClearOS VM for gw then configure the internal (LAN) interface for Next you would configure the hosts (including the machine on which the VM is running if you desire) you will be forcing through Tor to use IPs on the subnet with as the gateway. Be wary of offering DHCP from both the existing router and ClearOS.

Configuration: ClearOS: netfilter

We will need to store some iptables rules in such a way that they are loaded on startup. ClearOS provides two ideologically-correct places to do this. If you installed the Firewall - Custom rules module you will have a webconfig interface for manipulating rules stored in /etc/rc.d/rc.firewall.custom. The format of the file is simply

iptables options # descriptive comment

Traditionally, user-defined rules have been stored in /etc/rc.d/rc.firewall.local. This option is available whether or not you have installed the custom rules module and is formatted in much the same fashion, though one may do away with the hash mark and comment.

If you choose to omit one or more of the proxies outlined in this procedure you will have to manually configure netfilter to redirect TCP traffic on port 80 to the listening port of the last proxy in the chain. The "magic rule" looks like this:

iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports {PORT_NUMBER}

Where {PORT_NUMBER} is the intended target. Be mindful of existing rules that may need to be deleted.

Configuration: ClearOS: Installing the Software

ClearOS Modules

Assuming you now have a working ClearOS instance you will need to register with ClearSDN to get software updates and the rest of the modules we need (unless you selected them when doing the initial ClearOS installation).

If you will be using Squid and DansGuardian install the the Web Proxy Module and Content Filtering Module under Clear Center > Modules in the webconfig (if you did not do so during the server installation). Also install Antivirus file scanner module if you wish to use DansGuardian in conjunction with ClamAV to scan HTTP traffic for viruses on the fly.

If you would like to provide users attempting to use HTTPS friendly failure pages telling them how to enable their proxy locally install the Web server module.

Privoxy from RPM

Log into the ClearOS machine via SSH and install privoxy:

# rpm -iv ftp://ftp.muug.mb.ca/mirror/centos/5.5/os/i386/CentOS/privoxy-3.0.3-9.3.el5.i386.rpm

Make privoxy start on boot:

# chkconfig --level 2345 privoxy on

Tor from RPM

Installing Tor from RPM takes care of user account creation and init scripts automagically.

To install Tor you will first need libevent:

# yum install libevent

We will be using the torify command on the router to send our DNS requests over Tor later in the article. You will need to install tsocks or torify will not work:

# rpm -iv ftp://ftp.univie.ac.at/systems/linux/dag/redhat/el5/en/i386/dag/RPMS/tsocks-1.8-7.beta5.2.el5.rf.i386.rpm

Now Tor (adjust for the latest version):

# rpm -iv http://deb.torproject.org/torproject.org/rpm/centos5/tor-

Make Tor start on boot:

# chkconfig --level 2345 tor on

If you don't like the thought of ClearOS calling home disable suvad - bear in mind this will negatively impact your ability to receive software updates. First, remove your ClearSDN registration information via webconfig by loading this URL:


Next run:

# /etc/init.d/suvad stop
# chkconfig --level 2345 suvad off

Bear in mind that even if you decide to leave suvad on the basic ClearSDN subscription includes and automatically configures Clear's dynamic DNS service. One may wish to disable this feature if one does not want systemname.poweredbyclear.com always pointing to your current public IP.

Tor from Source

A while back one had to modify Tor's source to get one-hop circuits running but it seems this recommendation has since been implemented and one-hop circuits can be configured without modification, provided the intended exit node is configured to allow this.

If you still wish to compile Tor from source on ClearOS we must first install its build environment:

# yum groupinstall "Development Tools"

If you have already installed Tor from RPM remove it:

[[email protected] html]# cp -r /etc/tor/ /etc/tor.bak
[[email protected] html]# cp /etc/init.d/tor /etc/init.d/tor.bak
[[email protected] html]# rpm -e tor
tor (pid 2058) running
Stopping tor: /usr/bin/torctl stop: tor stopped
[  OK  ]
/var/tmp/rpm-tmp.25797: line 12: fg: no job control
warning: /etc/tor/torrc saved as /etc/tor/torrc.rpmsave

Download the latest source tarball from the Tor project's website:

# cd /usr/src
# wget https://www.torproject.org/dist/tor-
# tar zxf tor-
# cd tor-

Before we begin compiling we need to install libevent (if it is not already available) and libevent-devel:

# yum install libevent libevent-devel

Now OpenSSL and OpenSSL-devel:

# yum install openssl openssl-devel

On older software one had to modify src/or/control.c, removing or commenting out the following lines (big ups to sprawl for their article in 2600):

if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
                   "551 Can't attach stream to one-hop circuit.\r\n", conn);
   return 0;

As we can see this block has been replaced:

  /* Is this a single hop circuit? */
  if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
    routerinfo_t *r = NULL;
    char* exit_digest;
    if (circ->build_state &&
        circ->build_state->chosen_exit &&
        circ->build_state->chosen_exit->identity_digest) {
      exit_digest = circ->build_state->chosen_exit->identity_digest;
      r = router_get_by_digest(exit_digest);
    /* Do both the client and relay allow one-hop exit circuits? */
    if (!r || !r->allow_single_hop_exits ||
        !get_options()->AllowSingleHopCircuits) {
      "551 Can't attach stream to this one-hop circuit.\r\n", conn);
      return 0;
    ap_conn->chosen_exit_name = tor_strdup(hex_str(exit_digest, DIGEST_LEN));

Compile the software and install it:

# ./configure
# make
# make install

Now we need to make a non-privileged user for Tor to run under.

# useradd -d /var/lib/tor -s /sbin/nologin -r tor

Let's use the init script provided by the RPM, modifications in bold:

# tor    The Onion Router
# Startup/shutdown script for tor. This is a wrapper around torctl;
# torctl does the actual work in a relatively system-independent, or at least
# distribution-independent, way, and this script deals with fitting the
# whole thing into the conventions of the particular system at hand.
# This particular script is written for Red Hat/Fedora Linux, and may
# also work on Mandrake, but not SuSE.
# These next couple of lines "declare" tor for the "chkconfig" program,
# originally from SGI, used on Red Hat/Fedora and probably elsewhere.
# chkconfig: 2345 90 10
# description: Onion Router - A low-latency anonymous proxy

# Library functions
if [ -f /etc/rc.d/init.d/functions ]; then
   . /etc/rc.d/init.d/functions
elif [ -f /etc/init.d/functions ]; then
   . /etc/init.d/functions

# Increase open file descriptors a reasonable amount
ulimit -n 8192


# torctl will use these environment variables
export TorUSER

if [ -x /bin/su ] ; then
elif [ -x /sbin/su ] ; then
elif [ -x /usr/bin/su ] ; then
elif [ -x /usr/sbin/su ] ; then

case "$1" in

    action $"Starting tor:" $TorCTL start

    action $"Stopping tor:" $TorCTL stop

    action $"Restarting tor:" $TorCTL restart

    action $"Reloading tor:" $TorCTL reload

    $TorCTL status

    echo "Usage: $0 (start|stop|restart|reload|status)"

exit $RETVAL

We're going to need the torctl script too, open /usr/bin/torctl and paste (modifications in bold):

# Tor control script designed to allow an easy command line interface
# to controlling The Onion Router
# The exit codes returned are:
#       0 - operation completed successfully. For "status", tor running.
#       1 - For "status", tor not running.
#       2 - Command not supported
#       3 - Could not be started or reloaded
#       4 - Could not be stopped
#       5 -
#       6 -
#       7 -
#       8 -
# When multiple arguments are given, only the error from the _last_
# one is reported.
# |||||||||||||||||||| START CONFIGURATION SECTION  ||||||||||||||||||||
# --------------------                              --------------------
# Name of the executable
# the path to your binary, including options if necessary
# the path to the configuration file
# the path to your PID file
# The path to the log file
# The path to the datadirectory
TorARGS="--pidfile $PIDFILE --log \"notice file $LOGFILE\" --runasdaemon 1"
TorARGS="$TorARGS --datadirectory $TorDATA"

# If user name is set in the environment, then use it;
# otherwise run as the invoking user (or whatever user the config
# file says)... unless the invoking user is root. The idea here is to
# let an unprivileged user run tor for her own use using this script,
# while still providing for it to be used as a system daemon.
if [ "x`id -u`" = "x0" ]; then

if [ "x$TorUSER" != "x" ]; then
    TorARGS="$TorARGS --user $TorUSER"

# We no longer wrap the Tor daemon startup in an su when running as
# root, because it's too painful to make the use of su portable.
# Just let the daemon set the UID and GID.

# --------------------                              --------------------
# ||||||||||||||||||||   END CONFIGURATION SECTION  ||||||||||||||||||||

ARGV="[email protected]"
if [ "x$ARGV" = "x" ] ; then

checkIfRunning ( ) {
    # check for pidfile
    if [ -f $PIDFILE ] ; then
        PID=`/bin/cat $PIDFILE`
        if [ "x$PID" != "x" ] ; then
            if kill -0 $PID 2>/dev/null ; then
               STATUS="$EXEC (pid $PID) running"
                STATUS="PID file ($PIDFILE) present, but $EXEC ($PID) not running"
            STATUS="$EXEC (pid $PID?) not running"
       STATUS="$EXEC apparently not running (no pid file)"

for ARG in [email protected] $ARGS

    case $ARG in
        if [ $RUNNING -eq 1 ]; then
            echo "$0 $ARG: $EXEC (pid $PID) already running"
        if eval "$START" ; then
            echo "$0 $ARG: $EXEC started"
            # Make sure it stayed up!
            /bin/sleep 1
            if [ $RUNNING -eq 0 ]; then
                echo "$0 $ARG: $EXEC (pid $PID) quit unexpectedly"
            echo "$0 $ARG: $EXEC could not be started"
        if [ $RUNNING -eq 0 ]; then
            echo "$0 $ARG: $STATUS"
        if kill -15 $PID ; then
            echo "$0 $ARG: $EXEC stopped"
            /bin/sleep 1
            if kill -9 $PID ; then
                echo "$0 $ARG: $EXEC stopped"
                echo "$0 $ARG: $EXEC could not be stopped"
        # Make sure it really died!
        /bin/sleep 1
        if [ $RUNNING -eq 1 ]; then
            echo "$0 $ARG: $EXEC (pid $PID) unexpectedly still running"
        $0 stop start
        if [ $RUNNING -eq 0 ]; then
            echo "$0 $ARG: $STATUS"
        if kill -1 $PID; then
            /bin/sleep 1
            echo "$EXEC (PID $PID) reloaded"
            echo "Can't reload $EXEC"
        echo $STATUS
        if [ $RUNNING -eq 1 ]; then
        cat $LOGFILE
        echo "usage: $0 (start|stop|restart|status|help)"
        /bin/cat <<EOF

start      - start $EXEC
stop       - stop $EXEC
restart    - stop and restart $EXEC if running or start if not running
reload     - cause the running process to reinitialize itself
status     - tell whether $EXEC is running or not
log        - display the contents of the log file
help       - this text

        $0 help



exit $ERROR

Now make both scripts executable:

# chmod +x /usr/bin/torctl
# chmod +x /etc/init.d/tor

Now copy the sample configuration file:

# cp /usr/local/etc/tor/torrc.sample /usr/local/etc/tor/torrc

Create these directories if they were not created for you:

# mkdir /var/log/tor
# mkdir /var/run/tor
# mkdir /var/lib/tor
# chown tor: /var/log/tor
# chown tor: /var/run/tor
# chown tor: /var/lib/tor -R
# chmod 750 /var/log/tor
# chmod 750 /var/run/tor
# chmod 750 /var/lib/tor

Add Tor to startup:

# chkconfig --add tor
# chkconfig --level 2345 tor add

Configuration: Tor

Tor is configured by default to listen to port 9050 on localhost. If you would like hosts on the private network to be able to have direct access to Tor you must change or add a second SocksListenAddress directive for your router's LAN address (in this case in /etc/tor/torrc.

Enable the control port by uncommenting this line in /etc/tor/torrc:

ControlPort 9051

Run this command, replacing password with the password you would like to use for the controller:

tor --hash-password password

Ignore the warning about running Tor as root; the actual daemon has been configured by its RPM to use a non-privileged account. Ucomment and change the HashedControlPassword to the output you were provided. Start Tor:

# /etc/init.d/tor start

Verify you can log into the controller, replace password with the unencrypted password you gave tor --hash-password:

[[email protected] log]# telnet localhost 9051
Connected to localhost.
Escape character is '^]'.
authenticate "password"
250 OK

By default Tor builds random 3-hop circuits. You can use the controller to increase performance or anonymity by increasing or decreasing the number of hops your circuits use, and even the geographical distance between hops. I recommend you read Tor Control Protocol for more information.

Quit telnet by holding down control and pressing the ] key. Type quit and hit enter.

It is important that your system time is accurate; you will find it difficult to establish circuits if your clock is skewed. Let's force an NTP update before Tor is started by modifying its init script at /etc/init.d/tor:

    /usr/sbin/ntpdate -s -b -u 0.gentoo.pool.ntp.org 1.gentoo.pool.ntp.org 2.gentoo.pool.ntp.org 3.gentoo.pool.ntp.org
    action $"Starting tor:" $TorCTL start

Note: choose time servers you trust. You may not be able to start Tor and subsequently torify ntpd if the first update does not go out vanilla. ClearOS uses these time servers:


To keep the system time accurate and optionally provide NTP service for your local network activate the NTP daemon:

# chkconfig --level 2345 ntpd on
# /etc/init.d/ntpd start

NOTE Xen users experiencing clock skew between the VM and dom0 should add this to Tor's init script before the call to ntpdate (/etc/rc.d/rc.local is run too late):

echo 1 > /proc/sys/xen/independent_wallclock

Configuration: Tor: torify

If you have configured Tor to only listen on your LAN address you must configure tsocks accordingly in /etc/tsocks.conf:

# This is the configuration for libtsocks (transparent socks)
# Lines beginning with # and blank lines are ignored
# This sample configuration shows the simplest (and most common) use of
# tsocks. This is a basic LAN, this machine can access anything on the
# local ethernet (192.168.0.*) but anything else has to use the SOCKS version
# 4 server on the firewall. Further details can be found in the man pages,
# tsocks(8) and tsocks.conf(5) and a more complex example is presented in
# tsocks.conf.complex.example

# We can access 192.168.0.* directly
local =

# Otherwise we use the server
server =

Configure tsocks to connect to your LAN address on every host in the private network where you would like to use torify without the overhead of a local Tor deployment.

Configuration: Privoxy

Privoxy listens for connections on localhost by default. Set the listen-address parameter in /etc/privoxy/config to the LAN address of your router if you would like the ability to manually configure browsers to use it - a good idea if you expect to be using TLS/SSL connections. Configure Privoxy to connect to Tor:

# listen-address
forward-socks4a / .

The period at the end is intentional. Start Privoxy:

# /etc/init.d/privoxy start

Configuration: Squid

Log in to the ClearOS webconfig at https://lan-ip:81 and configure Web Proxy under the Gateway menu. Set a suitable cache size and enable transparent mode. Optionally, you may wish to enable the banner and pop-up filter. If you will be using DansGuardian to provide anti-virus protection and content filtering enable the Contant Filter. Make the service start on boot, then start it.

Next we must configure squid to channel its requests through privoxy. Add this to /etc/squid/squid.conf:

cache_peer localhost parent 8118 7 no-query default

header_replace User-Agent Mozilla/5.0 (en) Gecko/20070515 Firefox/
header_access User-Agent deny all
header_access From deny all
header_access Server deny all
header_access WWW-Authenticate deny all
header_access Link deny all
header_access Cache-Control deny all
header_access Proxy-Connection deny all
header_access X-Cache deny all
header_access X-Cache-Lookup deny all
header_access Via deny all
header_access Forwarded-For deny all
header_access X-Forwarded-For deny all
header_access Pragma deny all
header_access Keep-Alive deny all
header_access Referer deny all
# header_access Cookie deny all

Add this line if you are record-conscious would like to disable Squid's cache:

cache deny all

Then update any cache_dir values:

#cache_dir ufs /var/spool/squid 500 16 256
cache_dir null /tmp

Alternatively, one can use tmpfs/shm for the cache_dir. With this method the entire cache tree is stored in RAM; evidence disappears when the machine is shut down rather than being written to potentially recoverable storage media. Not only does this let us reap the benefits of caching in lieu of the low speeds Tor is notorious for, it produces faster cache hits. The down side is that if the router is compromised before it can be shut down the contents of /dev/shm may also be compromised. To use this method you will need enough free RAM to satisfy the cache constraints we configured earlier in proxy server webconfig module. Do not add the cache deny allACL to the configuration script. Instead, configure your cache_dir to reflect:

#cache_dir ufs /var/spool/squid 500 16 256
cache_dir ufs /dev/shm/squid 500 16 256

Now edit /etc/init.d/squid to create the directory on tmpfs with the proper permissions every time squid starts:

start() {
        mkdir /dev/shm/squid
        chown squid:squid /dev/shm/squid
        chmod 750 /dev/shm/squid
        for adir in $CACHE_SWAP; do

Now restart Squid:

# /etc/init.d/squid restart

Try loading http://whatismyip.com etc. from a host configured to use the ClearOS gateway. If everything worked successfully you should see the IP of a Tor exit node at this stage.

Configuration: DansGuardian

In webconfig click on the Content Filter link under the Gateway menu. Configure it to start on boot then start it manually. You can take advantage of the Blanket Block to enforce a web-based authentication scheme as I outlined in this article: Transparent Proxy for Hot Spot/Public Network Web-Based Authentication on ClearOS. Enable the virus scanner to take advantage of ClamAV.

We will need to remove a rule which this process inserts automatically. Use one of the custom rule files (see Configuration: ClearOS: netfilter) to run:

iptables -t nat -D PREROUTING -s ! -p tcp -m tcp --dport 3128 -j REDIRECT --to-ports 82

Now we must direct DansGuardian to hand off connections to the last proxy in the chain before it; port 3128 for Squid or 8118 for Privoxy. Edit /etc/dansguardian-av/dansguardian.conf:

# Network Settings
# the IP that DansGuardian listens on.  If left blank DansGuardian will
# listen on all IPs.  That would include all NICs, loopback, modem, etc.
# Normally you would have your firewall protecting this, but if you want
# you can limit it to a certain IP. To bind to multiple interfaces,
# specify each IP on an individual filterip line.
filterip =

# the port that DansGuardian listens to.
filterport = 8080

# the ip of the proxy (default is the loopback - i.e. this server)
proxyip =   

# the port DansGuardian connects to proxy on
proxyport = 3128
#proxyport = 8118

Configuration: dnsmasq: Torifying dnsmasq

I was pleasantly surprised to find that dnsmasq - ClearOS' default caching DNS and DHCP server - not only worked with torify but continued to bind to localhost and the LAN interface properly. It's as simple as editing this line in /etc/init.d/dnsmasq to show:

 echo -n $"Starting $prog: "
 daemon torify $dnsmasq

Restart dnsmasq:

# /etc/init.d/dnsmasq restart

Make sure dnsmasq is using the tsocks library:

[[email protected] ~]# lsof | grep tsocks

dnsmasq 31015 nobody mem REG 3,1 63136 12419 /lib/libtsocks.so.1.8

Queries made through dnsmasq via the ClearOS box are now sent out over Tor and results are cached in RAM locally. Make sure the resolv.conf on the gateway starts with but includes additional name servers so that dnsmasq knows where to send its queries.

[[email protected] ~]# cat /etc/resolv.conf

Configuration: dnsmasq: Transparent Query Redirection

Add the following to your firewall configuration:

iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53
iptables -t nat -A PREROUTING -i eth1 -p udp -m udp --dport 53 -j REDIRECT --to-ports 53

Where eth1 is the ClearOS box's LAN interface.

Configuration: dnsmasq: Verifying Transparency

Delete the rules we just added with iptables:

iptables -t nat -D PREROUTING -i eth1 -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53
iptables -t nat -D PREROUTING -i eth1 -p udp -m udp --dport 53 -j REDIRECT --to-ports 53


On a *nix host configured to use the ClearOS box as the gateway determine the name servers for any given domain:

[email protected] ~ $ whois google.ca


Name servers:

Query one of them for the domain you chose, in this case google.ca:

[email protected] ~ $ dig google.ca @ns1.google.com

; < < > > DiG 9.7.1 < < > > google.ca @ns1.google.com
;; global options: +cmd
;; Got answer:
;; -> > HEADER < <- opcode: QUERY, status: NOERROR, id: 64208
;; flags: qr aa rd; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;google.ca.                     IN      A

google.ca.              300     IN      A
google.ca.              300     IN      A
google.ca.              300     IN      A
google.ca.              300     IN      A
google.ca.              300     IN      A

;; Query time: 68 msec
;; WHEN: Sun Dec 19 20:05:29 2010
;; MSG SIZE  rcvd: 107

Note the presence of the aa flag. This indicates that we are looking at an authoritative answer from DNS servers configured to serve this zone. Now load the rules back in:

iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53
iptables -t nat -A PREROUTING -i eth1 -p udp -m udp --dport 53 -j REDIRECT --to-ports 53

Try the query again:

[email protected] ~ $ dig google.ca @ns1.google.com

; < < > > DiG 9.7.1 < < > > google.ca @ns1.google.com
;; global options: +cmd
;; Got answer:
;; -> > HEADER < <- opcode: QUERY, status: NOERROR, id: 48247
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0

Note how the aa flag has been replaced by ra, indicating a recursive lookup.


On a windows host configured to use the ClearOS box as the gateway, open the command line and run:


Find the DNS server for any given domain name. Set it in nslookup:

> server xxx.xxx.xxx.xxx

Now query the domain name:

> domain-name.com

You should see no trace of "Non-authoritative answer:" in the output. Now, add the rules again:

iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53
iptables -t nat -A PREROUTING -i eth1 -p udp -m udp --dport 53 -j REDIRECT --to-ports 53

Do not change the DNS server nslookup is configured to query. Run the query again:

> domain-name.com

Immediately before the Name and Address(es) portion of the output you will see "Non-authoritative answer:" which indicates that your requests are being routed through dnsmasq.

Configuration: dnsmasq: Verifying Anonymity

Verifying that your DNS queries are being routed through Tor is somewhat more complicated than with web traffic. You will either need to run packet capture software (see my article on Remote Ethernet Packet Capture with Wireshark and tshark over SSH for ideas; on ClearOS run yum install wireshark to get tshark) or set up a name server that logs queries.

I used BIND because I already had that deployed. You don't need to have a name server on public address space - or even a registered domain to do this. Simply get a working BIND installation on an address which is reachable by the ClearOS box and configure its /etc/resolv.conf to do lookups against it after

Include the following in your named.conf's logging block:

  channel request_log
    file "/var/log/named/request.log" versions 3 size 5m;
    severity info;
    print-time yes;
    print-severity yes;
    print-category yes;
  category queries

Now create and set the permissions on request.log:

# touch /var/log/named/request.log
# chown named: /var/log/named/request.log
# chmod 660 /var/log/named/request.log

Now reload the configuration and enable query logging:

# rndc reload
# rndc querylog

Make a request for a unique-looking subdomain of some zone your BIND server is configured to serve so you will be able to pick it out if you are using busy live servers. Otherwise you can:

# tail -f /var/log/named/request.log

to watch requests as they come through. If, according to this log, the request you made does not originate from your address(es) it is safe to assume they are leaving a Tor exit node.

System logs

It may suit one to take the system logs into account. On a traditional production system logging is important but if we're trying to make a disposable, anonymizing virtual machine it may be preferable to leave as few forensic traces as possible. One could disable syslog but some daemons write directly to file and may complain or fail to start if their logfiles are unwritable. We can satisfy everyone by loading a blank /log/ directory tree into tmpfs and deciding whether or not to disable syslog based on one's paranoia and available RAM.

First, we'll need to turn off syslog:

# /etc/init.d/syslog stop

Next, clear out the existing log files.

# yes | rm /var/log/*
# yes | rm /var/log/*/*

Create wtmp:

# touch /var/log/wtmp
# chown root:utmp /var/log/wtmp
# chmod 664 /var/log/wtmp

Add a symbolic link for dansguardian-av:

# ln -s /var/log/dansguardian /var/log/dansguardian-av

Now, move the sanitized directory elsewhere:

# mv /var/log /var/log.tree

Copy the log directory tree to tmpfs:

# cp -ax /var/log.tree /dev/shm/log

Create a symlink from tmpfs:

# ln -s /dev/shm/log /var/log

Now, if you choose, remove syslog from startup:

# chkconfig --level 2345 syslog off

There may be other logging considerations to take care of depending on your situation - such as snort packet logging, which is enabled by default.

We need to copy the new /log/ tree to tmpfs before anything else starts every time the system is booted, so let's create a very crude init script in /etc/init.d/logtree:

cp -ax /var/log.tree /dev/shm/log

Now link it into runlevel 3:

# chmod +x /etc/init.d/logtree
# ln -s /etc/init.d/logtree /etc/rc.d/rc3.d/S05logtree

If you would like to reduce the risk of having your logs intercepted while the machine is live we can disable logrotate and add these lines to /etc/crontab:

*/05 * * * * root yes | rm /var/log/*
*/05 * * * * root yes | rm /var/log/*/*

Restart cron:

# /etc/init.d/crond restart


Due to the way TLS is implemented and proxies are designed to handle such requests it is not, to the best of my knowledge, feasible to transparently handle TLS connections. This presents a serious problem if users on your protected network will be signing in to HTTPS-protected sites as they will break anonymity.

One must block traffic to the port:

iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 443 -j DROP

If your client(s) will be using HTTPS they must now configure either privoxy or squid as the proxy in their browser(s). Privoxy will only be available if you chose to bind it to your LAN address, at port 8118. If you are not taking advantage of squid's cache this may provide some performance gain. Otherwise, configure the browser(s) to use port 3128 (Squid) or 8080 (DansGuardian).

Failing Gracefully

Rather than block HTTPS traffic altogether we can redirect TLS requests to a local web server on the ClearOS box that shows a page instructing users to configure their browsers to use one of the available proxies. This costs resources (mostly RAM) but can save your client's calling you for support. You need to have installed the Web server module as outlined in Configuration: ClearOS: Installing the Software.

Log into webconfig at https://lan-ip:81/ . Click the Web Server link in the Server menu. Click the Start and Automatic buttons. Make sure SSL is enabled. Now add this to your firewall configuration:

iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 443

You may choose to replace or edit the default page that comes with ClearOS:

# nano /var/www/html/index.html

Edit the blurb to include details on configuring browsers to use one of the proxies you have chosen to end the daisy-chain with. I thought the ClearOS template was so cute I kept it:



<div id='dialogintro1' class='sb'>
<p class='blurb'>
Sorry, you can't make TLS/SSL connections without configuring your browser to use this proxy:<br />
<strong>Server</strong><br />
<p align='center'><a href='http://www.clearfoundation.com/'><img src="logo.png" alt="Powered by ClearOS"></a></p>

<script type='text/javascript'>


Now when a user behind the ClearOS box attempts to make an SSL connection their browser will complain about an invalid certificate. If they accept it they will be told why SSL isn't working and what to do about it.


I was first inspired to do something like this when I read sprawl's Tor Control Protocol article in the Winter 2009-10 Edition of 2600.

These articles helped along the way:

A special thank you to the countless developers who have contributed in one way or another to the software involved in this article.

Virtual Machine Image

DOWNLOAD clear-trollup.tar.lzma (342MB) c9a56f4b55084e97b8a54f54aff1f512

This file is a sparse, raw full-disk image which can be used natively by some virtualization platforms (Xen, QEMU) or converted for use by others (VirtualBox, VMware). It is based on the ClearOS 5.2 foxpa.ws HVM Edition.

Note to Windows Users: 7zip (and probably others) has a problem handling sparse tar files. Download the gnuwin32 version of tar for the command line at ??http://gnuwin32.sourceforge.net/packages/gtar.htm

c:\Users\karma\Desktop>"c:\Program Files\GnuWin32\bin\tar.exe" xf clear-trollup.tar

Modified from the original README:

Caveats and considerations:
 - comes with iftop and tshark
 - custom snort rules with SIDs beginning with 4000000
 - http://foxpa.ws/2010/06/04/bad-snort-rules/ applied
 - user username is user, password is user (must SU on physical console)
 - root password is root
 - user password is user; log in as user then SU to root on PTYs
 - automatic updates are disabled by default
 - graphical console disabled
 - eth0 ext DHCP
 - eth1 lan
 - admin
 - grant users shell access in webconfig enabled

The VM uses all of the proxies covered in this article and fails SSL connections gracefully. Unfortunately, this requires that the VM has on the order of 400MB of RAM to work with. Remember to update IP/port binding directives and netfilter to reflect your new configuration should you drop one or more proxies from the chain. On-the-fly virus-scanning is enabled by default and logs are written to tmpfs at /dev/shm/tmfs.

Suvad has been disabled from startup, it must be re-enabled and started before you will be able to register your VM with ClearSDN:

# chkconfig --level 2345 suvad on
# /etc/init.d/suvad start

If you encounter issues registering your system try loading this URL in your browser twice:

The LDAP system may stall on startup if the VM is unable to resolve DNS queries. Ensure that the external interface is configured correctly (edit /etc/sysconfig/network-scripts/ifcfg-eth0) and /etc/resolv.conf lists working name servers before you start the VM. The VM is configured to acquire a DHCP address for its external interface from your existing router/DHCP server and uses two public name servers by default.

If you are connecting the internal and external interfaces to distinct Layer 2 networks (i.e. using it as an actual gateway) you may wish to remove these lines from /etc/sysctl.conf:


To mount the partition inside the full disk image use kpartx:

# kpartx -a clear-trollup.hdd

Find the partition's device node in /dev/mapper and mount it:

# mount /dev/mapper/loop1p1 /mnt/rawroot

Once you have unmounted the partition remove the loop device:

# kpartx -d clear-trollup.hdd

kpartx is a part of the miltipath-tools package. On Gentoo run:

# emerge miltipath-tools

Your kernel must support Device Mapper.

After you have configured your VM it is a wise idea to generate new keys for SSH. run:

# rm /etc/ssh/ssh_host_*
# /etc/init.d/sshd restart

Virtual Machine Image: Xen Paravirtualized

You will require a PAE or 64-bit compatible hypervisor and dom0 to run this image paravirtualized. The first time the machine is created you must use the -c flag to see the pyGRUB bootloader or mx will complain about an invalid default kernel having been specified. You will have 5 seconds to choose the domU kernel and initrd combo. Once logged into the VM edit /boot/grub/grub.conf to boot the domU configuration by default.

This is the sample configuration that accompanies the image:

# ClearOS 5.2 foxpa.ws TROllup edition Jan 2011 http://foxpa.ws/

name = "clear-trollup"

vcpus = 1
memory = 512
vif = [ 'mac=00:16:3e:ff:00:01,bridge=xenbr0', 'mac=00:16:3e:ff:00:02,bridge=xenbr0' ]
disk = ['file:/var/xen/clear-trollup/clear-trollup.hdd,hda,w']

bootloader = "/usr/bin/pygrub"
root = "/dev/hda1 ro"
extra = "xencons=ttyS"

# REMEMBER update your /boot/grub/grub.conf to load the domU kernel automatically

Be sure to update the MAC addresses and file paths.

Virtual Machine Image: Hardware Virtualization

The regular (HVM) kernel entry in grub.conf has the divider=10 RHEL-specific kernel command line argument to reduce the default timer frequency from 1000Hz to 100Hz.

HVM users will probably encounter a recurring error message on the main PTY indicating that agetty is re-spawning too fast on /dev/ttyS0. Open /etc/inittab and comment this line:

s0:12345:respawn:/sbin/mingetty ttyS0

Tor's init script may complain when it goes to enable the independent clock feature specific to Xen PV before setting the time with ntpdate. Comment this line in /etc/init.d/tor:

echo 1 > /proc/sys/xen/independent_wallclock

Virtual Machine Image: Hardware Virtualization: VirtualBox (Windows)

On Linux, and with older versions of VB I recall being able to use raw disk images unmodified. It seems that this is no longer the case so before you set up your virtual machine we will have to convert the disk image into a suitable format.

On *nix run:

$ VBoxManage convertfromraw clear-trollup.hdd clear-trollup.vdi --format VDI

On Windows:

C:\Users\karma>cd "c:\Program Files\Oracle\VirtualBox"
c:\Program Files\Oracle\VirtualBox>VBoxManage.exe convertfromraw clear-trollup.hdd clear-trollup.vdi --format VDI

Open VirtualBox then click on the New button to start the New VM Wizard.

Give the VM a name, set the OS to Linux and the Version to Red Hat (32 bit).

Click next and specify a reasonable amount of RAM for the VM. With all proxies used, antivirus scanning, HTTPS graceful failure and IDS/IPS the VM will need up to 400MB. Click Next and you will be prompted to locate the disk image.

Click Next then Finish and you will exit the Wizard.

Select the VM and click the Settings button. You may wish to reduce the amount of video memory under the Display tab. Click on the Storage tab. Remove clear-trollup.vdi from the SATA controller, then add it to the IDE controller:

Click on the Network tab. Change the Attached to: drop-down to Bridged Adapter. Select the NIC you will be putting the external interface of the VM on.

Click on the Adapter 2 tab. Enable the adapter and attach it to a Bridged Adapter. If you will be using the VM to protect only the PC it is installed on or other hosts on the same layer 2 network with an existing router you may choose to bridge this interface to the same physical NIC as Adapter 1. If you will be using the VM as your subnet's primary router/firewall Adapter 1 must be connected to the uplink NIC (i.e. plugged into your cable modem) and Adapter 2 should connect to the local layer 2 network (i.e. switch).

Click on the Serial Ports tab and check the Enable Serial Port box to avoid annoying respawning messages due to a Xen-related modification to /etc/inittab. Click OK to exit the settings window and start the virtual machine.

Once init has finished its run change the IP address of the physical adapter you have bridged to Adapter 2 (eth1) to something on the subnet:

In your browser navigate to and log in with the username root and password root. Go to IP Settings under the Network menu and update your configuration if necessary (i.e. provide a static IP for eth0). Continue to set a new password, user accounts and so on. Reboot the virtual machine once you have reconfigured it to your specifications.

Load up your web browser and navigate to, say, http://whatismyip.org/. If the IP does not match your public address congratulations, you have successfully configured your VM.


This article and VM are dedicated to Bradley Manning, who reminded us all that no matter how creative your OPSEC is mouthing off to some asshat will probably get you nailed.



Do you know Whonix? Is has full HTTPS support, no DNS leaks and also supports all TCP ports.

How to contact you by e-mail?

• ash

Tnx (-:

In simple English (-: till what or only part i should obey ?

Ithare a way to switch the Privoxy from the clearOS GUI ?


• ash


Tnx for the lovely post (-:

Is it possible to install Privoxy only on the clearOS without the TOR ?

Or, install both but with a way switch them off separate ?

Tnx (-:


Yep, just ignore everything but the privoxy bit.

• fred

client request to dnsmasq (use except-interface=lo and bind in configuration so dnsmasq will run on ip_of_eth0:53) and dnsmasq forward requests to ttdnsd (ttdnsd run on ttdns forwards and transforms requests through TOR.

netstat -lnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0* LISTEN 2499/tor
tcp 0 0 192.xx.xx.xx:53* LISTEN 1951/dnsmasq
tcp 0 0* LISTEN 4948/privoxy
udp 0 0 192.xx.xx.xx:53* 1951/dnsmasq
udp 0 0* 1900/ttdnsd


When you say you only used in resolv.conf to get dnsmasq routing through Tor did you mean in conjunction with ttdnsd?

• fred

I tested ttdnsd over the weekend and it runs well. Just specifying as only nameserver in /etc/resolv.conf force dnsmasq to forward all dns queries through TOR.

Another remark (which is irrelevant with ttdnsd): the command torify seems to use '/etc/tor/tor-socks.conf' instead of '/etc/tsocks.conf'.


I just put a little warning notice up top for the time being. It looks like it is not possible to force dnsmasq to query in TCP only, it just forwards queries in whatever protocol it receives them.


Oh no! D: When I performed my tests I only used dig, which IIRC makes its requests with TCP by default. I did not take into account that typical requests are in UDP. Connecting directly to privoxy with your browser uses socks4a/5 which lets privoxy handle the DNS lookup. My objective is to get DNS traffic on machines not configured for the proxy to be torified transparently and I think ttdnsd is exactly what is called for. I will test it and roll it into the VM as soon as time permits, thank you for pointing out this serious problem!

• fred

The torify man page explains that it only supports tcp and does not handle hostname lookup. So, torifying dnsmasq does not make sens (or you will force dnsmasq to use TCP?).

In another hand, privoxy seems to solve the DNS stuff correctly from itself.

For now I am testing ttdnsd which seems to solve my DNS lookup problem (and could run as parent of dnsmasq).

• fred

$ cat /etc/tsocks.conf
server =
server_port = 9050

"lsof | grep tsocks" return the same result as in your article.


Are you sure your tsocks.conf is configured correctly?

• fred

I actually tried the 'torify dnsmasq' in a VM (ubuntu) but its seems that dnsmasq bypass tor anyway (tcpdump from outside the VM).