IPv6 on Comcast Residential

Comcast has now opened up their IPv6 service to residential customers. If you have a supported modem from Comcast and a device connected to it that understands IPv6 you can connect. You might ask why would I want to setup IPv6? And that is a good question. One reason is to stay up to date with current networking technology. Another reason is that we’re running out of IPv4 addresses and we will eventually need to switch to IPv6. Currently many sites on the Internet are supporting IPv4 and IPv6 to help with the adoption of IPv6. Another reason for IPv6 support is that this setup can give you a subnet of public IPv6 addresses to use in your house. Meaning that you can allow computers on your internal network to be accessible from the outside world. Of course this also means that you could potentially open up your computers to the outside world, so you need to be careful and setup your firewall to keep your internal computers secure unless you want them accessible. This also removes any issues with NAT as IPv6 doesn’t have any NAT support.

For my setup I have a compatible modem from Comcast and a Linux computer as my router. My Linux computer is running Ubuntu. These instructions are specific to my setup, but should be able to be used by others running most any Linux distribution.

The first thing you should do is secure your network from IPv6 so that something doesn’t get in while you’re setting things up. Here is my IPv6 firewall setup, it’s very similar to my IPv4 setup, except the port numbers for DHCP are different. Outbound traffic is allowed and inbound traffic is denied. I’ve also disabled forwarding of traffic, this prevents inbound traffic directly to the internet work. This script needs to be located at “/usr/local/sbin/firewall-ipv6-start” for the radvd script at the end of this post to work properly.

#!/bin/sh 

IPTABLES=/sbin/ip6tables
INET_IFACE="eth0"
LAN_IFACE="eth1"
LO_IFACE="lo"

$IPTABLES -F
$IPTABLES -X

# accept everything by default
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD DROP

${IPTABLES} -A FORWARD \
 -m state --state RELATED,ESTABLISHED \
 -m comment --comment "allow inbound traffic for established and related connections" \
 -j ACCEPT
${IPTABLES} -A FORWARD \
 -i ${LAN_IFACE} -o ${INET_IFACE} \
 -m comment --comment "allow all Internet bound traffic from the internal network" \
 -j ACCEPT
${IPTABLES} -A FORWARD -p ipv6-icmp \
 -m comment --comment "forward any ICMP traffic" \
 -j ACCEPT

${IPTABLES} -A INPUT \
 -m state --state RELATED,ESTABLISHED \
 -m comment --comment "allow inbound traffic for established and related connections" \
 -j ACCEPT

${IPTABLES} -A INPUT \
 -i ${LO_IFACE} \
 -m comment --comment "allow any local-only traffic" \
 -j ACCEPT

${IPTABLES} -A INPUT \
 -p ipv6-icmp \
 -m comment --comment "allow ICMP traffic from anywhere" \
 -j ACCEPT

${IPTABLES} -A INPUT -i ${INET_IFACE} \
 -p udp -m udp --dport 546 \
 -m comment --comment "Accept DHCP traffic" \
 -j ACCEPT

${IPTABLES} -A INPUT -i ${INET_IFACE} \
 -p udp -m udp --dport 547 \
 -m comment --comment "Accept DHCP traffic" \
 -j ACCEPT
 

The remainder of this post is based upon this post on using DHCPv6 with prefix delegation.

The next thing we need to do is get an address from Comcast along with a prefix (subnet) to hand out to the computers on the internal network. Comcast doesn’t appear to be using router advertisements for IPv6, so we’ll need to use DHCP over IPv6. For this I could use the ISC DHCP server that I’m using for IPv4, but it doesn’t support prefix delegation which I need to give the other computers in my house IPv6 addresses. For this I installed wide dhcp client. Ubuntu includes this in the package wide-dhcpv6-client. A side advantage to using a different DHCP client for IPv6 is that you can turn it off to disable IPv6 support without messing with your IPv4 network. Once you install the client edit /etc/wide-dhcpv6/dhcp6c.conf to look like this. You will need to modify the interface used and possibly the sla-len. I found the sla-len by trial and error. You won’t get a prefix if the value is incorrect.

interface eth0 { # external facing interface (WAN)
 send ia-na 1;
 send ia-pd 1;

 request domain-name-servers;
 request domain-name;

 script "/etc/wide-dhcpv6/dhcp6c-script";
};

