I've fixed these issues in the file in my repository.  Including
below.  However, I wouldn't mind if the "home" location for this file
was in some more public repository, like a git repo on alioth
shared-maint or whatever.  Even if I didn't have write access, I could
track your changes and send you my patches, or expose my repository so
you could pull my changes yourself.

I guess I could put just this one single file at git-hub, just to goof
around with that system...

                                        --Barak.

#! /bin/bash

### Script to set up an iodine tunnel route traffic through it
###
### Copyright 2008 Barak A. Pearlmutter <b...@debian.org>
###
### License: MIT
###
### Permission to use, copy, modify, and distribute this software for
### any purpose with or without fee is hereby granted, provided that
### the above copyright notice and this permission notice appear in
### all copies.
###
### THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
### WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
### WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
### AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
### CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
### LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
### NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
### CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

## Cause script to bail immediately on failed command
set -e

## Options for user to set.

## Minimal customization: put the two lines
##  subdomain=your.tunnel.sub.domain
##  passwd=password_for_that_tunnel
## in the file /etc/default/iodine-client.

echo "${iodine_client_rc:=/etc/default/iodine-client}" > /dev/null

if [ -r ${iodine_client_rc} ]; then
    . ${iodine_client_rc}
else
    echo WARNING: Cannot read ${iodine_client_rc}
fi

if [ -z ${subdomain} ]; then
    read -p "DNS tunnel DNS subdomain: " subdomain
fi

if [ -z ${subdomain} ]; then
    echo ERROR: Must set subdomain.
    exit 1
fi

if [ -z ${passwd} ]; then
    read -p "Password for DNS tunnel over ${subdomain}: " passwd
fi

## This is a host name used for testing DNS and for pinging
echo "${testhost:=slashdot.org}"                > /dev/null

## Set if local network should be taken down and then up
echo "${bounce_localnet:=true}"                 > /dev/null

## Set for testing network availability via ping at various points
echo "${test_ping_localnet:=true}"              > /dev/null
echo "${test_ping_tunnel:=true}"                > /dev/null
echo "${test_ping_final:=true}"                 > /dev/null

## Set if the script cannot find and then incorrectly guesses the
## local network router
echo "${default_router}"                        > /dev/null

## Set if script uses the wrong hardware interface
echo "${interface}"                             > /dev/null

## Set if the script should continue even if a command fails.
## Used to test script when running as non-root.
if [ $(whoami) = root ]; then
    echo "${continue_on_error:=false}"          > /dev/null
else
    echo "${continue_on_error:=true}"           > /dev/null
fi

## DEBIAN PACKAGES TO INSTALL: these are needed to run this script
##  iodine (for /usr/sbin/iodine)
##  iproute (for /bin/ip)
##  ipcalc (for /usr/bin/ipcalc)
##  dnsutils (for /usr/bin/dig)
##  fping (for /usr/bin/fping)
##  gawk (for /usr/bin/gawk, to use gensub())

## The default tunnel MTU is 1024.
## If local DNS server restricts to 512 byte packets then do this:
# ifconfig ${d} mtu 220

## TO DO
## - avoid double ping when DNS server and local router are the same
## - option to not kill existing iodine DNS tunnels, in case there
##   are meant to be more than one
## - sanify check whether default_router is on local network

echo ==== Creating IP-over-DNS tunnel over local network connection...


## Find a network interface

if [ -z ${interface} ]; then
    interface=$(tail --lines=+3 /proc/net/wireless \
        | head -1 | tr -d : | awk '{print $1}')
fi

if [ -z ${interface} ]; then
    interface=$(ifconfig -a | egrep '^[^ ].*encap:Ethernet' \
        | head -1 | awk '{print $1}')
fi

if [ -z ${interface} ]; then
    echo ERROR: No network interface found.
    exit 1
fi

echo ==== Local network interface: ${interface}

## Down any existing DNS tunnel (wish there were "approved" way to do this)

echo ==== Killing existing DNS tunnels...
if killall --quiet --wait --verbose --signal HUP iodine; then
    sleep 2
fi

## Stabilize local network

if ${bounce_localnet}; then
    echo ==== Bouncing local network connection...
    ifdown --force ${interface} || true
    ifup ${interface} || ${continue_on_error}
fi

## Fetch some information about the local network

