I recently set up DNS Tunneling on one of my VPSs. This technology is incredibly useful for bypassing captive portals, filters etc. as DNS is required for internet usage so egress on port 53 is almost always allowed on a network.
While sometimes these DNS requests are restricted to whitelisted servers or only for specific domains you will usually find that DNS is completely unrestricted and as always, if we control both ends of the pipe then we can tunnel data through it.
We could just set up an SSH server or similar on port 53, but in some cases the protocol will be filtered and your tunnel will fail. Tunneling over DNS then, seems like the best option.
Iodine
To do this, we're going to use a tool called iodine. Iodine consists of a DNS daemon we run on our server that listens for incoming DNS requests and unwraps the tunneled data. We then have a client that we run on the, well, client, that handles the other side.
The client sets up the tunnel and exposes the server as a new tunneled IP. We can then use this normally, but for full tunneling we'll want to connect to it using SSH to set up a dynamic proxy. So technically we're going to set up an SSH tunnel over a DNS tunnel!
Registering your DNS server
The first step will be to register our server as a DNS server. To do this we'll need a domain. GoDaddy has some cheap domains and has a privacy option so that our personal details aren't exposed by whois
domain lookups.
Once we have a domain we must enter an NS record for it in the domain control panel such as:
t1 IN NS ourdomain.com. ; note the dot!
If you already have a domain and want to use a different server for your iodine server, you can set up a subdomain first and register the IP of the iodine server, then point the NS record to this subdomain instead.
t1 IN NS t1ns.ourdomain.com.
t1ns IN A <iodine-server-ip>
This can take some time to propagate, but while it's doing so we can spend some time...
Setting up the daemon
The next step is to install iodine on the server. If you're using a debian-based distribution like me you can just do this using apt install iodine
.
We can run the iodine daemon using the following command:
iodined -fcP secretpassword 10.0.1.1 ourdomain.com
where
-f
option tells it to run in the foreground-c
disables checking the client IP address on all incoming requests, which can avoid some issues-P secretpassword
details the shared secret between the client and the server for authentication10.0.1.1
is the IP the server will be given on the client on the tun interface. The client will be given the next IP in the range.ourdomain.com
is the domain name of the DNS server we set up earlier.
Alternatively, if we want to set up iodine to run on start up you can enable the service using:
update-rc.d iodine enable
and
service iodine start
to start the service now. This will silently fail however until we set up the arguments to the daemon in the /etc/defaults/iodine
file. In this file, we have to set
START_IODINED
to trueIODINED_ARGS
to -c 10.0.1.1 ourdomain.comIODINED_PASSWORD
to secretpassword
Running the process as a service has the added benefit of running as the iodine user, which was added during its install.
Checking the config
Once everything is in place, we can check our config using the iodine check page.
If everything looks correct but it's still not working, check that our traffic isn't being caught by any firewalls etc on the server.
Running the client
On the client machine we then just have to run the iodine client. We can install iodine in the same manner as above and then run:
iodine -fP secretpassword ourdomain.com
and we should see some output followed by Connection setup complete, transmitting data.
The server is then exposed locally on the tun interface with the ip 10.0.1.1. Our DNS tunnel is complete!
Setting up the proxy
In order to have our browser or other tools use the tunnel, we have to set up a proxy. We're going to use SSH dynamic port fowarding to create a SOCKS proxy locally that will tunnel all traffic over SSH to our server, with SSH using the DNS tunnel.
Needless to say we'll need an SSH daemon running on our server. I'm going to assume that's already the case and if not there are plenty of guides already out there on how to do that.
We can then set up the proxy by issuing:
ssh -N -D 8080 [email protected]
where
-N
instructs SSH not to start a shell, as we're just wanting to create the proxy-D
sets up the dynamic port forwarding, with the SOCKS proxy on port 8080user
is a user on our server10.0.1.1
is our iodine server on the tun interface
Once this is done, we can just use the proxy in our browser. This can be done using, for example, the FoxyProxy extension in Firefox or Chrome. If all is successful, you should be able to check your IP in the browser and get back the IP of your server.
Winning
From here we're good to go! We can crack open a beer, sit back and enjoy our tunneled internets.