Note: I haven't tried this, but I can tell you it surely works because I have a friend of a friend of a friend of a friend of a friend of a friend of a friend of a friend that tried it this way and it works.
Note 2: You might get into a lot of trouble doing this, but that's your problem, not mine.
Basic knowledge
The i-Choice platform is used to connect users to a common network owned by a LEC in Cyprus in order to select their preferred ISP and connect from their onwards. It works using a website you have to visit before you connect to the Internet; probably most of you know about it, it's http://www.i-choice.com.cy (doesn't work if you click on it from outside the CyTA LEC network).
After you login to the site you have an ISP selection menu on your left. You click on the ISP you want to connect to and it brings up your preferred ISP login page where you have to enter another set of authentication details (username and password) for your ISP to permit access to the Internet via their service.
Once you have done all the above, you get a working Internet connection. Sounds like a lot of work to get on the 'net don't you think?
Advanced knowledge
The i-Choice platform is fairly simple in function. It uses internal IP addressing (10.x.x.x) which is assigned to the WAN interface of your home DSL gateway/router/modem/cpe and routes you all the way to your ISP with that private address. It is your ISP's obligation to perform network address translation in order to ensure anything reaching your external IP which is provided by your ISP to translate at a specific network boundary to an internal IP address representing your connection on the i-Choice network.
When you do login to the i-Choice website and click on an ISP link from the available carriers in the menu on the left, technically speaking, i-Choice's systems add a route in their local gateway that makes sure you are able to reach the destination network (the ISP you clicked on). So if you clicked on ISP A, the local gateway is given instructions to route your traffic to that particular ISP. Then the ISPs respective login page comes up.
When the page does come up, usually ISPs don't have a NAT configuration for you to provide translation from your private IP to your real IP. The reason being, IP addressing is not entirely static within the i-Choice platform and more importantly, your ISP has to identify you as a valid user before they give you a NAT entry in their own systems so you can be routed to the Internet. So this is where you would usually hit a brick wall if you are trying to get something for nothing.
Traffic that can go through
When you login on the i-Choice page and click on your preferred ISP, before even providing your authentication details you can actually reach your ISP's DNS servers directly without the need for a public (real, translated) IP address from your ISP. This essentially means that you can issue DNS requests to your ISP's nameservers without Internet access (nat translation). And this is where it all goes sour.
DNS Tunneling
DNS tunneling is far from a new method of tunneling IP traffic. In fact, it is roughly 10 years old. Slashdot wrote an article about it in 2000! The concept is simple. You have a domain. You delegate that domain with a name server which sits on the outside of the i-Choice and ISP network , meaning the Internet, and you run a modified DNS server on that machine.
In effect, the primary nameserver for your domain (let's say xyzbypass.com) would be your server on the outside (let's say 6.6.6.6). The concept simply put is that you will have a modified dns client that creates specially crafted DNS packets that ask for details regarding records from xysbypass.com. These requests are sent to your ISP's nameserver which you can request records without logging in (but clicking on the ISP link in i-Choice of the corresponding ISP).
The first time you do this, your ISP's nameserver (let's say 5.5.5.5) will lookup the nameservers for xyzbypass.com. The nameserver will naturally forward your request to the nameserver for xyzbypass.com which is in fact our modified name server with the IP packet in the data itself.
The nameserver will receive this packet and handle it accordingly. To represent this "tunnel" that exists via DNS between yourself and the modified nameserver, a pseudo interface is created with a pseudo IP address. This means that your IP traffic which is encapsulated over DNS is transported via your ISP's nameserver to the nameserver responsible for xyzbypass.com which in due turn forms the transport for your IP traffic over the tunnel. You can then NAT (masquerade) the DNS interface on the remote DNS machine to the outside interface. By employing specific routes from your local machine running the origination of the DNS tunnel you can then point your internet traffic towards the other end of the DNS tunnel in order to have a functional Internet access via the tunnel itself.
The following diagram illustrates the network depiction graphically.

