7/5/11

DNS Tunneling

Going on vacation? Time to set up some DNS tunneling. Take back the hotel fees, the airport fees, and recently the fees incurred in the sky. While you can't do everything over a DNS tunnel, expect speeds to around 20KB/s to 25KB/s, it will allow you to do some general poking around on the web that you wouldn't be able to do.  At least that was the original plan, it turns out this is extremely unstable and it is hard to maintain a good connection, or the network I am using blocks this type of abuse. Update: Switching to iodine I am able to at least create a terminal connection but in general it is still quite slow. Both iodine and DNS2TCP perform beautifully for tunneling on an internet connection that doesn't block anything. If you are looking to just tunnel some traffic on a Work network I could see this working without much trouble at all although if your network admin is worth his salt he will be on to you quite quickly.

Ready fit programs that enable DNS TCP Tunneling.
  • ozymandns
  • dns2tcp
  • iodine
A word about the setup
You are running a DNS server on home.clevar.me, you are then delegating the resolution of names on another subdomain say, tunnel.clevar.me to home.clevar.me. So if a request for the IP address for
ASDFDASFDSAFS.tunnel.clevar.me is sent, home.clevar.me receives the request and processes it returning data that one of the above programs produces to encapsulate TCP over DNS.

Using GoDaddy
Go to domain manager.

Add an A record called home.yourdomain.com, point it at your home IP.
Add an NS record called tunnel.yourdomain.com, point it at home.yourdomain.com

Wait for everything to propagate.

That's it.

What is an NS record?
""NS records specify the authoritative nameservers (both primary and secondary) for the given domain. The authoritative nameservers are identified by name, not IP address. For this reason, an A record must exist for the specified nameservers. Without it, connecting to the servers might be impossible. In every DNS zone, there must be at least two NS records.""

I will be attempting DNS tunneling with any program I can find that offers this unique ability and rating each on effectiveness below.

My setup looks like this:
Server: Running Ubuntu Linux
Client: Mac OS X

Reference will be made to Macports and brew, if you are not familiar with those please take a look. Nowadays I prefer brew over macports due to its tighter integrated approach with the OS.


DNS2TCP
My first attempt at utilizing this tunneling approach is with DNS2TCP.

Install dns2tcp on your client

Ubuntu/Debian
apt-get install dns2tcp

Mac OS X
If you are using Macports:
port install dns2tcp

For brew users:
brew install dns2tcp

Install DNS2TCP on your server
The server side was easy as well since Ubuntu/Debian package dns2tcp.

apt-get install dns2tcp

Set up the /etc/dns2tcpd.conf config file:
listen = 0.0.0.0
port = 53
# If you change this value, also change the USER variable in /etc/default/dns2tcpd
user = nobody
chroot = /tmp
domain = tunnel.clevar.me
resources = ssh:127.0.0.1:22 , smtp:127.0.0.1:25
Start up the server in debug mode to ensure we are good.

dns2tcpd -F -d 5 -f  /etc/dns2tcpd.conf

Run the client to show you available remote connections:

dns2tcpc -z tunnel.clevar.me 8.8.8.8

You should see ssh and smtp listed. If that is the case your setup is working.

Setup a remote tunnel
dns2tcpc -z tunnel.clevar.me  -l 3333 -r ssh
No DNS given, using 192.168.43.1 (first entry found in resolv.conf)
Listening on port : 3333

Connect to your SSH server through dns2tcp on port TCP/3333
ssh user@localhost -p 3333 -D 1080

You should connect to your home server !

Potential issues:
Version mismatch can cause problems:
http://forum.soft32.com/linux/Bug-595101-dns2tcp-Fails-differing-versions-ftopict520956.html

Conclusion for DNS2TCP
So far DNS2TCP has proven unusable due to the lack of a DNS server willing to play ball. I tried Google's DNS servers, Verizon's DNS servers, and the hotel's DNS server I was staying at. I will play around a bit and update the post if I have more success. At this point I am convinced the Network Admins are surprisingly smart enough to limit the number of DNS requests going through the limited network they setup for users connecting. DNS2TCP works fine as a tunnel when I am using my phone in network via tethered mode so I can only assume the admins are wise to this approach. If I have similar results with the other programs it will be fairly conclusive.


Iodine
Next on the list for DNS tunneling programs to try is iodine. The name started out as IOD, IP over DNS, and then the devs picked Iodine because it has the atomic number 53, i.e. the DNS port. Cute :).

Homepage: http://dev.kryo.se/iodine/

Client setup
Again I will be using Mac OS X as my client and brew seems to have a package already available so.

brew install iodine

You also need to install tuntap for Mac OS X: http://tuntaposx.sourceforge.net/

If you are using Ubuntu/Debian you can simply apt-get install iodine.

Server Setup
Ubuntu also has packages so the server install portion is easy as well.

apt-get install iodine

Starting the Server
sudo iodined -f -P test -n 123.4.5.6 10.0.0.1 tunnel.clevar.me

10.0.0.1 is the IP address to assign to the TUN interace, the client will have an IP address of 10.0.0.2.

tunnel.clevar.me is again the tunnel we setup, similar to the DNS2TCP section.

The -n option is to tell iodined what your external IP address is, the client uses this information to see if the network you are on allows raw UDP connections to the server IP that you are using for tunneling. If you are behind a NAT iodined will  omst likely detect your local IP address and not your external. If this happens you will see the client referring to your local IP address and not your external, you should use -n if this happens.

