IPv6 support on this site

Right in time for the World IPv6 Day, this site can now be reached over IPv6:

bash$ host p5r.uk
p5r.uk has address 70.85.16.194
p5r.uk has IPv6 address 2600:3c00::f03c:91ff:fe96:d898

Kudos to Linode for enabling IPv6 when other providers don't seem to care. My domain registrar, 123-reg, alas, does not offer AAAA records in their DNS manager, so I delegated the DNS to the Linode name servers. Linode has had AAAA record support on their DNS manager for quite some time now and now they are rolling native IPv6 support out on the virtual hosts.

Setup

The page Linode IPv6 describes the process in detail, but all I had to do was to open a support ticket to have a IPv6 address assigned to my Linode and to reboot my virtual host. I then refined the setup using this page: IPv6 on Debian.

Firewall

#!/bin/sh
# set -e

### BEGIN INIT INFO
# Provides:          firewall
# Required-Start:    $network $syslog
# Required-Stop:     $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start iptables based firewall
# Description:       Start IPv4 and IPv6 firewall
### END INIT INFO

# Version:      @(#)firewall  1.0.1  2006-01-22  thp.web@p5r.uk  First version IPv4 only
#                             1.2.0  2011-05-28  thp.web@p5r.uk  Added IPv6 support
#

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
NAME=firewall



iptables4=/sbin/iptables
iptables6=/sbin/ip6tables
pub_if=eth0                                 # public interface, e.g. eth0
pub_ipv4=70.85.16.194                       # public IPv4 address
pub_ipv6=2600:3c00::f03c:91ff:fe96:d898     # public IPv6 address


test -x $iptables4 || exit 0
test -x $iptables6 || exit 0

firewall_flush()
{
    # flush rules
    $iptables4 -F
    $iptables6 -F
    $iptables4 -F -t mangle
    $iptables6 -F -t mangle
    $iptables4 -X -t mangle
    $iptables6 -X -t mangle
    $iptables4 -F -t nat
    $iptables4 -X -t nat
    $iptables4 -X
    $iptables6 -X
}


firewall_default()
{
    default=$1

    # apply default rules
    $iptables4 -P INPUT   $default
    $iptables6 -P INPUT   $default
    $iptables4 -P FORWARD $default
    $iptables6 -P FORWARD $default
    $iptables4 -P OUTPUT  $default
    $iptables6 -P OUTPUT  $default
}


firewall_start()
{
    # default policy
    firewall_default DROP

    # accept everything from loopback
    $iptables4 -A INPUT  -i lo -j ACCEPT
    $iptables6 -A INPUT  -i lo -j ACCEPT
    $iptables4 -A OUTPUT -o lo -j ACCEPT
    $iptables6 -A OUTPUT -o lo -j ACCEPT

    # Allow Link-Local addresses
    $iptables6 -A INPUT -s fe80::/10 -j ACCEPT
    $iptables6 -A OUTPUT -s fe80::/10 -j ACCEPT

    # drop Bad Guys
    $iptables4 -A INPUT -m recent --update --seconds 60 -j DROP
    $iptables6 -A INPUT -m recent --update --seconds 60 -j DROP

    # Filter all packets that have RH0 headers:
    $iptables6 -A INPUT -m rt --rt-type 0 -j DROP
    $iptables6 -A FORWARD -m rt --rt-type 0 -j DROP
    $iptables6 -A OUTPUT -m rt --rt-type 0 -j DROP

    # drop spoofed packets (i.e. packets with local source addresses coming from outside etc.), mark as Bad Guy
    $iptables4 -A INPUT  -i $pub_if -s $pub_ipv4 -m recent --set -j DROP
    $iptables6 -A INPUT  -i $pub_if -s $pub_ipv6 -m recent --set -j DROP

    # accept ICMP packets (ping et.al.)
    $iptables4 -A INPUT  -p icmp   -j ACCEPT
    $iptables6 -A INPUT  -p icmpv6 -j ACCEPT
    $iptables6 -A OUTPUT -p icmpv6 -j ACCEPT
    $iptables6 -A FORWARD -p icmpv6 -j ACCEPT

    # internet (established and out)
    $iptables4 -A OUTPUT -o $pub_if -j ACCEPT
    $iptables6 -A OUTPUT -o $pub_if -j ACCEPT
    $iptables4 -A INPUT  -i $pub_if -m state --state ESTABLISHED,RELATED -j ACCEPT
    $iptables6 -A INPUT  -i $pub_if -m state --state ESTABLISHED,RELATED -j ACCEPT

    # allow public services
    $iptables4 -A INPUT -i $pub_if -p tcp -d $pub_ipv4 -m multiport --dports 25,80,143,443,465,993,8000 -j ACCEPT
    $iptables6 -A INPUT -i $pub_if -p tcp -d $pub_ipv6 -m multiport --dports 25,80,143,443,465,993,8000 -j ACCEPT

    # accept ssh connections (max 2/minute from the same IP address)
    $iptables4 -A INPUT -p tcp --dport 22 -m recent --update --seconds 300 --hitcount 10 --name SSH -j DROP
    $iptables6 -A INPUT -p tcp --dport 22 -m recent --update --seconds 300 --hitcount 10 --name SSH -j DROP
    $iptables4 -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH -j ACCEPT
    $iptables6 -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH -j ACCEPT

    # reject everything else in INPUT
    $iptables4 -A INPUT -j REJECT
    $iptables6 -A INPUT -j REJECT
}

firewall_stop()
{
    # flush rules
    firewall_flush

    # default policy
    firewall_default ACCEPT
}

case "$1" in
    start)
        echo -n "Starting $NAME: "
        firewall_start
        echo "OK."
        ;;
    stop)
        echo -n "Stopping $NAME: "
        firewall_stop
        echo "OK."
        ;;
    restart|reload)
        echo -n "Restarting $NAME: "
        firewall_stop
        sleep 1
        firewall_start
        echo "OK."
        ;;
    *)
        echo "Usage: /etc/init.d/$NAME {start|stop|restart|reload}" >&2
        exit 1
        ;;
esac

exit 0