To further prove that your ISP's DNS servers will in fact fetch DNS traffic on your behalf, a simple nslookup command can be used.
root@neptune:~# nslookup
> server 5.5.5.5
Default server: 5.5.5.5
Address: 5.5.5.5#53
> blogger.com
Server: 5.5.5.5
Address: 5.5.5.5#53
Non-authoritative answer:
Name: blogger.com
Address: 74.125.91.191
Name: blogger.com
Address: 209.85.165.191
Name: blogger.com
Address: 74.124.127.191
>
By using the server command, you effectively perform the lookups directly at the specified nameserver. You should perform this while not being logged on to your ISP but having clicked on the preferred ISP in the i-choice page.
Practical implementation
The theory should be relatively clear by now. Let's get into the practical part, followed by a discussion on fine tuning the tunnel and enabling Internet access via the DNS tunnel.
One of the most well known but fairly outdated implementations is NSTX. NSTX however has somewhat disappeared from the scene. A new tool called "iodine" is available and it offers additional features such as authentication and fine tuning.
You will have to point the NS records of your domain to the host of the machine that will be running the iodine server (iodined). How to do this is beyond the scope of this article - it is assumed that you can already do this.
You should be able to verify this with the "host" command:
root@neptune:~# host -t NS blah.comThe DNS records should point to the server's host running the DNS server that will tunnel our traffic. In order to verify that you can actually reach this server. Once you have verified that your domain is indeed pointing toward the nameserver host for NS queries, it is time to setup the iodined DNS server.
blah.com name server ns3.blah.com.
blah.com name server ns1.blah.com.
blah.com name server ns2.blah.com.
root@neptune:~#
Unpack the archive.
[root@unimatrix01 iodine]# tar vzxf iodine-0.4.2.tar.gz iodine-0.4.2/ iodine-0.4.2/man/ iodine-0.4.2/man/iodine.8 iodine-0.4.2/src/ iodine-0.4.2/src/encoding.c iodine-0.4.2/src/encoding.h iodine-0.4.2/src/Makefile iodine-0.4.2/src/dns.c iodine-0.4.2/src/dns.h iodine-0.4.2/src/md5.c iodine-0.4.2/src/md5.h iodine-0.4.2/src/tun.c iodine-0.4.2/src/tun.h iodine-0.4.2/src/iodined.c iodine-0.4.2/src/login.c iodine-0.4.2/src/login.h iodine-0.4.2/src/common.c iodine-0.4.2/src/common.h iodine-0.4.2/src/read.c iodine-0.4.2/src/read.h iodine-0.4.2/src/user.c iodine-0.4.2/src/user.h iodine-0.4.2/src/osflags iodine-0.4.2/src/version.h iodine-0.4.2/src/base32.c iodine-0.4.2/src/base32.h iodine-0.4.2/src/base64.c iodine-0.4.2/src/base64.h iodine-0.4.2/src/iodine.c iodine-0.4.2/TODO iodine-0.4.2/Makefile iodine-0.4.2/tests/ iodine-0.4.2/tests/encoding.c iodine-0.4.2/tests/Makefile iodine-0.4.2/tests/dns.c iodine-0.4.2/tests/login.c iodine-0.4.2/tests/read.c iodine-0.4.2/tests/test.c iodine-0.4.2/tests/test.h iodine-0.4.2/tests/user.c iodine-0.4.2/tests/base32.c iodine-0.4.2/tests/base64.c iodine-0.4.2/README iodine-0.4.2/CHANGELOG
Compile and install.
[root@unimatrix01 iodine]# cd iodine-0.4.2Test run:
[root@unimatrix01 iodine-0.4.2]# ls
CHANGELOG Makefile man README src tests TODO
[root@unimatrix01 iodine-0.4.2]# make
make[1]: Entering directory `/root/iodine/iodine-0.4.2/src'
OS is LINUX, arch is i686
CC tun.c
CC dns.c
CC read.c
CC encoding.c
CC login.c
CC base32.c
CC base64.c
CC md5.c
CC common.c
CC iodine.c
LD ../bin/iodine
CC iodined.c
CC user.c
LD ../bin/iodined
make[1]: Leaving directory `/root/iodine/iodine-0.4.2/src'
[root@unimatrix01 iodine-0.4.2]# make install
make[1]: Entering directory `/root/iodine/iodine-0.4.2/src'
OS is LINUX, arch is i686
make[1]: Leaving directory `/root/iodine/iodine-0.4.2/src'
mkdir -p /usr/local/sbin
install bin/iodine /usr/local/sbin/iodine
chmod 755 /usr/local/sbin/iodine
install bin/iodined /usr/local/sbin/iodined
chmod 755 /usr/local/sbin/iodined
mkdir -p /usr/local/share/man/man8
install man/iodine.8 /usr/local/share/man/man8/iodine.8
chmod 644 /usr/local/share/man/man8/iodine.8
[root@unimatrix01 iodine-0.4.2]# iodinedNow that you have it installed, time to run iodined with the correct settings for it to bring up the tunnel interface and make everything ready for us to connect to it.
Usage: iodined [-v] [-h] [-c] [-s] [-f] [-D] [-u user] [-t chrootdir] [-d device] [-m mtu] [-l ip address to listen on] [-p port] [-P password] tunnel_ip topdomain
[root@unimatrix01 iodine-0.4.2]#
[root@unimatrix01 iodine-0.4.2]# iodined -P gotdns 172.16.38.4 xyzbypass.com Opened dns0 Setting IP of dns0 to 172.16.38.4 Setting MTU of dns0 to 1024 Opened UDP socket Listening to dns for domain xyzbypass.com Detaching from terminal... [root@unimatrix01 iodine-0.4.2]#In the parameters, gotdns is the password, 172.16.38.4 is a random IP address I selected in order to have a Layer 3 endpoint on the tunnel interface and lastly, xyzbypass.com is the domain that points towards this DNS server which will act as the "relay initiator" in order to "trick" the ISP's DNS server to pass on the traffic for us to the iodined name server.
To verify that the tunnel interface endpoint is up and running, try ifconfig dns0. (see below)
[root@unimatrix01 iodine-0.4.2]# ifconfig dns0NOTE: Do not run the client before the server. This will result in the ISP's nameserver caching DNS packets (with no response since the server won't be running) and once you do run the server the packets will not traverse via the ISP's DNS server since it already thinks there is no response. In such cases you have to wait for the cache time to expire and nobody likes waiting.
dns0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:172.16.38.4 P-t-P:172.16.38.4 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1024 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
[root@unimatrix01 iodine-0.4.2]#
Now it is time to configure and run the client.
Since I use Ubuntu on my local machine, I will invoke apt-get in order to install iodine instead of compiling from source.
root@neptune:~# apt-get install iodine Reading package lists... Done Building dependency tree Reading state information... Done The following packages were automatically installed and are no longer required: linux-headers-2.6.28-11 linux-headers-2.6.28-11-generic Use 'apt-get autoremove' to remove them. Suggested packages: ipcalc fping The following NEW packages will be installed: iodine 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 0B/38.4kB of archives. After this operation, 168kB of additional disk space will be used. Preconfiguring packages ... Selecting previously deselected package iodine. (Reading database ... 129898 files and directories currently installed.) Unpacking iodine (from .../iodine_0.4.2-2_i386.deb) ... Processing triggers for man-db ... Setting up iodine (0.4.2-2) ... * iodined is not configured to start automatically. Change this in /etc/default/iodine or run dpkg-reconfigure iodine.
And a test drive command:
root@neptune:~# iodine Usage: iodine [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] [nameserver] topdomain root@neptune:~#
Note: You have to make sure you have the same versions of iodine running on the server and the client. It will complain and not work properly if you try it.
Client Side:
To bring up the client, you have to specify parameters to iodine which tell it which is your ISP's nameserver (that we will trick into forwarding our traffic) and the domain name responsible for our traffic to be sent to (the bogus nameserver). A password is also required.
root@neptune:~# iodine 5.5.5.5 desktop-ng.com Enter password: Opened dns0 Opened UDP socket Version ok, both running 0x00000402. You are user #2 Setting IP of dns0 to 172.16.38.7 Setting MTU of dns0 to 1024 Sending queries for desktop-ng.com to 5.5.5.5 Detaching from terminal... root@neptune:~#Let's check the interface of the tunnel:
root@neptune:~# ifconfig dns0At this stage, if everything went as planned, you should be able to ping the other side of the tunnel. If you have noticed, iodine automatically set an IP address similar to the one on the end of the tunnel where iodined (the server) is running.
dns0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:172.16.38.7 P-t-P:172.16.38.7 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1024 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@neptune:~#
root@neptune:~# ping 172.16.38.4 PING 172.16.38.4 (172.16.38.4) 56(84) bytes of data. 64 bytes from 172.16.38.4: icmp_seq=1 ttl=64 time=546 ms 64 bytes from 172.16.38.4: icmp_seq=2 ttl=64 time=44.7 ms 64 bytes from 172.16.38.4: icmp_seq=3 ttl=64 time=44.4 ms 64 bytes from 172.16.38.4: icmp_seq=4 ttl=64 time=44.5 ms ^C --- 172.16.38.4 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3003ms rtt min/avg/max/mdev = 44.422/170.141/546.862/217.500 ms root@neptune:~#Lovely! Now the part we have all been waiting for. Tunneling your Internet traffic through to the DNS server to fetch our IP traffic for us. To do this, you need to:
- Client: Add static routes which specify how to get to your ISP's DNS server
- Client: Add a default gateway being the end of the tunnel on the server
- Server: Make the server NAT our private IP on the tunnel to a real IP or to an interface which has access to the Internet.
- Server: Enable IP forwarding.
Enable IP forwarding (server):
[root@unimatrix01 iodine-0.4.2]# sysctl -w net.ipv4.ip_forward=1In the case of a reboot this setting will default back to 0. If you want it to retain a value of "1" after a reboot, I suggest you add an entry in /etc/sysctl.conf to be processed upon boot.
net.ipv4.ip_forward = 1
[root@unimatrix01 iodine-0.4.2]#
Network Address Translation (server):
To access the Internet via the server, we need to translate our private IP into a public IP or to an interface which points toward the Internet. To do this we enable IP MASQUERADE in IPTABLES.
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE /sbin/iptables -A FORWARD -i eth0 -o dns0 -m state --state RELATED,ESTABLISHED -j ACCEPT /sbin/iptables -A FORWARD -i dns0 -o eth0 -j ACCEPTTo check if this worked as it should have, try this:
[root@unimatrix01 iodine-0.4.2]# ping -I dns0 www.google.com PING www.l.google.com (209.85.229.99) from 172.16.38.4 dns0: 56(84) bytes of data. 64 bytes from ww-in-f99.google.com (209.85.229.99): icmp_seq=1 ttl=52 time=79.7 ms 64 bytes from ww-in-f99.google.com (209.85.229.99): icmp_seq=2 ttl=52 time=79.1 ms 64 bytes from ww-in-f99.google.com (209.85.229.99): icmp_seq=3 ttl=52 time=79.2 ms 64 bytes from ww-in-f99.google.com (209.85.229.99): icmp_seq=4 ttl=52 time=78.2 ms --- www.l.google.com ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 2999ms rtt min/avg/max/mdev = 78.281/79.110/79.723/0.558 ms [root@unimatrix01 iodine-0.4.2]#The default roots on the client machine are simple. There should be one route that points to the ISP's DNS server (5.5.5.5) and another route that specifies all traffic should point toward the IP address at the other end of the tunnel (172.16.38.4).
First let's take a look at the current routing table entries on the client.
root@neptune:~# route -NThe last entry in bold, is the magic one. This is the default route which tells my client machine to forward all traffic destined for other networks to 192.168.10.254. To get rid of it:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
172.16.38.0 0.0.0.0 255.255.255.0 U 0 0 0 dns0
192.168.10.0 0.0.0.0 255.255.255.0 U 2 0 0 wlan0
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 wlan0
0.0.0.0 192.168.10.254 0.0.0.0 UG 0 0 0 wlan0
root@neptune:~#
root@neptune:~# route del default gw 192.168.10.254We next need to add a route to our ISP's DNS server.
root@neptune:~#
root@neptune:~# route add -host 5.5.5.5 gw 192.168.10.254Now you should be able to issue DNS requests to your ISP's DNS server.
Following that, you must now add the default route that takes all your traffic to the iodined bogus nameserver.
root@neptune:~# route add default gw 172.16.38.4
At this stage, if all went well, you should be able to ping google.com via the DNS tunnel. Try it:
root@neptune:~# ping google.comYou can see the response time is terrible. Fine tuning should fix that. But at this stage you have a functional path to the Internet without actually having an account with any of the ISPs available on the i-choice platform. Great!
PING google.com (74.125.127.100) 56(84) bytes of data.
64 bytes from pz-in-f100.google.com (74.125.127.100): icmp_seq=1 ttl=53 time=2365 ms
64 bytes from pz-in-f100.google.com (74.125.127.100): icmp_seq=2 ttl=53 time=1442 ms
64 bytes from pz-in-f100.google.com (74.125.127.100): icmp_seq=3 ttl=53 time=526 ms
64 bytes from pz-in-f100.google.com (74.125.127.100): icmp_seq=4 ttl=53 time=740 ms
64 bytes from pz-in-f100.google.com (74.125.127.100): icmp_seq=5 ttl=53 time=948 ms
^C
--- google.com ping statistics ---
6 packets transmitted, 5 received, 16% packet loss, time 5013ms
rtt min/avg/max/mdev = 526.547/1204.601/2365.300/655.004 ms, pipe 3
root@neptune:~#
Optimizing the connection.
If you have tried this with the default MTU, I am sure you have felt the performance impact regarding response time. It's indeed unacceptable. The solution is to specify an MTU more suitable than 1024. Some DNS servers discard packets that exceed 512 bytes in size. This could be a problem for you. The solution is to set your MTU (with the -m option when running the server) to 220. This will ensure that all packets remain under the 512 byte limit. Experimenation is encouraged to find the most suitable MTU that gives you maximum performance. You might suspect this kind of behaviour in the case that you can send some types of traffic such as web browsing but can't open an SSH session for example.
More to come
I am currently investigating methods of detecting DNS traffic like this. Many thoughts have crossed my mind such as statistical anomaly detection within the payload itself, statistical analysis of DNS requests per client with a cross reference with current bandwidth usage, etc...
the unfortunate event is that everything comes at a cost. Resource-friendly methods are few and they are something to be skeptical and investigative about.
In the meanwhile, take care now...
2 comments:
UPDATE:
This works with i-choice DNS servers too (a friend told me).
Primary DNS: 192.168.6.108
Secondary DNS: 192.168.5.108
You don't need to click on anyone's ISP link in i-choice like this.
Also note that some ISPs don't allow DNS access before you login.
For ISP's to avoid this kind of attack, the simplest way would be to follow the rules and make sure that private IP's don't speak to public IP's on nameservers. I know this is done , or else the above wouldn't have worked!
Conform with network standards for goodness sake! NAT the IP to the outside and THEN allow the customer to speak to the DNS.
That still doesn't solve the problem of DNS tunneling though, i-choice DNS servers can pass your tunnel traffic for you.
Post a Comment