Now lets connect with the client. 
sudo iodine -f -P test  8.8.4.4 tunnel.clevar.me

8.8.4.4 is a Google DNS server, You can leave this blank and it will attempt to autodetect the DNS server but for the most part the Google servers should work.

Note here we do not need to provide the TUN interface IP it is automatically identified and set by the iodine client.

Conclusion for iodine
Using the same network as DNS2TCP I can actually create and keep a connection using iodine. While it is still basically unusable other than very slow terminal access over SSH I am impressed with the ease of use of iodine as well as the amount of features it auto detects based on the network you are connected to.  Both programs have received a recent refresh but with my previous attempts I was unable to use DNS2TCP at all, even for a simple ping test. So far iodine is definitely the program of choice for TCP over DNS tunneling. Iodine is by far easier to setup than DNS2TCP, no config files, just start with options and you are off.


OzymanDNS
The final DNS program I will be testing on the the networks I am on is OzymanDNS, it was written by Dan Kaminsky and is a Perl script that is designed specially to be used as a proxy program in SSH. Both Iodine and DNS2TCP allow you to forward any connection which, while not encrypted, could be advantageous if the tunnel is slow. With OzymanDNS you have to use SSH.

You can grab a copy of OzymanDNS here

Perl modules that need to be installed for Client and Server
*sudo perl -MCPAN -e 'install MIME::Base32'
*sudo perl -MCPAN -e 'install Net::DNS'
*sudo perl -MCPAN -e 'install Digest::CRC' 

*You don't need to use sudo if you don't want to install the modules directly into the Perl search path, if you do not do this you will need to add the location of the installed modules to the PERL5LIB environment variable.

Also, If you are using Ubuntu/Debian you can just search for the name of the module, e.g. apt-cache search MIME::Base32, and install the returned package. It is always better to use your systems package management software rather than CPAN.


Server
sudo ./nomde.pl -i 0.0.0.0 -p tunnel.clevar.me

Client, Start your SSH connection
ssh -o ProxyCommand="./droute.pl tunnel.clevar.me"  -C localhost

Conclusion
Unfortunately I was not able to get this to work, traffic was clearly being passed from client to server but no connection was ever completed successful even on an unrestricted network. Maybe i'll have better success with the optimized version by cyberphobia

Optimized version of OzymanDNS
There is an optimized version of Ozyman that has been attached that utilizes DNS NULL records, this allows for a larger transfer rate.

You can grab a copy of the Optimized version of OzymanDNS here


Server
I had to edit the file at line 347 and remove the three lines referring to a file that was supposed to be served. I didn't really bother to dig further into the code considering the failure with the unoptimized version.


if(length($opts{filename})) {open FILE, "$opts{filename}" or die $!;}
#binmode FILE;
#$opts{file}=FILE;


However once both client and server were running I suffered the same fate as the unoptimized version, I was unable to create an SSH tunnel successfully even on a non restricted network.


Client
ssh -o ProxyCommand="./droute.pl tunnel.clevar.me"  -C localhost


Conclusion for OzymanDNS/OzymanDNS Optimized
It looked promising but unfortunately I was not able to get it to work. Iodine works so well supports multiple record types so I don't really see a reason to play with this more, I may poke at it later and update this post if I figure out what was happening.


Final Thoughts
All three programs were tested on the same restricted network while staying in a Marriott hotel. For the most part I am done with this experiment. I want to run a test on a plane to see if I can connect to my box. If you want to do any DNS tunneling I highly recommend iodine over any of the other programs tested here.

Links/Tutorials etc that were used or helped lead to the solution above.

29 comments:

  1. nice post, i have trying iodine for bypass the captive portal of 3g network but the bandwidth is poor, do you have any advice for other alternatives now? (sorry for my bad english)

    ReplyDelete
  2. I have been testing iodine for a few days now. I can get the tunnel setup. But I cannot ping the server side IP address. my friend can connect with a jailbroken ipod. if you have any suggestions, i'd love to pick your brain, cheers.

    C:\iodine-0.7.0-windows>iodine.exe -f -P pwd -L0 -r x.x.x.x dns.test.com

    Opening device Ethernet 3
    Opened IPv4 UDP socket
    Opened IPv4 UDP socket
    Sending DNS queries for dns.test.com to x.x.x.x
    Autodetecting DNS query type (use -T to override).Opened IPv4 UDP socket

    Using DNS type NULL queries
    Version ok, both using protocol v 0x00000502. You are user #0
    Enabling interface 'Ethernet 3'
    Setting IP of interface 'Ethernet 3' to 10.0.0.2 (can take a few seconds)...

    Server tunnel IP is 10.0.0.1
    Skipping raw mode
    Using EDNS0 extension
    Switching upstream to codec Base128
    Server switched upstream to codec Base128
    No alternative downstream codec available, using default (Raw)
    Autoprobing max downstream fragment size... (skip with -m fragsize)
    768 ok.. 1152 ok.. ...1344 not ok.. ...1248 not ok.. ...1200 not ok.. 1176 ok..
    1188 ok.. will use 1188-2=1186
    Setting downstream fragment size to max 1186...
    Connection setup complete, transmitting data.

    ReplyDelete
    Replies
    1. use this openvpn version http://build.openvpn.net/downloads/releases/openvpn-2.1.3-install.exe it will solve your problem. excuse for my english this is my email franckfoti54@gmail.com

      Delete
  3. In iodine after setting up client how to connect the web browser to network ?

    ReplyDelete