Tunnel IP through DNS
Have you ever been somewhere that offers 'free' Wifi? Only to find that it's not free?
This page is for you! This page is also for educational purposes only...
This technique will tunnel IP out via DNS queries (sounds crazy, doesn't it?)
Once you're connected to the network, you need to ensure that you can access the internet.
Any HTTP traffic will be redirected to the login page, but you might find that DNS requests can get out!
google.com and see what happens...
If you get an IP back, you're probably good to go.
Setup and Configuration
You'll need to have access to a domain that you can configure, and you'll need to do the following.
Say your domain is
- Add a new NS record,
x.example.com, and point it at an A record
- The A record needs to point to a machine that you control, if necessary add a record, and configure Dynamic DNS (for example
This says: "for any DNS queries related to x.example.com, ask xn.example.com"
This is a handy little tool (available as
iodine on Ubuntu) that comes in two parts - Server and Client... Duh...
The Server is what you want to run on
You'll need to open port 53 (DNS) in any firewalls and you'll need to run iodined like so:
sudo iodined -b 27001 -f 10.0.0.1/24 x.example.com
-b 27001- forwards any DNS queries that aren't for
localhost:27001(if you have any DNS servers on the machine already, remember to move or stop them)
-f- keeps iodined running in the foreground
10.0.0.1/24- is the IP and subnet for the TAP that will be created - any incoming connections will get an IP address in this range
x.example.com- is the FQDN that has the NS record
ifconfig on the server should give you an entry like this:
dns0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet addr:10.0.0.1 P-t-P:10.0.0.1 Mask:255.255.255.0 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1130 Metric:1 RX packets:5721 errors:0 dropped:0 overruns:0 frame:0 TX packets:6182 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:500 RX bytes:885994 (885.9 KB) TX bytes:2916389 (2.9 MB)
Once your server is setup and running, you can have a play with the client. Run it like this:
sudo iodine x.example.com
You can use the information that is output at startup (while the link is being negotiated) to make the startup quicker:
sudo iodine -TNULL -r -m226 -OBase64u -L0 xn.example.com x.example.com
-TNULL- use DNS query type NULL
-r- skip RAW UDP mode
-m226- set a fragment size of 226 bytes
-OBase64u- force the downstream encoding type to base64u
-L0- force legacy (non-lazy) mode
xn.example.com- the name server to query (optional)
x.example.com- the FQDN to use
ifconfig on the client should give you an entry like this:
dns0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet addr:10.0.0.3 P-t-P:10.0.0.3 Mask:255.255.255.0 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1130 Metric:1 RX packets:230 errors:0 dropped:0 overruns:0 frame:0 TX packets:196 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:500 RX bytes:163067 (163.0 KB) TX bytes:26077 (26.0 KB)
Using the Tunnel
Now you should have a link up and running.
Don't forget that your routing will need adjusting (away from the 'pay me' default). This might be helpful: Route
You could also easily use ssh to forward ports and give you encrypted and compressed transport through this DNS tunnel(!) For example, if you have a proxy running on your server on port 8080, do this:
ssh email@example.com -L8080:localhost:8080
The previously mentioned configuration results in a painfully slow link... And I mean slow (around 16-24kb/s). But at least it's a link!
Okay, so I lied. You might not need to setup any DNS records, but it certainly makes it easier, and if you don't have a static IP, then it sorta' makes it possible.
You might see something like this if you don't setup DNS records:
$ sudo iodine 184.108.40.206 google.com Enter password: Opened dns0 Opened UDP socket Sending DNS queries for google.com to 220.127.116.11 Autodetecting DNS query type (use -T to override).......iodine: Got NXDOMAIN as reply: domain does not exist .iodine: Got NXDOMAIN as reply: domain does not exist .iodine: Got NXDOMAIN as reply: domain does not exist .iodine: Got NXDOMAIN as reply: domain does not exist .iodine: Got NXDOMAIN as reply: domain does not exist ..iodine: Got NXDOMAIN as reply: domain does not exist .iodine: Got NXDOMAIN as reply: domain does not exist .iodine: Got NXDOMAIN as reply: domain does not exist .iodine: Got NXDOMAIN as reply: domain does not exist .iodine: Got NXDOMAIN as reply: domain does not exist . iodine: No suitable DNS query type found. Are you connected to a network? iodine: If you expect very long roundtrip delays, use -T explicitly. iodine: (Also, connecting to an "ancient" version of iodined won't work.)
Running Without DNS Records
If your server's IP was 18.104.22.168, then you could run the following server command:
sudo iodined -b 27001 -f 10.0.0.1/24 google.com
And client command:
sudo iodine 22.214.171.124 google.com
You do however still need to open port 53.
So using a proxy is okay, but it would be much nicer to route the traffic properly... and therefore not rely on proxy configurations.
To set the scene, I have a Windows laptop with a Linux VM on it, and a Linux server.
Start iodined on the Server
sudo iodined -b 27001 -f 10.0.0.1/24 x.example.com
NAT dns0 Traffic onto eth0 on the Server
echo 1 > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE iptables -A FORWARD -i eth0 -o dns0 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i dns0 -o eth0 -j ACCEPT
Start iodine on the VM
sudo iodine -r x.example.com
Route All Traffic Throuh dns0 on VM
route del default route add default dev dns0 gw 10.0.0.1
NAT eth0 Traffic onto dns0 on the VM
echo 1 > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -o dns0 -j MASQUERADE iptables -A FORWARD -i dns0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i eth0 -o dns0 -j ACCEPT
Route All of the Laptop's Traffic Through the VM
route delete 0.0.0.0 route add 0.0.0.0 MASK 0.0.0.0 192.168.174.129
The Full Chain
- On my lap, is the Laptop. Traffic is routed into the VM
- The traffic arrives at the VM on eth0, it is NAT'ed through to dns0, and pushed through the tunnel
- The traffic arrives at the Server on dns0, is NAT'ed through to eth0, and reaches a network with internet access
Remember, I've not mentioned anything about DNS servers in this section... That's because we can use the 'free' Wifi's DNS servers just fine, and it'll be quicker to perform lookups through that instead of wasting tunnel bandwidth on lookups.