I want IPv6 to actually work on my network, here's how.

Here's a general overview of my setup, Comcast Business for my internet, a Raspberry PI running Debian 10 (Buster) as my firewall/router, a whole slew of systems behind it with a smattering of types of devices and OS's. I use nftables and not iptables. On my firewall, my internal interface is eth0 and my external is enxd037450b2409.

This guide does not contain anything about advertising routes and autoconfiguring IPv6, take a look here https://www.frakkingsweet.com/radvd-on-debian-10/ for that. For this guide, you will need to assign static addresses to your systems for it to work. Implementing radvd on the linked post will autoconfigure all of your devices on your network and is a sequel to this post.

First thing, this probably only applies to Raspberry PI's, make sure IPv6 is not disabled. sudo vi /boot/cmdline.txt. If you have disable.ipv6=1 there, remove it. Save and reboot. I honestly don't remember if I added it or not, but it was there on mine and I had to remove it. With it there I was getting an error in my logs from dhcpcd. The error was Address family not supported by protocol. If you get that error throughout this guide you will need to make sure that IPv6 is enabled.

Second, check to see if you have an IPv6 address already, ip -6 a. Should output a few addresses. Yours won't match but here is an example:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2603:3026:41d:7df3::1/64 scope global dynamic noprefixroute
       valid_lft 203938sec preferred_lft 99906sec
    inet6 fe80::8b5c:a54f:f2ac:303b/64 scope link
       valid_lft forever preferred_lft forever
3: enxd037450b2409: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2603:3026:41d:7d00::1/128 scope global dynamic noprefixroute
       valid_lft 203938sec preferred_lft 99906sec
    inet6 2603:3026:41d:7d00:b196:9cb1:cf62:25d/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 253173sec preferred_lft 253173sec
    inet6 fe80::bb7f:780b:84c5:dc56/64 scope link
       valid_lft forever preferred_lft forever

Next, set up your Comcast gateway to give out chunks of addresses. Open your admin page to your cable modem, the default username/password combination is cusadmin and highspeed. After you update the values be sure to pull the plug on the power, wait a minute then plug it back in. Took me a while to figure out that it is required for it to truly work.

  • I don't entirely know if you need to fill out the assigned User defined prefix, but I did. The System Delegated Prefix is set it to the same value as IPv6 Prefix, Number of addresses is 255 and Valid Lifetime is 208064.
  • Enable Rapid Commit is checked
  • Enable Unicast is not checked
  • Enable EUI-64 Addressing is not checked
  • Enable DHCPv6 is checked
  • Assign DNS Manually is not checked

Now that your modem is setup we need to configure the kernel. Without this part traffic won't flow and it won't get the prefix delegation that you need. Replace enxd037450b2409 with your internet facing interface.

sudo sysctl net.ipv6.conf.all.forwarding=1
sudo sysctl net.ipv6.conf.enxd037450b2409.accept_ra=3

To make this persist through reboots, sudo vi /etc/sysctl.d/11-ipv6forward.conf. The contents are:

net.ipv6.conf.all.forwarding=1
net.ipv6.conf.enxd037450b2409.accept_ra=3

The forwarding=1 tells the kernel to allow forwarding traffic through the interfaces and the accept_ra tells the kernel to respond to ICMPv6 packets as though it is a router and a client device. In the normal world, a system is either one but not both. In the Comcast world, we need to be both.

Now that the kernel is set up, lets configure the dhcpcd daemon on the firewall. Remember, eth0 is my internal interface and enxd037450b2409 is my external.

sudo vi /etc/dhcpcd.conf

# comment out clientid
# uncomment duid

interface eth0
 static ip_address=x.x.x.x/24 # internal IPv4 address
 noipv6rs

interface enxd037450b2409
 static ip_address=x.x.x.x/28 # public IPv4 address
 static routers=x.x.x.x # public IPv4 router
 static domain_name_servers=8.8.8.8 # dns server
 ipv6rs
 ia_na 0
 ia_pd 0/::/60 eth0/3/64

The clientid, duid, noipv6rs, ipv6rs, ia_na 0 and ia_pd blah are the important parts. To see what they mean you can check out the man page at http://manpages.ubuntu.com/manpages/trusty/man5/dhcpcd.conf.5.html

Now that dhcpcd is configured, in one terminal, watch the logs. On Debian, sudo tail -f /var/log/syslog. In another terminal restart dhcpcd. On Debian, sudo systemctl restart dhcpcd.

You should see some messages in the logs about your prefix delegation, look for the entry that says its adding a route to your internal interface. Here's an example of what you are looking for:

Jul 24 18:08:54 firewall dhcpcd[6372]: eth0: adding address 2603:3026:41d:7df3::1/64
Jul 24 18:08:54 firewall dhcpcd[6372]: eth0: adding route to 2603:3026:41d:7df3::/64

The first line is the gateway address for your clients and the second is the subnet that you use on your internal network. In this case, the gateway is 2603:3026:41d:7df3::1 and the subnet is 2603:3026:41d:7df3::/64.

If you run into firewall issues, make sure you open up traffic sourced from UDP port 547 (dhcpv6-server) and destined to 546 (dhcpv6-client) and ICMPv6. The necessary accept rules for nftables.conf are this:

ip6 saddr fe80::/10 ip6 daddr fe80::/10 udp dport dhcpv6-client accept
ip6 saddr fe80::/10 ip6 daddr fe80::/10 udp dport dhcpv6-server accept
ip6 nexthdr ipv6-icmp accept
icmpv6 type { destination-unreachable, packet-too-big, time-exceeded } accept
icmpv6 type { nd-router-advert, nd-neighbor-advert, nd-neighbor-solicit } ip6 saddr fe80::/64 ip6 daddr fe80::/64 accept

In theory, if the logs are clear you should be good to go. Set an IPv6 address on your client in the subnet you were given with the appropriate gateway and some DNS servers and you should be set. For reference, the Comcast DNS servers I received are: 2001:558:feed::1 and 2001:558:feed::2. Try and ping something over IPv6 ping -6 www.google.com

If you run into issues let me know, I'll try and help and update this post if necessary.