DNS tunneling to the rescue
Stuck somewhere without the Internet? Read on!
This is just another post about Iodine and DNS tunneling. Some kind of memo.
So, service provider is blocking almost everything but DNS queries? It's time for Iodine.
DNS tunnelling is not the fastest (like VPN or ICMP tunneling) and not most useful, but it works almost always.
All that needed is: own domain name, server with iodined and client with iodine.
It's important to have the same version on client and server. There are no backward compatibility.
Setup subdomains:
- NS record for Iodine: iodine.example.org pointing to Iodine server ip address
- A record for resolving hostname: tun.example.org
- Set NS record for tun.example.org to iodine.example.org
OK, now all requests to *.tun.example.org should go to Iodine.
Start server:
iodined -c -f 10.10.10.1 tun.example.org -P p@SSwoRd -DD
- c - disable checks for client's ip
- f - run in the foreground
- 10.10.10.1 - subnet for virtual network
- tun.example.org - domain for listening
- P - password
- DD - double debug
Let's check it (online check is available at http://code.kryo.se/iodine/check-it/):
dig srv z001.tun.example.org +short
hpiyxampo.md.
dig txt z1.tun.example.org +short
"tpiys2"
Iodine will reply with random string for any requests starting with 'z'.
Now, let's start iodine client:
iodine -r -m226 -OBase64u -L0 -P p@SSwoRd tun.example.org
- 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
- tun.example.org domain to use for queries
Great article and more examples here.
Cool, let's try to ping server via virtual dns0 device:
[root@host ~ ] ping 10.10.10.1
PING 10.10.10.1 (10.10.10.1) 56(84) bytes of data.
64 bytes from 10.10.10.1: icmp_seq=1 ttl=64 time=50.6 ms
64 bytes from 10.10.10.1: icmp_seq=2 ttl=64 time=54.2 ms
64 bytes from 10.10.10.1: icmp_seq=3 ttl=64 time=65.9 ms
64 bytes from 10.10.10.1: icmp_seq=4 ttl=64 time=63.4 ms
^C
--- 10.10.10.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 50.666/58.604/65.983/6.324 ms
So far so good.
The final part, routing
The easiest way to route requests to Iodine server is ssh dynamic tunneling (ssh -D ${port} user@server) which will create SOCKS server on the host machine.
But if our requests is encrypted with TLS or other suite we can route all traffic directly throught DNS tunnel (Iodine's password is using for authentication only, data is not encrypted at all).
Server should have enabled forwarding, NAT and ACCEPT rules or policy in the FORWARD chain:
echo 1 > /proc/sys/net/ipv4/ip_forward &&
iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -j MASQUERADE
To route all data through tunnel:
- add route for service provider's DNS resolvers
[user@host ~ ] cat /etc/resolv.conf
nameserver 10.10.100.117
nameserver 10.10.100.118
[user@host ~ ] ip r
default via 10.11.58.1 dev wlan0
10.11.58.0/24 dev wlan0 proto kernel scope link src 10.11.58.114
- adding routes for DNS servers
route add -host 10.10.100.117 gw 10.11.58.1
route add -host 10.10.100.118 gw 10.11.58.1
- delete default gateway and set it to dns0
ip r del default && ip r add default via 10.10.10.1
[user@host ~ ] ip r
default via 10.10.10.1 dev dns0
10.10.10.0/27 dev dns0 proto kernel scope link src 10.10.10.2
10.10.100.117 via 10.11.58.1 dev wlan0
10.10.100.118 via 10.11.58.1 dev wlan0
10.11.58.0/24 dev wlan0 proto kernel scope link src 10.11.58.114
- yup:
[root@jupiter ~ ] ping example.org -c 3
PING example.org (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=53 time=1023 ms
64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=2 ttl=53 time=1025 ms
64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=3 ttl=53 time=2047 ms
--- example.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2047ms
rtt min/avg/max/mdev = 1023.155/1365.228/2047.387/482.360 ms, pipe 2
Thanks for reading.