X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=iodine-jigger;fp=iodine-jigger;h=0bb32aecdb052c96cd6fa688f3d2c9c0db4a26ea;hb=2b464ba4132397e6ce4f0760cf820c34030729ff;hp=0000000000000000000000000000000000000000;hpb=b35a22f3a97c477ae0c975aa63fc8422d70f5bc8;p=bin.git diff --git a/iodine-jigger b/iodine-jigger new file mode 100755 index 0000000..0bb32ae --- /dev/null +++ b/iodine-jigger @@ -0,0 +1,248 @@ +#! /bin/bash + +### Script to set up an iodine tunnel route traffic through it +### +### Copyright 2008 Barak A. Pearlmutter +### +### 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 +## passed=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) + +## 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} + 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} \ + | awk '$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