Setting up FreeBSD with Comcast IPv6

There have been a number of how-to posts of various ages. Here's how I do it with no pain and suffering.

There's some documentation in the FreeBSD handbook but it is not usable for a Comcast client configuration.

Background: I use a simple FreeBSD-9 Via Nano X2 system for my gateway. I use pf + nat for IPv4 but choice of firewall isn't important here. Since you're not using NAT, you do need to be mindful of needing a firewall solution.

pkg install net/dhcp6

The WIDE dhcp6 client Just Works(TM). I was unable to get the ISC counterpart to work at all.

In IPv6, dhcp can ask for a prefix delegation (PD) and a network address (NA). The NA address is your gateway's outward facing address, the PD goes on your internal interfaces. You do simple IPv6 rounting / firewalling between them. No NAT. Ever.

You need an important /etc/sysctl.conf line:

net.inet6.ip6.rfc6204w3=1

This allows the machine to be both a router and accept router advertisements at the same time.

The relevant rc.conf lines, where re0 is my internal interface and sk0 is the Comcast side:

ifconfig_re0="inet 10.0.0.1 netmask 255.255.255.0"
ifconfig_re0_ipv6="inet6 fe80::1"

ifconfig_sk0="DHCP"
ifconfig_sk0_ipv6="inet6 accept_rtadv"

gateway_enable="YES"
ipv6_gateway_enable="YES"
ipv6_default_interface="re0"

dhcp6c_enable="YES"
dhcp6c_interfaces="sk0"

rtadvd_enable="YES"
rtadvd_interfaces="re0"

/etc/rtadvd.conf:

re0:\
        :prefixlen#64:

And finally, /usr/local/etc/dhcp6c.conf

interface sk0 {
        send    ia-na 1;
        send    ia-pd 1;
        send    rapid-commit;
};

id-assoc pd 1 {
        prefix ::/64 3600;
        prefix-interface re0 {
                sla-len 0;
                sla-id 0;
        };
};
id-assoc na 1 {
};

The short version of this is:

  • Ask Comcast for a network address (NA), use it on sk0.
  • Ask comcast for a /64 prefix (PD) and use it on re0.
  • Advertise my gateway to the internal network and let all my internal hosts auto-configure.
  • Route both ipv4 and ipv6 packets. IPv4 will be NATed, IPv6 will be directly routed and statefully firewalled.

This is vastly under-using the capabilities of this configuration. Comcast will give you a /60 prefix if you ask for it. You can then carve that up for multiple internal networks using the sla-len and sla-id to put different networks on different interfaces/vlans/whatever. Read the documentation for this.

You can (and probably should) use a v6 dhcp server on your internal network so you can assign fixed addresses to internal devices, use v6 ntp/dns and so on. I never quite got around to doing it as all my home devices have access to the RFC1918 internal services and IPv6.

The basics of a pf.conf setup for this:

scrub in all
# Translate IPv4 as it passes through.
nat on re0 from 10.0.0.0/24 to any -> (re0)

# block by default:
block return log on re0 all

# Allow clients to talk to the gateway
pass in on sk0

# Automatic stateful reverse path
pass out on re0

# and ICMP
pass in inet proto icmp all icmp-type echoreq
pass in inet6 proto ipv6-icmp all icmp6-type { 1, 2, 3, 4, 128, 129, 135, 136 }

Again, this is dangerously simplified, but it should be enough to build on.

I do not recall if a rule for DHCPv6 replies are needed.

At the end of the day, the gateway will look something like this:

re0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	inet 10.0.0.1 netmask 0xffffff00 broadcast 10.0.0.255
	inet6 fe80::ca9c:xxxx:2bee%re0 prefixlen 64 scopeid 0x1 
	inet6 fe80::1%re0 prefixlen 64 scopeid 0x1 
	inet6 2601:xxxxxxx:2bee prefixlen 64 
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL
sk0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	inet6 fe80::20c:xxxx:3eaa%sk0 prefixlen 64 scopeid 0x2 
	inet6 2001:558:xxxxx:4860:1a54 prefixlen 128 
	inet 73.xxxxxxxxx netmask 0xfffffe00 broadcast 255.255.255.255
	nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>

In the ifconfig output above, you can see the inet 73.x.x.x comcast address and the /128 "NA" address. You can see the internal re0 interface with a /64 address.

Another random machine in my home has:

ifconfig_re0_ipv6="inet6 accept_rtadv"
rtsold_enable="YES"
ip6addrctl_policy="ipv6_prefer"  

And it Just Works(TM).

re0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	inet6 fe80::ae2f:xxxx:f4fb%re0 prefixlen 64 scopeid 0x1 
	inet6 2601:642:xxxxxxx:f4fb prefixlen 64 autoconf 
	inet 10.0.0.3 netmask 0xffffff00 broadcast 10.0.0.255 
	nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
# route get -inet6 default
   route to: default
destination: default
       mask: default
    gateway: fe80::ca9c:xxxx:2bee%re0

It uses the link-local address for the gateway. Traceroute6 out should just work. Traceroute6 can work too if you open the UDP ports to your internal machines.

TL;DR: FreeBSD is easy to use as a gateway with Comcast IPv6, but the documentation you've probably seen is all wrong.

Contact info