DNS Tunneling w/ Iodine

Disclaimer: Using tools such as the ones described in this guide for the purposes of overcoming company policies is illegal and unethical. The techniques presented here were conducted for proof of concept only and the possible loophole, if any, was reported to the respective authorities.

After taking the undergraduate Computer Security class at Berkeley (CS161) I wanted to apply what I learned to practice. Having learned about DNS and DNSEC packets we were told to look into iodine as a way to expand on these principles. Iodine is an open source tool written by yarrick for easy DNS tunneling. It can embed TCP traffic in DNS packets so that they don't get filtered by firewalls. Most paid internet services like the ones at cafes or on airplanes simply block TCP packets going to/from your MAC address until you pay. However, they occasionally leave DNS open (port 53) so that they can redirect you to their payment page. The fact that DNS packets get sent out to the internet no matter what leaves a backdoor open to the web.

The following steps are a guide to setup iodine without any cost (server and software can be accessed for free). This methodology has been proof tested out in the open and is confirmed working in multiple scenarios. But again, even though it might be possible, you should not use such a tool for your own benefit.

0. Remarks

This guide assumes you read the documentation at given external links and have prior experience with Linux and the terminal. If you are stuck at any point feel free to shoot me an email. Also, steps 1-3 (inclusive) require internet access while the remainder can be performed behind a firewall.

1. Get A Server

If you have a server with a public IP address you can skip this step. For the purposes of this guide, we will use a Linux Red Hat distribution server. You can get a free server from AWS (the signup requires a credit card and a phone number for verification but you don't get charged and don't need a student discount). Once you have an account go ahead and create an EC2 instance picking Red Hat Linux as the operating system. You can SSH into your server (once it's ready) using a command similar to the following:

ssh -i IodineDemo.pem ec2-user@xxx.compute.amazonaws.com

2. Setup your domain

You need to own a domain for this part. Any domain works. If not yarrick recommends the following:

If you don't have a domain, it seems you can get a free subdomain with DNS control capable of NS records at http://freedns.afraid.org/

Assuming you have access to a domain control panel you need to pick a short subdomain to be your tunnel domain. I will use t.duman.me here since I own duman.me and t is the abbreviation for tunnel. Add an A record that points the tunnel domain (t.duman.me) to the IPv4 address of your server (such as 34.210.28.116). Then add an NS record that points the tunnel domain to the public IP of your server (can be IPv6 or IPv4, such as xxx.compute.amazonaws.com). After making sure that the DNS cache is updated (you can run dig in the terminal to check this), head over to this link and type in your tunnel domain. The page will tell you if your domain is setup correctly. At this point, all DNS queries for subdomains of your tunnel domain (for example, abc.t.duman.me) will be directed to your server. And this is how we will port information to our server even when behind a firewall.

3. Install Iodined on the Server

SSH into your server and run the following commands. If you are using Ubuntu instead you can substitute apt-get for yum.

sudo yum install git gcc make zlib-devel screen
git clone https://github.com/yarrick/iodine.git
cd iodine && sudo make install && cd bin
screen -R iodine
sudo ./iodined -f -c -P myPass 10.0.0.1 t.duman.me

This will run the iodined server in a screen (like a new tab in terminal) so that when you close your terminal (or loose connection to the server) the process does not terminate. For the last line make sure to choose a secure password and replace t.duman.me with your own tunnel domain. Once you see the string Listening to dns for domain t.duman.me displayed in the console you are good to go. You can leave the screen by hitting Ctrl+A+D or stop the iodined instance by pressing Ctrl+C. When you reconnect to your server using SSH you can access the same screen using the following command:

screen -x iodine

The iodined server will run continually and accept connections from multiple clients until you terminate it.

4. Install Iodine on the Client

Now that the server side is up and running we can connect to it from the client (aka your laptop behind the firewall). Run the following commands in your laptops terminal:

FILE="localhost 127.0.0.1\nnameserver $(scutil --dns | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | head -1)"
echo $FILE | sudo tee /etc/resolv.conf
sudo iodine -f -P myPass t.duman.me

Again, for the last line use your password and your tunnel domain. The first two lines read the DNS Resolver IP as indicated to your laptop by the DHCP response from the WiFi network and write it to resolv.conf. These two lines are only necessary because newer versions of macOS don't update this file automatically. You can try leaving them out first and see if it works that way. Once you see the string Connection setup complete, transmitting data the client is connected to the server. Make sure not to close the current terminal tab or press Ctrl+C as these actions will break the connection. If you want you can install screen locally and run this process in a screen instance.

5. Setup SSH Tunnel

We can now connect to the server using SSH by only sending DNS packets. The server will appear on our local network thanks to iodine. Run the following command to setup an SSH tunnel on port 9999:

ssh -i IodineServer.pem ec2-user@10.0.0.1 -D 9999

You should also keep this terminal tab open for the connection to persist. At this stage we are using port 9999 to talk to the server and iodine is forwarding all our communication through port 53.

6. Tell Chrome to use SOCKS proxy

We need to tell Chrome to use the tunnel when sending HTTP requests. This can be achieved by downloading the Chrome Plugin SwitchyOmega. Head to the plugin options page and create a new profile with the following properties:
Profile Name: DNS Tunnel
Protocol: SOCKS5
Server: localhost
Port: 9999
After applying your changes you can use the plugin icon to switch to the profile you created and every page you load after this point will be forwarded through iodine.

7. Profit

Now you can surf the web freely (even establish TLS connections) behind a firewall as described in the introduction section. The connection speed will be slow as DNS packets are not large in size by nature. You can fine tune the iodine flags to optimize your speed. Make sure to switch back your SwitchyOmega profile to default and terminate the SSH tunnel and iodine instance once you are done testing the tool.

This is my first blog post! Let me know what you think below.


FAQ
Getting many SERVFAIL errors? Try using the flag -L0 when launching iodine.
Can't point a NS record to IPv6? Ask your domain service provider to do it for you manually.