ATT Business Fiber and IPv6 Prefix Delegation

Earlier this week I had ATT Business fiber installed in the new apartment. This building was gutted and rebuilt in the mid-2010s, so there was already ATT UVerse fiber in the utility closet. Installation was fairly trivial; the technician showed up with a gateway (looks like a BGW210-700). Four ethernet ports on the back, one port which goes to the PON (the thing already screwed on the wall with the fiber going into it), and power. Probably took longer waiting for the line to train than it did to actually plug it all in.

After some confusion on the part of my contact (apparently, when you order a static IPv4 block they won’t tell you what it is until you call in to tech support and they click some things. Sadly, in the finest ATT tradition You Must Always Call, there’s no email support or ticket portal) IPv4 was up and just running.

The next thing I wondered about was IPv6. ATT talks about IPv6 in various places on their website, but there’s precious little information about what you actually get or how it works. There are customer forums on their site, which are … a morass of vague, conflicting or just wrong information. Tech support wasn’t much help; the person on the phone said, and I quote, “Oh, we don’t do IPv6.” Combined with my lack of any real experience with IPv6 I was in for a ride.

My external gateway (the thing plugged directly into the ATT gateway, behind which the rest of my network lived) had some auto-assigned, real IPv6 address, in ATT space, so I knew something was working. And the minimal web portal you get to the ATT gateway showed an IPv6 address, but in the delegated prefixes section had nothing listed. In digging around, I gleaned that you could get prefixes delegated if you used dhcpv6, and the ifupdown package in Debian Buster (my gateway) could be configured to ask for prefix delegation, but with no way in /etc/network/interfaces to specify what prefix size to ask for. I wanted more than a /64, so I could have different subnets.

At first I just ran dhclient manually with the appropriate flags to ask for a prefix delegation, but I couldn’t get more than a single /64. But, I noticed, the delegated prefix network part ended with ef, and the auto-assigned address ended with e0, so there looked like a /60 was sitting there for me.

Turns out what you have to do is ask for multiple prefix delegations, of size /64. I believe what’s happening is that the ATT gateway starts up, connects upstream, and gets a /60 assigned. It sits on the “0” network (“e0” in my setup), and any thing behind it plugged directly into it which tries to do SLAAC will get some address in that “e0” /64. But you can ask for up to 8 /64 prefix delegations via dhcpv6, which will sit on the “8” through “f” networks (“e8” through “ef” in my case). The ATT gateway basically goes “okay, you get those networks and they’re your problem, I’ll send traffic for them your way”. I have no idea what happens with the “e1” through “e7” networks; no matter what I tried I couldn’t get more than 8 delegations. 8 subnets will probably be enough for my apartment.

Here’s what seems to be the process:

  1. The interface on your gateway uses SLAAC to get a routable IPv6 address in the initial /64, and gets the default gateway that way (you do not seem to get that back via dhcpv6)
  2. You run dhclient -6 ... to ask for delegated prefixes. You’ll get also get one “ia-na” addresses (identity association non-temporary address). This will be something in that 0 /64 with a weirdly low number; I have concrete examples below.
  3. You’ll also get as many delegated prefixes as you asked for, up to eight in total. Those are “ia-pd” (identity association for prefix delegation).

“Identity associations” in DHCPv6 are what we used to call “leases” in DHCPv4. “These things belong to you”, essentially, since DHCPv6 doesn’t just handle single addresses, it can hand out delegations and the like.

I’m still working out how to handle running dhclient -6 outside the control of ifupdown, since it won’t run it in the mode where you can ask for multiple prefix delegations, but honestly, I don’t need ifupdown to run dhclient. I just need to run it — and you do need to keep it running, as if dhclient fails to renew it’s identity associations, or gives them up, the ATT gateway will stop routing traffic to the delegated prefixes.

Here’s what things look like:

/etc/network/interfaces:

iface bond0.102 inet6 auto
    accept_ra 2
    dhcp 0

bond0.102 is my external interface, accept_ra 2 says “accept router announcements and use them for forwarding, and don’t try DHCPv6. auto tells ifupdown to do SLAAC.

This results in an interface which looks like:

$ ip -6 a l bond0.102
10: bond0.102@bond0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet6 2600:1700:XXXX:XXe0:yyyy:yyyy:yyyy:yyyy/64 scope global dynamic mngtmpaddr 
       valid_lft 3493sec preferred_lft 3493sec
    inet6 fe80::zzzz:zzzz:zzzz:zzzz/64 scope link 
       valid_lft forever preferred_lft forever

