When the Internet access is firewalled, but you badly need to transfer data, DNS tunneling comes to the rescue. Even at the strictest settings, DNS queriescan sometimes be allowed, and we can use this by responding to them from our server on the other side. The connection will be very slow, but this will be sufficient to penetrate into a local network of an entity or, for example, to urgently access the Internet through paid Wi-Fi abroad. Let's have a look at the utilities that will help you in such a situation, as well as their pluses and minuses.
Here is a general diagram that demonstrates what we will do. Roughly, the theory is trivial here: even if there is no way out, requested URLs should be resolved, so often DNS is not limited. This enables though a small but working loophole.
Now you can find on the Internet a lot of DNS tunneling utilities — each one has its own features and bugs. We have chosen the top five most popular ones for comparison testing.
dnscat2 is a rather popular utility developed by Ron Bowes to create a command and control channel (C&C) for malware over the DNS protocol. It consists of the server written in Ruby and the client written in C. There is a PowerShell version of the client for Windows.
Dnscat2 uses hex encoding. Data is transported in strings, this means that
AAAA is equivalent to
AAA.A and so on.
Also, this protocol is not case-sensitive, so
A1 are the same. To use this utility, the user should have the authoritative server for the domain with NS records referring to a particular machine. The client can choose whether to append a domain name or to prepend the
dnscat. tag to a message when sending data.
Messages are represented as
<encoded data>.<domain> or
<tag>.<encoded data>. In case data is presented in another form, transferred in an unsupported record type or has an unknown domain, the server can discard such data or forward it to an upstream DNS server.
Dnscat2 supports the main types of DNS messages: TXT, MX, CNAME, A and AAAA.
The response type corresponds to the incoming request type:
- A TXT response is the hex-encoded data;
- CNAME and MX are encoded in the same way as the request: either with a tag prefix or a domain postfix. This is necessary because intermediate DNS servers will not forward the traffic if it does not end with the appropriate domain name.
- A and AAAA are the same. TXT, the raw data without any domain or tag added.
A session is established by the client that sends a SYN packet to the server. The server responds with a similar packet. The client and the server communicate using MSG packets. When the client decides that a connection is over, it sends a FIN packet to the server and the server responds in the same way. When the server decides that connection is over, it responds to a MSG from the client with a FIN packet and the session is finished.
It may be noted among specific features that the dnscat2 server can maintain several sessions and supports basic cryptography (without any reliability guaranteed).
You can learn more about the protocol and specific features of this utility in the developer’s repository.
Following the GitHub instructions, let's assemble everything we need and try to start it. First off, we will track on the server what will be happening on port 53. Let's enter the following command for this.
Now, let's start the server. We specify only a domain name in the arguments, because we are not interested in direct IP specification.
We are starting the client in the same way and see that the session has been established. Excellent, it seems working!
We see the following on the server.
Excellent, let's enter the session!
Let's see what this utility gives us.
Fine! Let's run a shell to check.
Great! A shell session has been created, though we have received “а bad sequence”, rather than a message.
We are pressing Ctrl-Z to exit the session and are going to session 2.
Let's create a file and write down a text into it, after that we will display the content and delete it.
You have to press Enter once again after obtaining the result to create a new command. Of course, the process is not interactive, but that's okay.
It's all fun, but we have to build a tunnel anyway. Let's try to download the file using SCP from some server through the client, at the same time we will check the average speed.
Now, we are building a tunnel.
We specified in the client's session that it is necessary to listen to port 9090 on the server's side and to forward traffic from the client to `188.8.131.52:22`.
Now, let's start SCP. You can see communication between the client and the server in tcpdump.
In the end, we got an average speed of 0.8 kbyte/s — of course, not enough to see 4K movies, but we managed to tunnel the traffic after all.
Let's have a look what’s about downloading there.
As we can see, although the speed was about 10 kbyte/s, but in fact the utility worked too slowly.
Now we started the client in Kali, let's see how it works in Windows.
Everything is sad here. During the same experiment, the client eventually managed to establish a connection, though this took a countless number of attempts.
But the client suddenly lost connection when trying to tunnel SCP.
Eventually, I did not even manage to measure the channel's average speed. The client was tested in Windows 7 and 10 with the same results.
At last, let's have a look at the PowerShell client. To do this, we have to restart the server using the
Finally, we managed to start the client and even to make it friends with the server for some time.
At one point, we even obtained this.
However, in most cases this led to the situation shown below.
- Simple set-up
- A large set of functions
- Support of several sessions
- Compilable clients
- Unstable work in Windows (if it can be called work at all)
- Download speed ~ 0.6–0.8 kbyte/s
- Upload speed ~ 10 kbyte/s, but with a strange delay
Iodine is a utility developed by Erik Ekman. It enables to tunnel IPv4 traffic over DNS using virtual interfaces. It consists of the compilable server and client written in C. Clients can be started only with root privileges.
Iodine clients can work on different architectures (ARM, IA64, x86, AMD64 and SPARC64) of multiple OSs: Linux, FreeBSD, OpenBSD, NetBSD, macOS and Windows (with OpenVPN TAP32 driver).
To install Iodine on a server, it is enough to run this command
$ sudo apt-get install libz-dev && git clone https://github.com/yarrick/iodine.git && cd Iodine && make && make install
$ sudo ./iodined -f -c -P secretpassword 172.17.0.1 oversec.ru
You should write something like this to start working with the client
$ ./iodine -f -P secretpassword oversec.ru
Now, there is a dns0 virtual interface on the client, the client will obtain an IP address. You can address this IP and traffic will be tunneled through DNS.
Let's try to connect through SSH.
$ ssh email@example.com
It works! This is what TCPDump shows on port 53 of the Iodine server.
Iodine can independently choose the fastest available encoding type (Base128, Base64, Base32) and packet type (NULL, TXT, MX, CNAME and A), thanks to which the speed is high — about 10 kbyte/s when using SCP.
Let’s test the client for Windows. First, you should install TAP/TUN interface drivers for this. Then we start the application, in the same way as in Linux — using the administrator’s account.
It seems like the interface has been successfully set, but nothing happens when trying to transmit data.
So we did not succeed in starting the Iodine client in Windows.
Let's test the sending and receiving speed.
As we can see, the speed is excellent for the DNS tunnel: 9.8 Kb/s for sending and receiving through SCP.
- Autoselection of encodings and packet types
- Can be run only as root
- Compilable client
- Necessity to install drivers in Windows (and doubts about possibility to work with this system)
- Download speed ~ 9.8 kbyte/s
- Upload speed ~ 9.8 kbyte/s
dns2tcp is a tool for relaying TCP connections over DNS. The client and the server are compilable, the server is also available through APT. The utility's specific feature is that it tunnels traffic from the client to the server.
To begin, let's set up the server. First, let's edit the file
Now, start the server itself with a command
dns2tcpd -f /etc/dns2tcpd.conf
Okay, now let's take the client.
We specified here that we would tunnel SSH (a mode for SMTP is also available), specified the port that we would try to access, and of course the domain itself.
Come on, let's download this file.
And check downloading at the same time.
- Compilable server and client
- It works in the “inward” tunneling mode
- Average download speed ~ 5 kbyte/s
- Average upload speed ~ 13 kbyte/s
[Heyoka](https://github.com/xant/heyoka-unix; http://heyoka.sourceforge.net) is a utility written in С, and its client and server are the same executable file. It creates a bidirectional DNS tunnel. According to the authors, this utility works 60% faster than the other similar tools (as at 2009). A ready-to-use executable file is available on the project's website, and a version for Unix made by a third-party developer is placed on GitHub.
After reading description and instructions on the website, let's try to tame this racer. Let's begin with starting the server in Windows 10.
Excellent, it seems working. Now, let's start the client.
Oops! It seems not working, although it was started with the admin’s rights.
Well, now let's assemble the tool for Unix. We are starting the server in the same way and testing the client.
We did not manage to start the client following the instructions from the developer’s website, and it is almost impossible to make heads or tails of the source code and protocol. So let's go to the next tool.
A rather old tool to create DNS tunnels through SSH, which was written by Dan Kaminsky back in 2005.
To begin using it, you should install Perl and MIME::Base32 and Net::DNS libraries as well as update the packet manager.
$ sudo perl -MCPAN -e shell cpan> install CPAN cpan> reload cpan cpan> install MIME::Base32 cpan> install Net::DNS
Downloading the archive:
$ wget https://github.com/mubix/stuff/blob/master/stolen/ozymandns_src_0.1.tgz?raw=true
$ tar -xf ozymandns_src_0.1.tgz?raw=true
If you try to start the script right now, it will more than likely crash showing an import error. To fix that, you need to delete the selected fragment from the file nomde.pl.
The server can be started very easily:
$ perl ./nomed.pl -i 0.0.0.0 oversec.ru
If import errors occur, try installing missing packets through CPAN.
Starting the client:
$ ssh -D 8080 -C -o ProxyCommand="perl droute.pl lol.oversec.ru" oversec.ru
We see an error: Perl is not satisfied with DNS servers’ addresses. Trying to specify ours:
$ ssh -D 8080 -C -o ProxyCommand="perl droute.pl -r 184.108.40.206 lol.oversec.ru" oversec.ru -v
We see that it recognizes the server but connection is not established.
Impressed by articles and videos where people demonstrate how perfectly it works, we have spent several days fiddling with OzymanDNS, but we never managed to make this tool tunnel at least a bit of information. Maybe, some readers will have enough patience, but will it make sense? For those who [managed to connect through OzymanDNS] (https://cyberphob1a.wordpress.com/2008/02/10/dns-tunneling-part-i/) the speed was 17 kilobit/s and the work was unstable, and, given a poor set of features, you can safely move from this utility to something else.
Thus, we have considered the best known DNS tunneling utilities. It is clear that there are much more solutions and you can find a lot of alternatives on the Internet. But now we have at least some options to choose from.
|Name||Incoming speed, kbyte/s||Outcoming speed, kbyte/s||Advantages||Disdvantages|
|dnscat2||0.7||10||Simple set-up, broad set of functions, support of several sessions||Compilable clients, unstable work in Windows|
|iodine||9.8||9.8||Autoselection of encodings and packet types, high working speed||Start-up only with root privileges, compilable client, necessity to install drivers for Windows|
|dns2tcp||5||13||Not found||Compilable client, works in the “inward” tunneling mode|
|heyoka||NaN||NaN||Not found||Difficult start-up|
|OzymanDNS||NaN||NaN||Not found||Difficult start-up|
As a result, the most common issue is a necessity to compile the client and unstable work in Windows. Is there any workaround? We will discuss this next time! :-)