Restart Ipv6 Tunnel

Problem

Verizon Fios does not provide native dual-stack connectivity. To enable my connection for IPv6, I signed up for Hurricane Electric's Tunnelbroker service. To make a long story short, whenever the IPv4 IP on my Fios connection cycled to a new address, I had to manually update my new IPv4 IP in a few places (Tunnel Broker website, /etc/hostname.gif0) and run a few commands.

Solution

Wrap ifstated with ping and a small shell script to automatically restart my IPv6 tunnel on the new IPv4 IP.

Details

graph TD;
  IPv4{IPv4 Up?};
  IPv4-- No -->Restart_IPv4;
  Restart_IPv4-->IPv4;
  IPv4-- Yes -->IPv6;
  IPv6{IPv6 Up?};
  IPv6-- Yes -->Wait_IPv6(Wait 120 Seconds);
  Wait_IPv6-->IPv6;
  IPv6-- No -->Restart_Ipv6;
  Restart_Ipv6-->IPv6;

In words:

  • If IPv4 is down, try to restart IPv4.
  • If IPv4 is up, check if the IPv6 tunnel is up.
  • If IPv6 tunnel is down, attempt to restart it.

Normal situation: IPv4 is up, IPv6 tunnel goes down.

gate1# ifstated -d -v -v -f /etc/ifstated.conf 
ipv6_up = "( "ping6 -c1 -q -w 1 2001:4860:4860::8888 >/dev/null" every 30 )"
ipv4_up = "( "ping -c1 -q -w 1 8.8.8.8 >/dev/null" every 30)"
initial state: auto
changing state to auto
running ping -c1 -q -w 1 8.8.8.8 >/dev/null
running ping6 -c1 -q -w 1 2001:4860:4860::8888 >/dev/null
running echo in auto:init
in auto:init
started

running ping -c1 -q -w 1 8.8.8.8 >/dev/null
running ping6 -c1 -q -w 1 2001:4860:4860::8888 >/dev/null
ping6: sendmsg: Network is down
changing state to no_ipv6
running ping6 -c1 -q -w 1 2001:4860:4860::8888 >/dev/null
ping6: sendmsg: Network is down
running ping -c1 -q -w 1 8.8.8.8 >/dev/null
running logger -t ifstated In ipv6_tunnel state init.
running logger -t ifstated IPv6 tunnel seems to be down. Attempting to restart IPv6 tunnel.

....

{brought gif0 down}

running ping6 -c1 -q -w 1 2001:4860:4860::8888>/dev/null
ping6: sendmsg: Network is down
running echo 'ipv6 is DOWN'
ipv6 is DOWN
running logger -t ifstated IPv6 tunnel seems to be down. Attempting to restart.
running /root/restart_ipv6.sh
......
interface gif0 departed
interface gif0 arrived
running ping6 -c1 -q -w 1 2001:4860:4860::8888>/dev/null
running echo 'ipv6 is up'
ipv6 is up
running ping6 -c1 -q -w 1 2001:4860:4860::8888>/dev/null

Worse situation: IPv4 goes down. Is down for a while, but then comes back up. IPv6 tunnel gets restarted.

Config

I use Google's public DNS IPs (both IPv4 and IPv6) to determine connectivity for each IP version respectively.

A ping is sent to each DNS server's IP every 60 seconds. If the result of that ping returns it failure, the state for that IP version if set to either no_ipv4 or no_ipv6 depending on which one failed. Given the tunnel's nature of running IPv6 over IPv4,if IPv4 is found to be unresponsive, the IPv6 tunnel is restarted. IPv4 going down temporarily could mean the IP has changed, and therefore we must re-establish the IPv6 tunnel.

# /etc/ifstate.conf
ipv6_up = '( "ping6 -c1 -q -w 1 2001:4860:4860::8888 >/dev/null" every 60 )'
ipv4_up = '( "ping -c1 -q -w 1 8.8.8.8 >/dev/null" every 60 )'

state auto {
      if ! $ipv4_up {
      	 set-state no_ipv4
      }
      if ! $ipv6_up {
        set-state no_ipv6
      }
}

state no_ipv4 {
  if ! $ipv4_up {
    run "logger -t ifstated No IPv4 connectivity. Attempting to restart em0."
    run "sh /etc/netstart em0"
  }
  if $ipv4_up {
    set-state auto
  }
}

state no_ipv6 {
  if ! $ipv6_up {
    run "logger -t ifstated IPv6 tunnel seems to be down. Attempting to restart IPv6 tunnel."
    run "/root/restart_ipv6.sh"
  }
  if $ipv6_up {
    set-state auto
  }
}

init-state auto

Code

#!/bin/sh
# /root/restart_ipv6.sh

TMP_HOSTNAME_FILE=/tmp/hostname.gif0
HOSTNAME_FILE=/etc/hostname.gif0
IPV4_IP=`ifconfig em0 | grep -v inet6 | grep inet | awk '{print $2}'`
IPV6_SUBNET="HE_IPV6_PREIX"

echo "# File re-generated by restart_ipv6 at `date`" > $TMP_HOSTNAME_FILE

echo "!ifconfig gif0 destroy" >> $TMP_HOSTNAME_FILE
echo "tunnel $IPV4_IP HE_IPV4_TUNNEL_IP" >> $TMP_HOSTNAME_FILE
echo "!ifconfig gif0 inet6 alias $IPV6_SUBNET::2 $IPV6_SUBNET::1 prefixlen 128" >> $TMP_HOSTNAME_FILE
echo "!route -n add -inet6 default $IPV6_SUBNET::1" >> $TMP_HOSTNAME_FILE

cp $TMP_HOSTNAME_FILE $HOSTNAME_FILE

curl HE_UPDATE_URL

sh /etc/netstart gif0

/sbin/pfctl -e -v -f /etc/pf.conf

Important Variables

  • HE_IPV6_PREFIX: The IPv6 prefix provided to you by Hurricane Electric (without the trailing colons)
  • HE_IPV4_TUNNEL_IP: IPv4 IP of the Hurricane Electric side of the IPv6-over-v4 tunnel.
  • HE_UPDATE_URL: Update URL to call to update your IPV4 IP of the tunnel.

Summary

This integration was a minimum viable product to getting integration working between ifstated and the IPv6 tunnel. There is cleanup and further error handling I could write, but given those situations have not arisen yet, I have not spent the time to dig into it.

Related