View Full Version : Tunneling shit over DNS

December 9th, 2009, 03:49 PM
This is a followup to my previous tutorial. I'm posting it late as punishment for Kalub's demands that I post it earlier. This is what you get.

Protip: Only do this if you know what the hell you're doing. If you get lost anywhere in this explanation or that tutorial that follows you shouldn't even be trying this!

So, we have a tunnel over SSH as presented in the other tutorial. This will work nearly anywhere, is relatively fast, and is extremely secure. But what if we're at a hotel or in an airport, where all traffic is blocked except HTTP - which is piped into a captive portal? What do we do here?

Well, we abuse the Internet, of course.

DNS, for the morons out there who don't know what it is, is the system that turns "google.com" into (or some other address, Google is load-distributed). The fun thing about it is how it works: You ask a server at your end to go find "example.com", it goes to the DNS Root Server and asks "where's com.?" (note the dot position). The Root Server says "Asks NetworkSolutions" (the company that owns the servers for the .com TLD), so you ask NetworkSolutions "where's example.com.?" and it points you to a server that says where example.com is. We can add a subdomain, say, tunnel.example.com and tell this DNS server that it's at our own server somewhere (usually the same server that hosts example.com). Now, when we lookup "tunnel.example.com" we get to this step and the chain finally hits something we have control of. This is where we strike.

DNS tunneling involves encoding messages into subdomains of subdomains of subdomains up to a primary domain that is "managed" by a server you operate. That server doesn't run a typical DNS daemon - which would normally just look at a sort of table and return an IP; instead, it runs a specially crafted tunnel server that looks at your subdomains, converts them into data and pipes that through a socket. At the same time, it waits for special requests (ie, to down.tunnel.example.com, whereas the other ones are to up.tunnel.example.com) and when it receives those it makes use of a special functionality of DNS - the TXT block (if we were desperate, we could encode four bytes, but that's not nearly enough), which, as its name suggests, is a lot of text.

So, basically, the idea is that we hide data in a request and get data hidden in a response. To an unsuspecting DNS chain, there's nothing fishy going on here.

Now, you read this tutorial hoping for a copy of the goods, not some bullshit theory you don't care about, amiright? The most common implementation of this system is slow, doesn't make full use of a DNS request, and has a lot of overhead in how it operates. This is the SSHNS system, created by Dan Kamnisky - a pro hacker who revealed a lot of issues with the DNS system. What this implementation does is run a Perl server and a Perl client (I wrote my own client in Python, though, and that's the one I'm giving out) and tunnels SSH connections over it.

You should already have everything set up for SSH, so I'm going to explain how to set up the server. I need to reupload all of my stuff somewhere because the only other place to get it is really slow (as in "not-working" slow), so you'll have to wait (again).

In the meantime, you can set up your NS.

You Will Need:
- A domain name (for the server that will run this)
- A remote (or not-on-the-machine-your-doing-this-on) DNS server
- A machine with a global IP that *isn't* behind a firewall
- This machine should be running a Posix OS, if not, GET ONE
- Said machine must also be running SSH, and preferably with pubkey authentication (don't know what that means? STOP READING)
- The Perl script and all of its dependencies (::Base64, ::DNS, etc.; if you're on a good Linux these should be easy to find and install)
- My Python script and bash script (the former is a better client, the latter *really* helps get this working)

First Steps
We need to set up our NS server. Get to your NS settings and add a subdomain (ie, tun.example.com) with an NS block that points to the domain name (ie, example.com, or ns.example.com for better results) of the server that you will run the tunnel from. That is all that is required of the remote DNS settings.

Now, get the Perl script running. I've provided in my 7zip a simple script that will do this for you, just change the domain.

That should be it, your tunnel server is ready.

The Client
I have provided my own client, the original client, and a startup script for SSH that will help you out a lot. All you need to do is run this script and you should be done. If you're on Windows I don't know how to do this with PuTTY, please use Cygwin and you'll be able to run the script.

All my script does is start up SSH with the pipe/tunnel enabled. You can now point your SOCKS proxy client (ie, Firefox) just as you did in the last tutorial (note that I'm using port 8080 here) and you'll be done.

This is VERY VERY SLOW, I'm working on a new implementation that has significantly improved throughput and runs in C, which will make it a lot more efficient. DO NOT attempt to load multiple pages at once! One at a time, and let them load completely. I do not suggest trying to watch YouTube videos with this, but you can try. It's best for small things like IRC and SMTP (mail).

Get everything here (http://www.acm.uiuc.edu/%7Elange7/ssh_dns_tunnel.7z).
- Put the `dns` directory in your Python 2.5 "site-packages" directory (/usr/lib/python2.5/site-packages/ normally)
- Place sshns/ in your home directory
- Place pytun in your home directory
- Change sshns/droute.py so that `extension = "sshns.YOUR.SERVER.WITH.SUBDOMAIN"`
- Place sshns/ in your home directory
- Place dnstunserv in your home directory
- Edit dnstunserver so that "tun.EXAMPLE.COM" is your domain name and subdomain

Start the server:
Run `sudo ./dnstunserv` while in your home directory.

Start the client:
Run `./pytun` from in your home directory. If you don't eventually see "Interactive session started", `killall ssh python2.5` and try again. It can fail.