TorDNSEL: A Tor DNS-based Exit List

TorDNSEL implements the design described at
<https://tor.eff.org/svn/trunk/doc/contrib/torel-design.txt> with some
modifications. Instead of parsing the cached-routers file, it establishes a
persistent controller connection to Tor, receiving updated nodes and exit
policies as Tor fetches them from directories. When Tor is running as a
directory authority this information should be the most up to date.

TorDNSEL can perform active exit testing by launching an HTTP request to itself
through every exit node with a suitable exit policy. This allows it to detect
exit nodes configured to send outbound connections through a different IP
address from the one they advertise in their descriptors. When configured to
run exit tests, it tests through a particular exit node each time the node
publishes a new descriptor. All running nodes are tested periodically between
descriptor uploads.

Currently, only query type 1 from torel-design.txt is supported:

A request for the A record "1.0.0.10.80.4.3.2.1.ip-port.exitlist.example.com"
would return 127.0.0.2 if there's a running Tor node at 10.0.0.1 that allows
exits to port 80 at 1.2.3.4 and our AuthoritativeZone is set to
"exitlist.example.com". If there isn't such an exit node, we return NXDOMAIN.
If the query is unsolicited and outside our authoritative zone, we return
REFUSED.

Presumably, users of software with built-in support for DNSBLs would configure
[service port].[service address].ip-port.exitlist.example.com as a DNSBL.

-----------------------------------------------------------------------------

Dependencies

  TorDNSEL requires GHC 6.6. If you're running Debian unstable:

    apt-get install ghc6 libghc6-mtl-dev libghc6-network-dev libghc6-time-dev \
      libghc6-hunit-dev

  Older Debians will need backports from Haskell Unsafe:

    http://haskell-unsafe.alioth.debian.org/haskell-unsafe.html

  Otherwise, use your system's package manager or grab a binary distribution
  from the GHC website:

    http://haskell.org/ghc/download.html

  binary, a new serialization library, also required, is available here:

    http://hackage.haskell.org/packages/archive/binary/0.3/binary-0.3.tar.gz

  Before building binary, apply the included patch in binary.patch.

    cd binary-0.3 && patch -p0 < ../tordnsel-0.0.6/binary.patch

  If you don't, you're likely to experience a segfault if you receive a
  malformed DNS message.

  OpenSSL's libcrypto is required for strong random numbers.

Building TorDNSEL

    ./Setup.lhs configure
    ./Setup.lhs build

  If you want a tordnsel binary installed in /usr/local/bin:

    sudo ./Setup.lhs copy

Configuring TorDNSEL

  Copy config/tordnsel.conf.sample. At the very least, you'll need to uncomment
  and modify AuthoritativeZone, DomainName, SOARName, StateDirectory, and
  probably DNSListenAddress.

  To run exit tests, you need to specify at least ConcurrentExitTests,
  StateDirectory, TestListenAddress, and TestDestinationAddress.

  Make sure everything is working before changing RunAsDaemon to True so you
  won't miss any error messages (currently there's no support for logging).

  Load a config file with the -f option.

  Options listed in tordnsel.conf.sample can also be specified on the command
  line:

    ./tordnsel -f /etc/tordnsel.conf --AuthoritativeZone exitlist.example.com

  Command line options override those included in a config file.

Running TorDNSEL practically

  cp config/tordnsel-init.d-script.sample /etc/init.d/tordnsel
  chmod +x /etc/init.d/tordnsel
  cp config/tordnsel.conf.sample /etc/tordnsel.conf
  # Configure it
  vim /etc/tordnsel.conf
  addgroup --system tordnsel
  adduser --ingroup tordnsel --system --no-create-home \
    --home /var/lib/tordnsel tordnsel
  mkdir /var/lib/tordnsel

  update-rc.d tordnsel defaults
  /etc/init.d/tordnsel start

Common configuration problems

  This indicates that you're trying to bind to a port that is already bound:

    tordnsel: bind: resource busy (Address already in use)
