Scripts for guaranteed IPv6 support


Overview


About

On my notebook, I am often in places where no IPv6 is available. Usually, it is possible, to create a tunnel solution, which fails, and is unneccessary, when there is native IPv6 already.

To setup IPv6 I use a point-to-point tunnel via OpenVPN to my host provider, and dig a 6in4 tunnel, since openvpn does not yet support IPv6 on all platforms. This solution has the advantage of being very reliable, but also produces a lot of overhead. Therefore, native IPv6 should always be preferred, and the tunnel should be used only as a fall back.

The following scripts first check, if IPv6 isn't already available via neighbour solicitation. If not, the script first looks for an address via DHCP6. If this also fails, the tunnel is established. Edit /etc/wicd/postconnect/01-dhcp6.

Scripts

I'm using WiCD as a connection manager, so I can use the scripting functions. First, add a script for dhcp6 support:

01-dhcp6
#!/bin/sh

# Get any ipv6 address
IPV6=`/sbin/ip addr show | grep global |sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d'`

[ -n "${IPV6}" ] && exit 0
dhclient -6 -1


The following script /etc/wicd/postconnect/10-openvpn sets all openvpn connections to up:

10-openvpn
#!/bin/sh

CONNECTIONS="my-connection"

for CONNECT in $CONNECTIONS
do
    openvpn-manager $CONNECT start
done


The corresponding script in /etc/wicd/predisconnect/10-openvpn tears down the openvpn connections, when the network disconnects.

10-openvpn
#!/bin/sh

CONNECTIONS="my-connection"

for CONNECT in $CONNECTIONS
do
    openvpn-manager $CONNECT stop
done


The openvpn-manager is a simple script, that sets up all openvpn connections specified in the list "CONNECTIONS"

openvpn-manager
#!/bin/sh

CONFIG=$1
PIDFILE=/var/run/openvpn-${CONFIG}.pid

if [ "$2" != 'start' ] && [ "$2" != 'stop' ]; then
    echo "useage $0 <connection> [start|stop]"
    exit 1
fi

if [ $(id -u) -ne 0 ]; then
    exec sudo $0 $1 $2
    exit 1
fi

vpnrunning() {
    if [ ! -f $PIDFILE ]; then
        return 1
    else
        pid=$(cat $PIDFILE)
        if kill -0 $pid 2>/dev/null ; then
            return 0
        else
            return 1
        fi
    fi
}

case $2 in
    start)
        if vpnrunning; then
            echo "openvpn connection $CONFIG already running" >&2
        else
            exec openvpn --cd /etc/openvpn --config ${CONFIG}.conf --daemon
        fi
        ;;
    stop)
        if vpnrunning; then
            exec kill $(cat $PIDFILE)
        else
            echo "openvpn connection $CONIFG is not running"
        fi
        ;;
esac


The openvpn connection is a simple point-to-point connection, with two v4 addresses at its endpoint. Since I don't have a second ::/64 network, I did the dirty trick of splitting of a ::/80 network to be able to route on the server side. This is very quick and dirty. If you can avoid this, don't do it!

The up.sh script for the openvpn connection tests whether IPv6 is available, and exits with a code <> 0 if so. This will abort the whole tunnel to be build. Otherwise the tunnel is brought up.

up.sh
#!/bin/sh

# Set some preferences
IP="/sbin/ip"

# NOTE: The endpoint address is hardcoded, because it can't be requested
# from the server!
REMOTEENDPOINTIP="<MY-IPV4-TUNNELENDPOINT>"
SITID="ipv6-sit"

# Get the ipv6 address of any interface
# This only tests for global variables
IPV6=`/sbin/ip addr show | grep global |sed -e'
s/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d'`
 
# exit, if we already have an ipv6 address
[ -n "${IPV6}" ] && exit 1

# Create an address space
IPV6BASE="<MY-IPV6-NETWORK-PART-64>"

V6NET=$(echo ${ifconfig_local} | awk -F. '
{print $NF}')

# Set up the tunnel
$IP tunnel add ${SITID} mode sit ttl 255 remote ${REMOTEENDPOINTIP} local ${ifconfig_local}
$IP link set dev ${SITID} up
$IP -6 addr add ${IPV6BASE}:${V6NET}::2/80 dev ${SITID}

# set default route
$IP route add default via ${IPV6BASE}:${V6NET}::1
exit 0


To tear the tunnel down, the down.sh script is executed:
down.sh
#!/bin/sh

# Set some preferences
IP="/sbin/ip"

# NOTE: The endpoint address is hardcoded, because it can't be requested
# from the server!
REMOTEENDPOINTIP="<MY-IPV4-ENDPOINT>"
SITID="ipv6-sit"

# Set the bbase address
IPV6BASE="<MY-IPV6-NETWORK-PART-64>"

V6NET=$(echo ${ifconfig_local} | awk -F. '
{print $NF}')

# remove default route
$IP -6 route default via ${IPV6BASE}:${V6NET}::1

# Tear down the tunnel
$IP -6 addr del ${IPV6BASE}:${V6NET}::2/80 dev ${SITID}
$IP link set ${SITID} down
$IP tunnel del ${SITID} mode sit ttl 255 remote ${REMOTEENDPOINTIP} local ${ifconfig_local}

exit 0
There are no comments on this page.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki