Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Continuing with my theme of VPNs, I thought I’d share some Iodine DNS tunneling this week.
If you are not aware, Iodine is a great tool released by Erik Ekman and Bjorn Andersson that will do IPv4 tunneling over DNS.
This is useful for evading captive portals, exfiltration, or just another layer of obfuscation/privacy.
For another walkthrough, I recommend the following blog post
First, I setup iodine on the server that I wanted to use.
root@server:~# apt-get install iodine Reading package lists... Done Building dependency tree Reading state information... Done Suggested packages: fping oping ipcalc The following NEW packages will be installed: iodine 0 upgraded, 1 newly installed, 0 to remove and 13 not upgraded. Need to get 101 kB of archives. After this operation, 251 kB of additional disk space will be used. Get:1 http://mirrors.digitalocean.com/ubuntu/ trusty/universe iodine amd64 0.6.0~rc1-18 [101 kB] Fetched 101 kB in 0s (157 kB/s) Preconfiguring packages ... Selecting previously unselected package iodine. (Reading database ... 92366 files and directories currently installed.) Preparing to unpack .../iodine_0.6.0~rc1-18_amd64.deb ... Unpacking iodine (0.6.0~rc1-18) ... Processing triggers for man-db (2.6.7.1-1ubuntu1) ... Processing triggers for ureadahead (0.100.0-16) ... Setting up iodine (0.6.0~rc1-18) ...
I also installed the application on my local Kali box for testing in the same way.
With iodine installed on both systems, it was time to start-up the server. As mentioned in the previously linked walkthrough, I decided to go with a subdomain instead of my full domain name.
root@server:~# iodined -f 10.0.0.1 t1.myserver.com Enter password: Opened dns0 Setting IP of dns0 to 10.0.0.1 Setting MTU of dns0 to 1130 Opened UDP socket Listening to dns for domain t1.myserver.com
Unfortunately, when I first tried to connect to my server, I was receiving a lot of bad handshake errors.
root@kali:~# iodine -f -r 1.2.3.4 t1.myserver.com Enter password: Opened dns0 Opened IPv4 UDP socket Sending DNS queries for t1.myserver.com to 1.2.3.4 Autodetecting DNS query type (use -T to override). Using DNS type NULL queries Version ok, both using protocol v 0x00000502. You are user #0 Received bad handshake Retrying login... Received bad handshake Retrying login... Received bad handshake Retrying login... Received bad handshake Retrying login... Received bad handshake Retrying login... iodine: couldn't login to server
I found a blog post that mentioned fixing this problem with the ‘-c’ flag. Also, the README says that this flag should be used, “If there is a chance you’ll be using an iodine tunnel from unexpected environments, start iodined with a -c option.”
After checking the actual binary, it seems that the flag would fix my errors.
-c to disable check of client IP/port on each request
With the -c flag added to my server, I re-ran the application on my client. As you can see, it connected just fine this time.
root@kali:~# iodine -f -r 1.2.3.4 t1.myserver.com Enter password: Opened dns0 Opened IPv4 UDP socket Sending DNS queries for t1.myserver.com to 1.2.3.4 Autodetecting DNS query type (use -T to override). Using DNS type NULL queries Version ok, both using protocol v 0x00000502. You are user #0 Setting IP of dns0 to 10.0.0.2 Setting MTU of dns0 to 1130 Server tunnel IP is 10.0.0.1 Skipping raw mode Using EDNS0 extension Switching upstream to codec Base128 Server switched upstream to codec Base128 No alternative downstream codec available, using default (Raw) Switching to lazy mode for low-latency Server switched to lazy mode Autoprobing max downstream fragment size... (skip with -m fragsize) 768 ok.. ...1152 not ok.. 960 ok.. 1056 ok.. 1104 ok.. ...1128 not ok.. 1116 ok.. will use 1116-2=1114 Setting downstream fragment size to max 1114... Connection setup complete, transmitting data.
Note that I was getting a lot of “SERVFAIL” errors. This is likely due to my DNS server being impatient and timing out quickly. That said, it didn’t seem to effect anything, and iodine automatically updates the timeout interval.
iodine: Got SERVFAIL as reply: server failed or recursion timeout iodine: Hmm, that's 1. Your data should still go through... iodine: Got SERVFAIL as reply: server failed or recursion timeout iodine: Hmm, that's 2. Your data should still go through... iodine: Got SERVFAIL as reply: server failed or recursion timeout iodine: Hmm, that's 3. Your data should still go through... iodine: Got SERVFAIL as reply: server failed or recursion timeout iodine: Hmm, that's 4. Your data should still go through... iodine: Got SERVFAIL as reply: server failed or recursion timeout iodine: I think 5 is too many. Setting interval to 1 to hopefully reduce SERVFAILs. But just ignore them if data still comes through. (Use -I1 next time on this network.) iodine: Got SERVFAIL as reply: server failed or recursion timeout iodine: Got SERVFAIL as reply: server failed or recursion timeout iodine: Got SERVFAIL as reply: server failed or recursion timeout
With the server and client both functioning, it was time to test the tunnel.
First, I verified my current IP and location information.
root@kali:~# curl ipinfo.io { "ip": "40.x.x.x", "hostname": "x.ip.windstream.net", "city": "< ... snip ... >", "region": "Massachusetts", "country": "US", "loc": "< ... snip ... >", "postal": "< ... snip ... >", "phone": "< ... snip ... >", "org": "AS7029 Windstream Communications LLC" }
I also verified that my new ‘dns0’ interface was up, and had a proper IP address.
root@kali:~# ifconfig dns0
dns0: flags=4305
inet 10.0.0.2 netmask 255.255.255.224 destination 10.0.0.2
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1 bytes 48 (48.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Next, I created an SSH tunnel between my client and the server, to act as a SOCKS proxy. The -N flag instructs SSH to not start a shell, as this will just function as a transparent proxy, and the -D flag configures the dynamic port forwarding.
root@kali:~# ssh -N -D 8080 [email protected] The authenticity of host '10.0.0.1 (10.0.0.1)' can't be established. ECDSA key fingerprint is SHA256:BMLJjcXWsYSzkeBeW17+bWZx9hoa2ylQVpS8NnywqWQ. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '10.0.0.1' (ECDSA) to the list of known hosts. [email protected]'s password:
With my proxy setup, I requested my updated IP information using the local proxy settings. As you can see, I was now connecting from my downstream server!
root@kali:~# curl --socks5 127.0.0.1:8080 http://ipinfo.io { "ip": "1.2.3.4", "city": "< ... snip ... >", "region": "New Jersey", "country": "US", "loc": "< ... snip ... >", "postal": "< ... snip ... >", "phone": "< ... snip ... >", "org": "AS14061 DigitalOcean, LLC" }
Once I had everything working, I was curious about what the real requests looked like.
First, I fired up tshark and listened to any DNS queries on my ethernet interface. As you can see, the client was sending some very interesting looking queries to my iodine server.
root@kali:~# tshark -T fields -e dns.qry.name -i eth1 Running as user "root" and group "root". This could be dangerous. tshark: Lua: Error during loading: [string "/usr/share/wireshark/init.lua"]:32: dofile has been disabled due to running Wireshark as superuser. See https://wiki.wireshark.org/CaptureSetup/CapturePrivileges for help in running Wireshark as an unprivileged user. Capturing on 'eth1' paaqjrvi.t1.myserver.com paaqjrva.t1.myserver.com paaqjrvq.t1.myserver.com paaqjrvi.t1.myserver.com ipinfo.io ipinfo.io ipinfo.io ipinfo.io ipinfo.io 0ecbg82\276zGb\325\375aabacuGa\306dmeabagm\373\277Gaaekaaay4\276aw\3361\347\321\344VGK\370Gdajx\362\370a.aaqiGvQoFr\316\365\372i\370m6\347\313y\277\343\333v\3706\330p\326\336\331n\311\345\276\333s\347x\344\337\372lGXqoL\366\374\325W2\320Rdp.I\347MiHJZY5S3\365x\315\367qH4\353\303F4n1F\303I\325F\304\323\3676J\322\3510y\335R\340d\300\360\361\326\343\362k\274J\340\370\350\347K\327.g\336\361PO23\366\321\367\276.t1.myserver.com paaqjrvq.t1.myserver.com 0ecbg82\276zGb\325\375aabacuGa\306dmeabagm\373\277Gaaekaaay4\276aw\3361\347\321\344VGK\370Gdajx\362\370a.aaqiGvQoFr\316\365\372i\370m6\347\313y\277\343\333v\3706\330p\326\336\331n\311\345\276\333s\347x\344\337\372lGXqoL\366\374\325W2\320Rdp.I\347MiHJZY5S3\365x\315\367qH4\353\303F4n1F\303I\325F\304\323\3676J\322\3510y\335R\340d\300\360\361\326\343\362k\274J\340\370\350\347K\327.g\336\361PO23\366\321\367\276.t1.myserver.com
After reading through the operational info, it seemed that application encoded the default queries in Base128. As I couldn’t get CyberChef to decode these properly, I decided to try to view the queries in Base64.
root@kali:~# iodine -f -O Base64 -r 1.2.3.4 t1.myserver.com Enter password: Opened dns0 Opened IPv4 UDP socket Sending DNS queries for t1.myserver.com to 1.2.3.4 Autodetecting DNS query type (use -T to override). Using DNS type NULL queries Version ok, both using protocol v 0x00000502. You are user #1 Setting IP of dns0 to 10.0.0.3 Setting MTU of dns0 to 1130 Server tunnel IP is 10.0.0.1 Skipping raw mode Using EDNS0 extension Switching upstream to codec Base128 Server switched upstream to codec Base128 Switching downstream to codec Base64 Server switched downstream to codec Base64 Switching to lazy mode for low-latency Server switched to lazy mode Autoprobing max downstream fragment size... (skip with -m fragsize) 768 ok.. ...1152 not ok.. 960 ok.. 1056 ok.. 1104 ok.. ...1128 not ok.. 1116 ok.. will use 1116-2=1114 Setting downstream fragment size to max 1114... Connection setup complete, transmitting data.
Unfortunately, iodine was still encoding the queries in something that I couldn’t understand or decode.
12fby82\3122hb\276\356k\326rn\304\351\305\276\356Wk\352\304dl\276\336dy\306\342V2y\340B\316\313\3018FB\316\352\324Kml\300f\335\304Qje\304hR6.\317\350HP\375\304\307v\341\363\3312C\3552\351\313Z\300\367W\362\324\361\332\314\354\274f\344\375C\302\353\327\324i\3153\363\352q\332\340V\353\3306\363\354tWb\3754p\337.\336.t1.myserver.com 12fby82\3122hb\276\356k\326rn\304\351\305\276\356Wk\352\304dl\276\336dy\306\342V2y\340B\316\313\3018FB\316\352\324Kml\300f\335\304Qje\304hR6.\317\350HP\375\304\307v\341\363\3312C\3552\351\313Z\300\367W\362\324\361\332\314\354\274f\344\375C\302\353\327\324i\3153\363\352q\332\340V\353\3306\363\354tWb\3754p\337.\336.t1.myserver.com
This was mostly just an exercise in curiosity, but let me know if you know how to decode these queries!
Iodine was fairly simple to get running once I had everything configured. I don’t think I’ll use this as often as my standard VPN solutions, but it is a nice trick to have in the bag, especially when I’m behind something like a captive portal.
I’ve still got to finish work on the other vulnserver commands, so don’t expect a new one of those posts too quickly.
Other than that, as always, let me know if you have any ideas for tools, research, or a post in general!
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he’s done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!
He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.
This page contains links to products that I may receive compensation from at no additional cost to you. View my Affiliate Disclosure page here. As an Amazon Associate, I earn from qualifying purchases.
Hello Sir, How can I limit the user client from server side in Andiodine dns
The easiest way would be to set a password.