BT Infinity with IPv6 on Linux

If you’re building your own Linux based router to connect to BT Infinity you’ll probably want IPv6 working too. Address assignment works differently in IPv6 to IPv4 – we aren’t going to be given a single address we are going to be given a 56 bit prefix. From a 128 bit address that leave us a lot of bits available to use to address hosts on many sub-networks in our network. We are going to assign 64 bit prefixes to our interfaces (we can create 256 prefixes at 64 bits each) each with vastly more addresses than the entire IPv4 address space. To get our prefix from BT and delegate prefixes to our own networks we need an IPv6 DHCP client. This is where lots of other guides, forum posts, and the like, are a bit out of date (or don’t apply to BT Infinity) using wide-dhcpv6, dibbler, radvd, sysctl settings and custom scripts. Having played with various options I’ve found what works for BT Infinity in 2017, resulting in a really clean and simple method that boils down to a very simple configuration.

First the basic internet connection

I’m using a white OpenReach modem, as originally supplied for BT Infinity, connected to eth0. If you don’t have one of these excellent VDSL modems you can pick them up cheaply on eBay.

Install pppoe with “apt-get install pppoe”

Edit /etc/network/interfaces in include the following:

iface eth0 inet manual
  mtu 1508

auto vdsl
iface vdsl inet ppp
  provider bt
  pre-up /sbin/ifconfig eth0 up mtu 1508
  post-down /sbin/ifconfig eth0 down

Edit /etc/ppp/chap-secrets

# Secrets for authentication using CHAP
# client	server	secret			IP addresses
""     *       "password"

Create /etc/ppp/peers/bt (note the filename matches provider name in /etc/network/interfaces)

#BT Broadband

# Use the pppoe kernel module.
plugin eth0

# Name this connection as ppp0.
unit 0


# No default IP; allocated dynamically by ISP.

# Try to get name servers from ISP.

# Use this connection as the default route.

# Replace the default route if already present

# There is an 8 byte overhead for PPPoE; however, 
# we are using baby jumbo frames of 1508 on eth0
# to account for the extra 8 byte overhead.
mtu 1500
mru 1500

# Exclude password string when logging packet contents.
# Try to reopen the connection if it is terminated.

ipv6 ,

Run “ifup vdsl” to connect.
Then run “ifconfig” and check a new interface named ppp0 has appeared and got an IP v4 address (there will also be a link local IPv6 address (starting fe80:), but no public IPv6 address yet). You should now be able to “ping”.

Points to note:
  • The space and comma on that last line of /etc/ppp/peers/bt – they are needed!
  • We are able to pass full sized Ethernet frames (1500) through to the internet, despite the 8 byte added header of pppoe. This is because we increased the mtu of eth0 (over which this pppoe connection runs) to 1508 (instead of the default 1500) in /etc/network/interfaces
  • Although we defined an interface called vdsl, this name is only used if you call ifup / ifdown to start or stop the connection. In ifconfig and firewall rules our internet interface will be named ppp0.
  • Credit to for the basic Infinity Configuration, all I’ve added to this config is IPv6 support.

Now IPv6

Install dhcpcd5 with “apt-get install dhcpcd5”

Edit /etc/dhcpcd.conf

option rapid_commit

option domain_name_servers, domain_name, domain_search, host_name
option classless_static_routes

require dhcp_server_identifier

nohook lookup-hostname


allowinterfaces ppp0 eth1 eth1.9

interface ppp0
	ia_pd 1 ppp0/0 eth1/1 eth1.9/9

Now restart dhcpcd with “systemclt restart dhcpcd” (you only need to do this now because the config has been changed, you don’t need to start it manually normally):

Now run “ifconfig” and look at the output, you should see ppp0, eth1 & eth1.9 all have real world IPv6 addresses (output trimmed for brevity and censored):

eth0      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet6 addr: fe80::20e:c4ff:fece:db8b/64 Scope:Link

eth1      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:  Bcast:  Mask:
          inet6 addr: 2a00:xxxx:xxxx:xx01:20e:c4ff:fece:db8c/64 Scope:Global
          inet6 addr: fe80::20e:c4ff:fece:db8c/64 Scope:Link

eth1.9    Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:  Bcast:  Mask:
          inet6 addr: 2a00:xxxx:xxxx:xx09:20e:c4ff:fece:db8c/64 Scope:Global
          inet6 addr: fe80::20e:c4ff:fece:db8c/64 Scope:Link

lo        Link encap:Local Loopback
          inet addr:  Mask:
          inet6 addr: ::1/128 Scope:Host

ppp0      Link encap:Point-to-Point Protocol
          inet  Mask:
          inet6 addr: 2a00:xxxx:xxxx:xx00:3583:3ff4:c30c:e6f3/64 Scope:Global
          inet6 addr: fe80::3583:3ff4:c30c:e6f3/10 Scope:Link

You should now be able to “ping6”

Points to note:
  • This is obviously just an example adjust your network interfaces to suit. If you use different interfaces in the “ia_pd” line remember to update “allowinterfaces” too!
  • In the line “ia_pd 1 ppp0/0 eth1/1 eth1.9/9” you specify the interfaces you want to assign prefixes to. The number after the / is the prefix number – note it corresponds to the next 8 bytes of the network address after the 56 byte prefix supplied by BT (mostly censored out in the above). I like to make them match the third octet of my class C IPv4 networks, but they don’t have to.
  • Don’t change the 1 in “ia_pd 1 …”

Leave a Reply