id-assoc pd 1 {
 prefix-interface eth1 { #internal facing interface (LAN)
 sla-id 0; # subnet. Combined with ia-pd to configure the subnet for this interface.
 ifid 1; # IP address "postfix". if not set it will use EUI-64 address of the 
         # interface. Combined with SLA-ID'd prefix to create full IP address of interface.
 sla-len 0; # prefix bits assigned. Take the prefix size you're assigned
            # (something like /48 or /56) and subtract it from 64. 
            # In my case I was assigned a /64, thus the value is 0
 };
};

id-assoc na 1 {
 # id-assoc for external interface
};

When you start the wide DHCP client and all is happy you will find that your external interface has an address. In my case it starts with 2001:558:6014. See the output of “ip addr show dev eth0” changing the interface as appropriate. Below is the output for my system with the IP addresses masked out.

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
 link/ether 00:d0:b7:3f:4d:18 brd ff:ff:ff:ff:ff:ff
 inet XXX.XXX.XXX.XXX/22 brd 255.255.255.255 scope global eth0
 valid_lft forever preferred_lft forever
 inet6 2001:558:6014:XXXX:XXXX:XXXX:XXXX:XXXX/128 scope global 
 valid_lft forever preferred_lft forever
 inet6 fe80::XXXX:XXXX:XXXX:XXXX/64 scope link 
 valid_lft forever preferred_lft forever

Once this is setup you can ping IPv6 addresses from your router. You can test this with “ping6 google.com”.

Now to allow your local network talk to the Internet via IPv6 you’ll need to allow forwarding and then assign them IPv6 addresses.

First we’ll tell the kernel to allow forwarding by modifying adding the file 70-ipv6-routing.conf to /etc/sysctl.d. Note that net.ipv6.conf.all.accept_ra is set to 2. Any other value will not work due to how the router advertisements are handled.

# only set this on the external interface, otherwise we don't get a
# default route for IPv6
net.ipv6.conf.EXT_IFACE.accept_ra=2
net.ipv6.conf.EXT_IFACE.forwarding=0

net.ipv6.conf.INT_IFACE.accept_ra=1
net.ipv6.conf.INT_IFACE.forwarding=1

net.ipv6.conf.all.forwarding=1
net.ipv6.conf.all.autoconf=1

 
Once you change these values you will need to reboot or use the sysctl utility to set them immediately.

Now to hand out IPv6 addresses to the rest of the network. This will be done by setting up radvd. The package ‘radvd’ on Unbuntu contains this daemon. Once installed you can setup /etc/radvd.conf for the prefix that Comcast gave you. However when your IP address changes you’ll need to update the file. So instead I have created a script that can be run from wide dhcp client. Put the following in “/usr/local/sbin/update-ipv6-setup.sh” and add a call to this script from the end of /etc/wide-dhcpv6/dhcp6c-script. You’ll need to change the interface in this script to be your internal interface.

#!/bin/sh

debug() { ! "${log_debug-false}" || log "DEBUG: $*" >&2; }
log() { printf '%s\n' "$*"; }
warn() { log "WARNING: $*" >&2; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$*"; exit 1; }
try() { "$@" || fatal "'$@' failed"; }

mydir=$(cd "$(dirname "$0")" && pwd -L) || fatal "Unable to determine script dir
ectory"

prefix=$(ip -6 addr show dev eth1 scope global \
 | grep inet6 \
 | awk '{print $2}') \
 || fatal "Unable to get prefix"

cat > /etc/radvd.conf.new <<EOF

interface eth1
{
 AdvSendAdvert on;
 AdvIntervalOpt on;
 MinRtrAdvInterval 60;
 MaxRtrAdvInterval 300;
 AdvLinkMTU 1280;
 AdvOtherConfigFlag on;
 AdvHomeAgentFlag off;
 
 prefix ${prefix}
 {
 AdvOnLink on;
 AdvAutonomous on;
 AdvRouterAddr on;
 };
};

EOF

diff /etc/radvd.conf.new /etc/radvd.conf > /dev/null
if [ $? -ne 0]; then 
 # only move if there are differences
  try mv -f /etc/radvd.conf.new /etc/radvd.conf
  try service radvd restart
fi
try /usr/local/sbin/firewall-ipv6-start

Now you have IPv6 setup on your router and your home network. I found that Linux, Windows and Mac automatically recognize the IPv6 router advertisements and grab addresses and setup routes appropriately.

Resources: