Subscribe to RSS feed

splitbrain.org - electronic brain surgery since 2001

DNS Tunneling made easy

"Tunnel vision" by adactio

Yesterday I came across a technique to tunnel any traffic through the DNS protocol: All the packages you send are base32 encoded and prepended as the hostname of a DNS lookup request. A specially prepared DNS server will then forward your packages and reply with TXT answers.

What is it good for? It's an interesting way to hide your traffic. Cory Doctorow wrote about it in Little Brother for example. But it can also be used to sneak into certain public hotspots which are protected by HTTP redirections only. Those hotspots will allow web traffic to some few restricted websites (or some login page) only, but often allow all DNS traffic. It should also work to circumvent restrictive company firewalls.

I googled for implementations and came across two.

One is NSTX which makes use of the tun device support in Linux. This seems to be an excellent choice when you plan to use DNS tunneling on a regular basis.

The second option are some Perl scripts by Dan Kaminsky included in his OzymanDNS scripts. These are better fitted for the occasional use and easier to set up IMHO.

Those scripts can be combined with SSH to tunnel arbitrary traffic and there's an excellent documentation how to do that at dnstunnel.de.

However I found those scripts to be a bit messy and some things simply didn't work. They also contained code that was unrelated to DNS tunneling traffic.

I spent some hours to clean up the OzimanDNS scripts by doing the following things:

  1. fixed code indention
  2. fixed most warnings with use warnings
  3. fixed bugs (like non working listen option in the daemon, or the messed up resolver settings in the client)
  4. cleaned usage notices
  5. renamed some option switches (was needed to avoid name collisions)
  6. removed all unneeded code (like storing data in the DNS server) – less code, less potential flaws
  7. added privilege dropping after opening port 53
  8. added init scripts

You can download the whole thing here: dnstunnel-latest.tgz

Read on for a quick guide how to use it.


Setting up a DNS Tunnel Web-Proxy

The goal is to use SSH's builtin Socks proxy to be used with Firefox to tunnel all traffic through DNS requests only.

Here's what you need:

  1. The tarball above
  2. Control over a DNS server
    • If you run your own – good, but see below
    • Maybe your ISP gives you enough control in a WebGUI1)
    • Ask at dnstunnel.de for a free setup
  3. A server to set up the daemon
    • It can not already run an external DNS service
    • You need to have root access
  4. Perl, a bunch of Perl modules, screen, SSH
  5. Some Unix and DNS knowledge helps as well ;-)

DNS Setup

For making DNS tunneling work we'll setup our own DNS server that has to be authoritative for a given (sub)domain. Let's assume we have our own root server running at www.example.com using the IP 123.123.123.123. That box also will run our tunnel daemon. Our new subdomain for DNS tunneling should be tunnel.example.com.

This means we have to setup DNS delegation for that subdomain on the nameserver that is responsible for example.com. In Bind this can be done using something like this:

tunnel.example.com.  IN      NS      www.example.com.
www.example.com.     IN      A       123.123.123.123

All DNS requests for *.tunnel.example.com will now go to the IP 123.123.123.123.

Server Setup

On to the server at www.example.com. Here you should install a few needed software packages first. The following should suffice on Debian:

#> apt-get install screen libnet-dns-perl libmime-base32-perl

Then download dnstunnel-latest.tgz and unpack it to /opt/ – creating /opt/dnstunnel.

Edit the config at the top of the dnstunneld.wrapper' script. Eg. if you're running a caching DNS on the local interface you may want to bind the tunnel server to the external interface explicitly. You also may want to specify the user and group the daemon will run as. Run dnstunneld without arguments to get a list of possible options.

Here's an example:

DNSHOST="tunnel.example.org"
REPLYIP="127.0.0.1"
OPTIONS="-l 123.123.123.123 -u nobody -g nogroup"

Now link the init script and start the server

#> ln -s /opt/dnstunnel/dnstunneld.init /etc/init.d/dnstunneld
#> /etc/init.d/dnstunneld start

A DNS lookup for foo.tunnel.example.com should now return 127.0.0.1.

Client Setup

On the laptop, we need libnet-dns-perl and libmime-base32-perl again. Then copy the dnstunnelc script somewhere in your PATH. I suggest /usr/local/bin/.

To test the connection let's try to login via SSH using the tunnel client as proxy:

$> ssh -C -o ProxyCommand="dnstunnelc -v sshdns.tunnel.example.com" you@localhost

Notice the sshdns bit? The tunnel daemon will only answer with tunnel replies when this is set. You can change the name on the server with the -f option. The secrecy of the DNS name is the only “authentication” for the tunnel it self, so choose wisely.

Of course the access to the box behind the tunnel is protected by the usual SSH mechanisms. Notice the use of localhost? That localhost refers to the tunnel server of course, because when SSH arrives at the end of the tunnel it is localhost already.

Now if everything works, you can use SSH to open a Socks proxy:

$> ssh -D 8000 -N -C -o ProxyCommand="dnstunnelc sshdns.tunnel.example.com" you@localhost

Refer to my Conference WiFi Security article on how to set it up with Firefox.

Run the dnstunnelc script without any arguments to learn about a few more options. It has some interesting mechanisms to spread your DNS requests over many DNS servers.


PS: Circumventing access restrictions with this method might be illegal depending on where and what for you use it. Use it at your own risk.

Tags:
dns,
ssh,
tunnel,
network,
linux,
ozymandns,
security
Similar posts:
1) Works fine with http://regfish.net
Posted on Sunday, November the 2nd 2008 (8 months ago).

Comments?

1
Interesting,
But I expect that wireless network providers would allow only DNS queries to the DNS servers they own ? I have to try it :)
2008-11-12 16:57:06
2
Thanks for cleaning up the code - I was using Dans code about 18months ago and found that it would occasionally crash - hopefully your code cleanup will have helped with that

As for the comment above, it doesnt matter what DNS server the wireless network makes you use, as you are querying for a domain that you own, so thier DNS has to talk to yours - its pretty clever

Thanks again. OSG
2009-03-19 12:37:55
3
I tried to use this script as well. But it kept crashing on me too (it would eventually enter an error state and not know it). NSTX does the same thing. I eventually wrote my own. I tested this on very poor networks and it still works. For increased performance it also has a sliding window of packets and LZMA compression.
http://analogbit.com/tcp-over-dns_howto
2009-04-11 13:53:59
4
It should also be mentioned that if you want to get the init script to autostart with the server, you need to run (as root, on debian/ubuntu)
"update-rc.d /etc/init.d/dnstunneld defaults"
2009-06-11 22:50:42
myname
CAPTCHA

No HTML allowed. URLs will be linked with nofollow attribute. Whitespace is preserved.