addr=$(ip -4 addr show dev ${interface} scope global \
    | tail -1 | awk '{print $2}')
prefix_len=$(echo ${addr} | sed 'sX^.*/XX')
local_net=$(ipcalc --nobinary ${addr} | awk '$1=="Network:" {print $2}')

echo ==== Local address: ${addr}
echo ==== Local network: ${local_net}

router=$(ip -4 route list dev ${interface} \
    | awk '$1=="default" {print $3}' | head -1)
if [ -z ${router} ]; then
    ## This can happen when the default local route is already deleted
    if [ -z ${default_router} ]; then
        echo WARNING: no default route, guessing local router IP address.
        ## Minimum address on local net is usually right
        router=$(ipcalc --nobinary ${addr} | awk '$1=="HostMin:" {print $2}')
    else
        echo WARNING: no default route, using configured default router.
        ## But sometimes need to hardwire...
        router=${default_router}
    fi
fi

echo ==== Local network router: ${router}

## Test DNS service

testhost_ip=$(dig +short -t A -q ${testhost})
if [ -z ${testhost_ip} ]; then
    echo WARNING: Failure on DNS lookup of ${testhost}.
fi

## fetch DNS servers

nameservers=$(awk '$1=="nameserver" {print $2}' /etc/resolv.conf)
if [ -n "${nameservers}" ]; then
    echo ==== DNS servers: ${nameservers}
else
    echo ERROR: No DNS servers found.
    exit 1
fi

## Test if local network is up

if ${test_ping_localnet}; then
    echo ==== Ping test of  local network router and DNS servers...
    fping -C1 ${router} ${nameservers} \
        || echo WARNING: Ping test failed.
fi

## Add point-to-point routes for any non-local DNS servers

for n in ${nameservers}; do
    n_net=$(ipcalc --nobinary ${n}/${prefix_len} | awk '$1=="Network:" {print 
$2}')
    if [ "${n_net}" != "${local_net}" ]; then
        echo ==== Adding point-to-point route for DNS server ${n}
        ## remove point-to-point route first, in case it is already present
        ip -4 route del ${n}/32 || true
        ip -4 route add ${n}/32 via ${router} || ${continue_on_error}
    fi
done

## Bring up DNS tunnel

echo ==== Creating IP-over-DNS tunnel...
iodine -P "${passwd}" "${subdomain}" || ${continue_on_error}

## Find DNS tunnel interface

tunnel_interface=$(ifconfig -a | egrep '^dns' | awk '{print $1}' | head -1)
if [ -z "${tunnel_interface}" ]; then
    echo WARNING: Cannot find DNS tunnel interface, using default.
    tunnel_interface=dns0
fi
echo ==== DNS tunnel interface: ${tunnel_interface}

## Figure out router at other end of tunnel, assuming router uses final octet .1
## (There should be some way to get this information out of iodine, since
## it *prints* it as it sets up the tunnel, so it does know it.)

tunnel_remote=$(ip -4 address show dev ${tunnel_interface} \
    | gawk '$1=="inet" {print gensub("[.][0-9]*/.*", ".1", 1, $2)}' | head -1)

if [ -z ${tunnel_remote} ]; then
    echo ERROR: Cannot find DNS tunnel remote endpoint.
    ${continue_on_error}
    ## set something random if debugging
    echo WARNING: Confabulating DNS tunnel remote endpoint.
    tunnel_remote=192.168.253.1
fi

echo ==== DNS tunnel remote endpoint: ${tunnel_remote}

if ${test_ping_tunnel}; then
    echo ==== Ping test of local router, nameserver, and DNS tunnel...
    fping -C1 ${router} ${nameservers} ${tunnel_remote} \
        || echo WARNING: Ping test failed.
fi

## Modify routing table to send trafic via DNS tunnel

echo ==== Setting default route through DNS tunnel...

## Remove default route via local router
ip -4 route del default via ${router} || ${continue_on_error}
## Add default via tunnel
ip -4 route add default via ${tunnel_remote} || ${continue_on_error}

## Test if all is well

if ${test_ping_final}; then
    echo ==== Ping test of local router, nameserver, DNS tunnel, external test 
host...
    fping -C1 ${router} ${nameservers} ${tunnel_remote} 
${testhost_ip:-${testhost}} \
        || echo WARNING: Ping test failed.
fi



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to