Iodined - how to use free internet on airports

How to get internet connectivity on an open wi-fi access point that requires a credit card without actually paying:


  • OpenWRT router
    • public ip, not necessarily static
  • account on
  • OS X laptop

Iodine on OpenWRT and installation on a OS X

On the OpenWRT:

  • opkg install iodined
  • update /etc/init.d/iodined to:

[dropdown_box expand_text="code" show_more="Show" show_less="Hide" start="hide"]

#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011


start_instance () {
local section="$1"
config_get address  "$section" 'address'
config_get password "$section" 'password'
config_get tunnelip "$section" 'tunnelip'
config_get tld      "$section" 'tld'

service_start /usr/sbin/iodined -l "$address" -c -s -P "$password" $tunnelip "$tld" &
sleep 1
ifconfig dns0 $tunnelip netmask

start() {
config_load 'iodined'
config_foreach start_instance 'iodined'

stop() {
service_stop /usr/sbin/iodined


  • so that it starts automatically
/etc/init.d/iodined enable
  • edit /etc/config/iodined (because there' s a bug on openwrt)
    • change address to
config iodined
 option address ''
 option password ''
 option tunnelip ''
 option tld ''
  • Make sure the openwrt router has a static ip address ( provides dyndns updates)
  • Make a dns zone: ns ->
    • has a dyndns update
  • port forward 53 (tcp and udp) from first router to second router (or just open 53 on the openwrt)

osx client

  • (tuntap)
  • script:

[dropdown_box expand_text="code" show_more="Show" show_less="Hide" start="hide"]


# are we root?
if ! [ $UID == 0 ] ; then
  echo "IODINE SETUP: use 'sudo $0'";
  exit 0;

#$1 says whether we use clearcode or
if [ -z $1 ] ; then
  echo 'IODINE SETUP: first param must be 1( or 2(';
  exit 0;

if [ $1 == 1 ] ; then

if [ $1 == 2 ] ; then

# get the first dns from resolv.conf and use it.
abused_nameserver=`cat /etc/resolv.conf | grep nameserver | head -1 | awk '{print $2}'`
echo ">>>>>>>>>>>>>>>>>>>USING DNS: $abused_nameserver"

# kill iodine if any and remove old routes
killall iodine
route delete > /dev/null
route delete > /dev/null

# get the default gateway for iodine
default_gateway=`netstat -rn | grep default | awk '{print $2}'`

#when I die, restore the default gateway, use trap to get Ctrl+C
function disconnect() {
  # kill the process with id coming as a parameter
  kill -9 $1;
  route add default $default_gateway;
#disconnect and exit
function cleanup() {
  disconnect $(pgrep iodine);
  exit 0;
trap "cleanup" SIGINT

#dns query types
dns_query_types="TXT CNAME NULL"

function connect() {
  # start iodine (possible dns types are CNAME, TXT, NULL), -F puts a pid file with the processId inside
  iodine_output=$(./iodine -T CNAME -r -P "peshev sucks" -F /var/run/ $abused_nameserver $endpoint_domain 2>&1 | tee /dev/tty)

  #remote_net from iodine_output
  remote_net=$(echo $iodine_output | grep -o "Adding route [0-9\.]*/[0-9]\{1,2\} to [0-9\.]*" | awk '{print $3}')  

  #remote_net is something like and should be
  remote_net=$(./ipcalc -nb $remote_net | grep Network | awk '{ print $2}')

  #tunX_ip (tunX_ip) from iodine_output
  tunX_ip=$(echo $iodine_output | grep -o "Adding route [0-9\.]*/[0-9]\{1,2\} to [0-9\.]*" | awk '{print $5}')

  #remote_gateway (gateway on iodine) from iodine_output
  remote_gateway=$(echo $iodine_output | grep -o "Server tunnel IP is [0-9\.]*" | awk '{print $5}')

  # route to nameserver to be abused
  route add -host $abused_nameserver $default_gateway
  # route to remote network via tunX_ip (necessary because my mac sucks)
  route add -net $remote_net $tunX_ip
  # change default gateway from system default to iodine 
  route delete default
  route add default $remote_gateway

  # time to download 100kb file in seconds (1.34). We remove the dot for easy comparison (1.34 -> 134)
  t=$( { time -p curl -s; } 2>&1 )
  seconds=$(echo $t | awk '{ print $2;}' | tr -d . );
  echo SECONDS: $seconds;


while true; do sleep 10000; done;


  •  add ipcalc because the script needs it: ipcalc


Some testing found out speeds like 7-15 kb/s, sometimes less on and With local DNS servers the speeds are like 100kb/s. More testing is necessary.

6 thoughts on “Iodined - how to use free internet on airports”

  1. hello, I am running openwrt and trying to get iodined running but with no luck. the thing is when I run iodined the dns dies for the entire network. the tester from iodined website shows then that it is correctly configured. what am I doing wrong?:)

    1. Iodined IS a special dns server. It's hard to configure a normal dns for your external or internal network on the same machine.

  2. yeah, what I found out over the internet is this:
    iptables -t nat -A PREROUTING -p udp --dport 53 -m string --algo bm --from 20 --hex-string "|xxxxxxxxxxxxxxxxxx|" -j REDIRECT --to-ports 5353

    but on openwrt it does not work. From what I understand, the iodined server must be running on port 5353 and instead of xxxxxxxx must be the adress of the tunnel in hex format but on openwrt it does not work. Maybe I am missing a package?

    1. iodine must be running on tcp and udp 53. If you want to simultaneously have a normal dns then it gets a little bit more difficult.

  3. Well I bought a Raspberry pi and moved iodined there. Enjoying my raspberry. What am I doing now is searching to get openvpn running on 53 port. Some say that there is not the speed limit. (Sorry for the offtopic 🙂 )

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.

This site uses Akismet to reduce spam. Learn how your comment data is processed.