2600:1700:XXXX:XXe0:yyyy:yyyy:yyyy:yyyy/64 is the SLAAC assigned address, it looks like the normal IPv6 modified EUI-64 interface addresses. Our routes look like this:

$ip -6 r l
::1 dev lo proto kernel metric 256 pref medium
2600:1700:XXXX:XXe0::/64 dev bond0.102 proto kernel metric 256 expires 3294sec pref medium
fe80::/64 dev bond0 proto kernel metric 256 pref medium
fe80::/64 dev bond0.100 proto kernel metric 256 pref medium
fe80::/64 dev bond0.101 proto kernel metric 256 pref medium
fe80::/64 dev bond0.102 proto kernel metric 256 pref medium
fe80::/64 dev tun0 proto kernel metric 256 pref medium
default via fe80::xxxx:xxxx:xxxx:xxxx dev bond0.102 proto ra metric 1024 expires 1494sec hoplimit 64 pref medium

So, loopback, the local network for the SLAAC assigned address on bond0.102, a bunch of link local addresses, one per device on this host, and then a default route. Note that the default route is another link local address, in this case it’s the link local address of the ATT gateway at the other end of the cable, which honestly is all you need (although this may not be best practice, apparently, but that’s for another day).

Let’s start dhclient:

$ sudo /sbin/dhclient -6 -v -pf /run/dhclient6.bond0.102.pid -lf /var/lib/dhcp/dhclient6.bond0.102.leases -I -P -P -P -P -P -P -P -P -N -d bond0.102
[...]
RCV: Advertise message on bond0.102 from fe80::attg:atew:aylo:cal.
RCV:  X-- Preference 255.
RCV:  X-- IA_NA aa:bb:cc:dd
RCV:  | X-- starts 1607661933
RCV:  | X-- t1 - renew  +1800
RCV:  | X-- t2 - rebind +2880
RCV:  | X-- [Options]
RCV:  | | X-- IAADDR 2600:1700:XXXX:XXe0::46
RCV:  | | | X-- Preferred lifetime 3600.
RCV:  | | | X-- Max lifetime 3600.
RCV:  X-- IA_PD aa:bb:cc:dd
RCV:  | X-- starts 1607661933
RCV:  | X-- t1 - renew  +1800
RCV:  | X-- t2 - rebind +2880
RCV:  | X-- [Options]
RCV:  | | X-- IAPREFIX 2600:1700:XXXX:XXef::/64
RCV:  | | | X-- Preferred lifetime 3600.
RCV:  | | | X-- Max lifetime 3600.
RCV:  X-- IA_PD aa:bb:cc:dd
RCV:  | X-- starts 1607661933
RCV:  | X-- t1 - renew  +1800
RCV:  | X-- t2 - rebind +2880
RCV:  | X-- [Options]
RCV:  | | X-- IAPREFIX 2600:1700:XXXX:XXee::/64
RCV:  | | | X-- Preferred lifetime 3600.
RCV:  | | | X-- Max lifetime 3600.
[...]

It goes on with as many IA_PD as you asked for, up to eight here. IAADDR 2600:1700:XXXX:XXe0::46 is the additional address assigned via dhcpv6, not sure if it’s used but there it is. Note that it’s in e0, the same /64 as the SLAAC assigned address for bond0.102 is at. IAPREFIX 2600:1700:XXXX:XXef::/64 is the first prefix, you’ll also get ee, ed through e8.

Note now that if you look at the addresses on bond0.102 you’ll see:

10: bond0.102@bond0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet6 2600:1700:XXXX:XXe0::46/128 scope global 
       valid_lft forever preferred_lft forever
    inet6 2600:1700:XXXX:XXe0:yyyy:yyyy:yyyy:yyyy/64 scope global dynamic mngtmpaddr 
       valid_lft 3493sec preferred_lft 3493sec
    inet6 fe80::zzzz:zzzz:zzzz:zzzz/64 scope link 
       valid_lft forever preferred_lft forever

you now have two global scope addresses on that interface. It’s IPv6, just throw more addresses on things. I’m fine with that.

It’s interesting to go dig through your /var/lib/dhcp/dhclient6.bond0.102.leases, you’ll see a record of everything. Next is figuring out how to consume that information; I don’t know if that /60 is statically assigned to me, that particular ATT gateway, or what. But you can manually start assigning addresses to your gateway interfaces for different subnets, and figure out how to handle addresses to clients there, perhaps with radvd or the like.

Update: The ATT gateway is still acting like a firewall, so be sure to go into the administrative interface and turn everything off if you want all access control to be done at your gateway.