Tunnel IP through DNS

From Attie's Wiki
Revision as of 01:56, 26 November 2013 by Attie (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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...

Contents

Groundwork

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! Try resolving google.com and see what happens...

If you get an IP back, you're probably good to go.

Setup and Configuration

DNS

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 example.com.

  1. Add a new NS record, x.example.com, and point it at an A record
  2. The A record needs to point to a machine that you control, if necessary add a record, and configure Dynamic DNS (for example xn.example.com)

This says: "for any DNS queries related to x.example.com, ask xn.example.com"

Note: Your Wifi provider will see a LOT of DNS queries to this domain name. Be careful, remember that they can do a WhoIs any time.

Iodine

This is a handy little tool (available as iodine on Ubuntu) that comes in two parts - Server and Client... Duh...

Server

The Server is what you want to run on xn.example.com. 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 x.example.com to port 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

Running 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)

Client

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

Running 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 attie@10.0.0.1 -L8080:localhost:8080

Evaluation

Throughput

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!

DNS

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 12.34.56.78 google.com
Enter password:
Opened dns0
Opened UDP socket
Sending DNS queries for google.com to 12.34.56.78
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 12.34.56.78, 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 12.34.56.78 google.com

You do however still need to open port 53.

Extension!

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

Note: This is a Windows laptop...
route delete 0.0.0.0
route add 0.0.0.0 MASK 0.0.0.0 192.168.174.129

The Full Chain

  1. On my lap, is the Laptop. Traffic is routed into the VM
  2. The traffic arrives at the VM on eth0, it is NAT'ed through to dns0, and pushed through the tunnel
  3. 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.

Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox