Welcome to DNStunnel.de!
Did you ever sit at the airport or at a cafe and there was a unencrypted wireless access point nearby, but whenever you wanted to visit a site their website would pop up asking for a fee to use the internet through their AccessPoint (aka. Captive Portal)?
Well, I did, several times. But in most cases you are able to look up arbitrary hostnames, ie. google.com. That is because if you cannot resolve a host name your browser won't display any site. So these providers usually allow to look up hostnames to then filter whether they are allowed to access the site or not. In the latter case, their pay-to-get-access site pops up.
But you can use the fact that you can resolve arbitrary hostnames to gain free connection to the internet. Not a very fast one, though, but still a free internet connection.
The Idea is to tunnel all outgoing traffic through DNS. Yes, you heard right, through DNS, the Domain Name System, used to translate human-readable hostnames to numerical IP addresses and vice versa.
To understand how this'll work, you need a little knowledge of DNS. The DNS system has quite a lot of so-called types of records, such as A for address record, NS for nameserver record, CNAME for canonical name record etc. The most commonly used record is the A record. To let the hostname example.com point to 192.0.34.166 you'd set up the following in your DNS server's config:
example.com. IN A 192.0.34.166
Usually, such entries are stored at your provider's nameserver and you don't have any/full control over them (most likely if you bought a rather cheap webhosting package). But to allow DNS tunneling to work, there has to be a little bit more advanced setup.
What we'll do is delegate all requests to a certain subdomain (or, subzone) to another nameserver. That means: People want to look up your IP, get to your ISP's nameserver and will be redirected to your own nameserver which can then answer the request. For this, of course, you'll need a server running the client where you can become root.
Keep in mind: All requests to a certain subdomain are relayed to your host, which then answers them. And you won't look up ordinary hostnames, I tell you. Hope you got the idea.
To delegate all requests to sub.example.com to ns.anothernameserver.com, you first have to delegate all requests to that server (NS record, line 1) and then send a so-called GLUE record (that is, glued to the record before because it's most likely the asking server will need this info as well) with your server's IP (line 2, A record).
sub.example.com. IN NS ns.anothernameserver.com. ns.anothernameserver.com. IN A 192.0.34.166
If you just have a DynDNS account and no static IP, you'd set up the delegation using a CNAME record. As mentioned above, CNAME is a canonical name (speak: an alias). So when a server gets back a CNAME instead of an A record (IP address) he continues to look up this hostname. That brings us to the following:
sub.example.com. IN NS ns.extern.example.com. ns.extern.example.com. IN CNAME foo.bar.dyndns.org.
The fake server you can set up at your server to tunnel all the traffic through is a little program called OzymanDNS, written in Perl (Client and Server together 642 SLOC) by DNS guru Dan Kaminsky. The tool is split in four files, two of them being a file upload/download tool using DNS. Nice examples, but rather uninteresting for our approach.
The script nomde.pl is the server. Since the server binds to port 53 UDP on your server (which is a privileged port) you must be root to start the server. Also, make sure port 53 UDP is reachable from the outside (consider running nmap -v -sU host from a remote machine). You will usually want to start it as follows:
sudo ./nomde.pl -i 0.0.0.0 server.example.com
Here, the server will only listen to DNS requests for all subdomains of server.example.com. That way, people who don't know that exact address cannot use the service on your server.
The OzymanDNS client is just a perl script which encodes and transfers everything it receives on STDIN to it's destination, via DNS requests. Replys are written to STDOUT.
So this isn't particularly useful as a standalone program. But it was designed to be used together with SSH. And with SSH this works great. SSH has a config option, ProxyCommand, which lets you use OzymanDNS's droute.pl client to tunnel the SSH traffic. The command to connect to your server would look like this:
ssh -o ProxyCommand="./droute.pl sshdns.server.example.com" user@localhost
Note two things:
Once the connection is established (you'll probably have to enter your password) you have a shell! The connection is a little bit droppy sometimes and has not got the best latency, but it is still good keeping in mind that connections to the internet are not allowed at this Cafe/Airport/....
Once you verified that the connection is actually working, you can set up a tunnel so that you may not only have shell, but complete web acces, can fetch mails using POP, etc., etc...
For this, I recommend to read my tutorial on How to Tunnel Everything through SSH.
Don't forget: It may provide great performance increases to use SSH's -C ("compress data") switch!
So, now how might the servers communicate with each other, not being directly able to establish a connection?, you might ask now.
Well, since all subdomain resolve requests are delegatet (ie., relayed) to your host, you can include arbitrary data in the hostname which your server then can interpret and execute/relay.
The bytes you want to send to the server (upstream) will be encoded using Base32 (if you know what Base64 is, Base32 is just the same except there is no case sensivitiy, for EXAMPLE.COM ist just the same as example.com). After the data, there is a unique ID (since some DNS requests may take longer than others and the UDP protocol has no methods to check this) and either one of the keywords up or down, indicating whether the traffic's up- or downstream. Here is what an example request could look like (transferring something to the server):
ntez375sy2qk7jsg2og3eswo2jujscb3r43as6m6hl2ws xobm7h2olu4tmaq.lyazbf2e2rdynrd3fldvdy2w3tifi gy2csrx3cqczxyhnxygor72a7fx47uo.nwqy4oa3v5rx6 6b4aek5krzkdm5btgz6jbiwd57ubnohnknpcuybg7py.6 3026-0.id-32227.up.sshdns.feh.dnstunnel.de
The server's response comes as a DNS TXT record. A TXT record can hold arbitrary ASCII data and can hold uppercase letters as well as lowercase letters and numbers (some other characters, as well). So the responses come Base64 encoded. Such a response might look like the following one:
695-8859.id-39201.down.sshdns.feh.dnstunnel.de. 0 IN TXT "AAAAlAgfAAAAgQDKrd3sFmf8aLX6FdU8ThUy3SRWGhotR6EsAavqHgBzH2khqsQHQjEf355jS7cT G+4a8kAmFVQ4mpEEJeBE6IyDWbAQ9a0rgOKcsaWwJ7GdngGm9jpvReXX7S/2oqAIUFCn0M8=" "MHw9tR0kkDVZB7RCfCOpjfHrir7yuiCbt7FpyX8AAAABBQAAAAAAAAAA"
That is, in rough outlines, how tunneling via DNS works.
There are a few security issues you'll have to think about before letting the server run permanently:
Well, that is the reason I created this website. I offer to set up
a subdomain for you which delegates all requests (see above) to your
fake nameserver.I cannot handle the mass of requests coming in;
doing the communication and (manually!) setting up the records is just too
much.
Therefore, I advise you to check at free DNS providers first, for example:
If you're willing to pay a little money (like 5 EUR) you could just as well register a domain name at INWX, which is the provider I use for hosting the DNS of this domain.
If you have no whatsoever means to do the setup on your own write me an email at <request AT dnstunnel.de>. You should include your full name, your server's static IP or DynDNS hostname and the desired subdomain name (name.dnstunnel.de; I encourage you to keep this secret for your own security). Be prepared to wait a few days or even weeks until I get around to setting up the records!
Circumventing the AP's access controls (that includes DNS tunneling) is most probably considered to be a crime, depending on the country you live in. I am not responsible for whatever you do with your tunnel. I am just providing two simple entries in my ISP's DNS server to let a hostname point to your server's IP.
Here are two little helper scripts that'll allow you to
automatically start OzymanDNS on system boot through initd.
This is my /etc/init.d/ozymandns
file:
#!/bin/sh # Written by Julius Plenz set -e case "$1" in start) echo -n "Starting ozymandns listener..." screen -d -m /usr/local/bin/ozymandns-listener echo "." ;; stop) echo -n "Stopping ozymandns listener..." kill `cat /var/run/ozymandns.pid` echo "." ;; restart) /etc/init.d/ozymandns stop /etc/init.d/ozymandns start ;; reload|force-reload) echo "cannot do that" echo "." ;; *) echo "Usage: /etc/init.d/$NAME {start|stop|restart}" exit 1 ;; esac exit 0
Of course, you'll have to make the script executable. Then I'd suggest to put two links to automatically start and terminate the server on bootup/shutdown:
~# cd /etc/rc0.d/; ln -s ../init.d/ozymandns K15ozymandns ~# cd /etc/rc2.d/; ln -s ../init.d/ozymandns S99ozymandns
The program called from the init script
(/usr/local/bin/ozymandns-listener
) looks like this:
#!/bin/sh REPLYIP=0.0.0.0 DNSHOST=name.dnstunnel.de echo $$ > /var/run/ozymandns.pid while [[ -e /var/run/ozymandns.pid ]] ; do cd /usr/local/bin/ nomde.pl -i $REPLYIP $DNSHOST >/dev/null 2>&1 done
Note: This script again assumes you have installed the nomde.pl server in /usr/local/bin/ as well.
I made an example video: DNS Tunneling Example Video (1:30, 20MB)
There are a few other documents on the net explaining how DNS tunneling works. Some of these documents describe how DNS tunneling works with nstx, which is a different application, but basically also does the same as OzymanDNS.
© 2006-2011 Julius Plenz <julius * dnstunnel.de>