[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-talk] Experimental DNS/DNSSEC hidden service HOWTO (optionally over TLS)


I've started a DNS/DNSSEC hidden service at b36iqwi6e4l4eyvf.onion. The
service listens on two ports:

- 53 (plain DNS over TCP)
- 44353 (DNS over TLS)

The TLS version is an experiment - paradoxically not for security
(unbound currently does not check the certificate), but as a hackish
attempt at performance.

Below is a HOWTO for setting up your system resolver to upstream to the
hidden service with unbound.

1. For whom and what purpose is it intended

- DNS hidden service can be used as your system resolver if you have a
  virtualized environment (virtualized Linux distribution)
- you want to resolve "uncommon" RR types like SRV for XMPP (Jabber)
- you still should use Tor SOCKS proxy for any application that needs
  only connecting to a given FQDN and TCP port (like browsers, IRC) so
  that no unnecessary DNS requests are made. See
  [1][2] for more information about circuit correlation. Tor
  0.2.3.x-alpha recommended due to stream isolation support.
- in the steps below, 9050 is expected to be Tor's SocksPort (the default)
- is it slow? Yes, it's very slow. Expect timeouts. A lot depends on the
  state of unbound's cache of DNS records.

2. What software you'll need

- unbound, latest (1.4.16) is recommended, some features like
  tcp-forwarding or DNS-over-TLS may not be available in older versions
- socat (http://www.dest-unreach.org/socat/)
- dig (from bind-utils, this is just for testing the tunnel)

3. Setup of resolver on client side (version without inner TLS)

Create a file name /etc/unbound/root.key containing (this is for DNSSEC
signature validation):

trusted-keys {
"." 257 3 8
// key id = 19036


In /etc/unbound/unbound.conf, find the line with option
'trusted-keys-file' and point it to the root.key file (make sure the
line is not commented out by leading #).

	trusted-keys-file: /etc/unbound/root.key

(Note: if you don't set the 'trusted-keys-file' and also keep other DNS
key settings like 'dlv-anchor-file' commented out, that will turn off
DNSSEC validation - makes the DNS resolving faster, unbound acts as a
non-validating caching resolver.)

In the same way, find option 'tcp-upstream' and change it to 'yes':

	tcp-upstream: yes

At the end of /etc/unbound/unbound.conf, add following lines (that is
what makes the forwarding to the upstream DNS hidden service happen):

 	name: "."

Next, we setup socat so that it will listen on 5353 and upstream any DNS
request made by system to the hidden service (run in different terminal
or screen, you may remove the two '-d -d' later, those are just for
debugging purposes to see when it opens/closes connection):

socat -d -d TCP4-LISTEN:5353,fork \

First check that the hidden service is connected (try few times if 'dig'
times out):

dig +dnssec +tcp -p 5353 addons.mozilla.org @localhost

If you got answer, it's time to start the local unbound resolver:

/etc/init.d/unbound start

There's an utility named 'unbound-checkconf' that might help you if
unbound complains about errors in config.

Again, try if unbound can resolve (may timeout, try multiple times):

dig +dnssec addons.mozilla.org @localhost

If it seems to work, make unbound your system resolver by replacing any
lines in /etc/resolv.conf starting with "nameserver" by:


Note that if the Linux distro is using things like NetworkManager (or
dhclient hooks), you need to tell them to set local unbound as resolver.
E.g. for NetworkManager by creating file
with the following contents (make it executable):

# Override /etc/resolv.conf to use unbound, no search and no domain
if [ "$2" = "up" ]; then
	echo "nameserver" > /etc/resolv.conf

4. Configuring client's unbound for DNS-over-TLS

In unbound.conf, uncomment and set 'ssl-upstream' to 'yes'. Then, in the
socat invocation, change destination to port 44353, i.e.:

socat -d -d TCP4-LISTEN:5353,fork \

Restart of unbound is necessary if already running.

The TLS version was an attempt to side-step the performance issue that
unbound opens TCP connection for each query (i.e. what would be single
UDP packet is now TCP SYN/ACK-handshake+data+FIN/ACK).

Still not sure it actually helped, seeing TLS encrypted alert 21 often
(followed by partial TLS handshake in some cases and FIN/ACK in others).

5. Setting up unbound as DNS hidden service

It's done just as any other hidden service [3], just point it at local
port 53. By default unbound listens on TCP (option 'do-tcp').

If you want to have the service "hidden", you need to upstream to other
resolver either via VPN or unbound's 'forward-zone' option (just like
above, only set the address to an actual IP adress of validating
recursive resolver).

But keep in mind that it's not "really hidden" since it needs to perform
DNS queries to outside world.

If you want TLS as well, first generate a self-signed certificate and
key using openssl, then set in unbound.conf:

        interface: ::1@44353
        interface: ::1

        #unbound.pem and unbound.key are the generated cert/key
        ssl-service-key: "/etc/unbound/unbound.key"
        ssl-service-pem: "/etc/unbound/unbound.pem"
        ssl-port: 44353

6. Comments/notes

This is not "full DNS/DNSSEC in Tor" yet, but can be used/deployed

Other not yet mentioned quirks:

- not scalable as such (no load-balancing/resolver switching at client's
- resolving timeouts might cause strange corner-cases, like unbound
  thinking that a response is bogus because DNSKEY query timed out
- greatest problem performance-wise is validation of names that chain
  through multiple zones due the use of CNAME/DNAME (commonly CDN/cloud
  services - requires many DS/DNSKEY queries)
- "if it times out first time, there's good chance it will work second
  time" - usually unbound queried and cached the reply in the meantime


[3] https://www.torproject.org/docs/tor-hidden-service.html.en
tor-talk mailing list