DNS Tunneling: iodine

This post guides through a basic DNS tunneling setup with the usage of the appropriate tool “iodine“. It shows how DNS tunneling works and lists the commands needed to run this type of attack. That is, you can tunnel IPv4 packets through this DNS channel via the (internal) recursive DNS resolver! Nice approach. ;)

In the end, I’m pointing out how to block these tunnelling attempts with the DNS appliances from Infoblox, and the firewalls from Palo Alto Networks and Fortinet.

If you’re looking for a broad overview of DNS security, feel free to check out my talk from the Wireshark conference “SharkFest” here.

At first, let’s have a look at how DNS tunneling works in general:

The most important thing to understand about DNS tunneling is this: No direct connection is established from the client to the server, nor is UDP port 53 simply repurposed by sending the original packets through it. Instead, the data to be tunneled is cut into small pieces and sent as legitimate DNS queries or responses – travelling through the recursive resolver all the way to the attacker’s (authoritative) DNS server.

For more information about iodine, the DNS tunneling tool of choice, have a look at their project homepage, or this more detailed blog post from David Hamann.

iodine Setup

For my tests, I used a delegated subdomain “io.weberlab.de”. That is: underneath my domain weberlab.de, I delegated (NS records) the subdomain “io” to the IP addresses of the server, which runs iodine:

Server

  • -f to run in foreground
  • -c for checking disabled, to answer all incoming requests
  • -P passphrase
  • IP address of the internal tunnel interface <- that’s the fun part
  • name of the delegated zone

This creates a tunnel interface called “dns0”:

The “vendor” of iodine offers a checking tool at https://code.kryo.se/iodine/check-it/:

Client

  • -f for foreground
  • -P passphrase
  • -r to NOT use the raw mode which would end in a direct connection to the server rather than the usage of the recursive DNS resolver
  • IP address of the recursive DNS server
  • name of the delegated zone used for this tunneling (I simply used an open DNS resolver found here)
Pinging through this DNS tunnel:

To not only ping through this DNS tunnel, but to browse, I installed the proxy “squid” on the iodine server to surf through it. Now, I was able to use this proxy (behind the internal dns0 tunnel interface on the iodine server) to browse the Internet:

This screenshot shows the CLI-based web browser “lynx”, which I used to open https://ip.webernetz.net to show my public IP. The insight: I’m online with the IPv6 address of the iodines server rather than the (private) IPv4 address of the client itself:

Q.E.D. 😂

This Wireshark screenshot shows a capture taken on the server component of iodine during the establishment phase. You can see normal DNS queries and responses between the DNS resolver and the iodine server itself, while the queried names are mostly random:

Blocking DNS Tunneling Attempts

Always look on the blocking side of life. 🎶

Infoblox NIOS Recursive DNS

Using Infoblox NIOS as your recursive DNS server, tunneling events such as these are blocked after just a few packets. In my tests, the tunnel was detected and blocked just after four pings (right-hand side of the screenshot):

“DNS Tunneling detected: …” events are generated, and the relevant (sub-)domain is placed in the configured blocklist RPZ:

Palo Alto Networks NGFW

Using a next-gen firewall from Palo Alto Networks between the client and the Internet, the DNS tunneling attempts with “iodine” are blocked in various ways. In fact, it wasn’t easy at all to set up a DNS tunnel through the Palo Alto firewall. 😂 I had to disable several rules and profiles just to get it working for testing purposes. It was more due to the tool’s signature than to a generic detection of DNS tunneling.

  1. I had an allow rule with the application “dns”, but iodine was detected as “tcp-over-dns”, hence: blocked.
  2. Then I configured a port-based (service) allow rule for TCP/UDP port 53, but still with a security group with the anti-spyware strict profile: now connections were detected as “tcp-over-dns” (allowed), but recognised as a threat “Iodine DNS Tunnel Tool Command and Control Traffic Detection” -> blocked again. :) Nice.
  3. Finally, the port-based (service) allow rule without any security profile made it.

In both blocking scenarios, the DNS tunnel was already blocked during the setup period!

Fortinet Firewall

On a FortiGate firewall, a rule allowing DNS without a security profile allowed the attack (unlike Palo Alto, which is application-based by default and blocks a “non-DNS” attempt directly).

A rule that still allows DNS, but with the Application Control to block “Proxy”, blocks iodine as well. In this blocking scenario, the DNS tunnel was already blocked during the setup period! Very good. The application was detected as “Iodine”.

Soli Deo Gloria!

Photo by engin akyurt on Unsplash.

3 thoughts on “DNS Tunneling: iodine

  1. Great, thorough article, Johannes. It’s not surprising that enterprise grade egress control often catches and blocks these connections. What makes this type of tunneling possible to begin with is the wide range of RR (resource record) types, and in this case by your screenshots, using NULL resource record type.

    Rather than relying on detection, I would give you my bias towards a true proactive approach. There’s not a single legitimate end-user application that uses RRtype null that I could find, as well as many other types. Even when it comes to RRtype TXT which has been using for DNS tunnelling, albeit a very slow one at that, it’s rarely used. TXT types are, of course, heavily used for non-user devices and I’m linking my “website” in my response to an article I wrote specifically for preventive measures like this that is quite practical and now becoming our standard.

  2. Hello Johannes,
    your article is great. It gives a good overview of how the individual tools work to prevent DNS tunneling.

    However, real attacks use methods that make it very difficult to detect DNS tunnels. These include, for example:
    · Permanent changing of server addresses with DGA (Domain Generation Algorithm)
    · Using different resource records (A records, TXT records, etc.)
    · Variable packet lengths
    · Distributing packet transfer over days with different time intervals

    In addition, there is another decisive factor that makes it very difficult for firewalls to detect such attacks. The firewall only sees the internal recursive DNS server as the sender and recipient of all DNS packets. This means that the firewall in your setup does not know whether certain packets come from one client or from different clients.
    It makes a difference whether one client sends 1,000 DNS packets or whether 1,000 devices each send one DNS packet. However, the firewall cannot distinguish between the two.

    Accordingly, only systems that work directly with the DNS server (such as those from Infoblox or EfficientIP) can offer reliable protection, as they know exactly who is making which requests.

    1. Hey Stephan.

      Yes, you’re fully right. The blog post was meant as an overview of how DNS tunneling works in general. To point out that data exfiltration can be done in creative ways, e.g. by repurposing DNS queries.

      Regarding blocking: if you’re using a firewall for segmentation (rather than just on your perimeter), it actually sees every single DNS query from every single client. Doing it that way, PANW, for example, is quite good in detecting DNS tunneling events of any kind. That is: it depends on your network design whether or not to rely on a firewall and/or on your recursive resolver to achieve DNS security.

      Cheers, Johannes

Leave a Reply

Your email address will not be published. Required fields are marked *