This component does a few important things:
-
Retrieves an IPv6 address (from comcast) for our external interfaces (Using IA).
-
Retrieves a prefix from comcast using Prefix Discovery (PD). By default, comcast will send a /64 prefix, which is only good for one host (we need more networks, as routing anything less than a /64 tends to break a lot of stuff in ipv6). In this case, we use
wide-dhcpv6-client
to request a /60 from comcast. Note that the network is not related to the IP address given to the interface. -
Assign ipv6 addresses to each of the other interfaces, based on the prefix received from comcast and our configuration (see below).
-
Note that routes (including default routes) in ipv6 are assigned via RA. Make sure
net.ipv6.conf.all.accept_ra
andnet.ipv6.conf.<interface>.accept_ra
are both set to 2 in/etc/sysctl.conf
(normally interface here is the WAN interface, eth0.)Sample
/etc/sysctl.conf
entries:net.ipv6.conf.all.accept_ra=2 net.ipv6.conf.eth0.accept_ra=2
- Note: Setting it to 1 will work partially, but the WAN interface (eth0) won't receive the default route to the Internet, breaking things.
Sample wide-dhcpv6 config (eth0 = external interface, lan0.X = internal VLANs:)
profile default
{
information-only;
script "/etc/wide-dhcpv6/dhcp6c-script";
};
interface eth0 {
send ia-na 1;
send ia-pd 1;
};
id-assoc na 1 {
};
id-assoc pd 1 {
# Request a /60 from Comcast.
prefix ::/60 infinity;
# `sla-id` is the Site Level Aggregator (SLA) used to form the ipv6 of each
# of the interfaces. The format is normally `<prefix><sla-id>::<if-id>`. We
# Match the VLAN number for easy identification of IPv6 addresses.
#
# `sla-len` is how long the SLA ID should be (in bits). In our case, we have
# a /60 given to us by Comcast and we want each interface to have a /64,
# so this should be 4.
#
# `if-id` identifies the interface number (in practive, the last octet)
# inside each interface. We use 1 so that each interface in the server
# will end up in `:1`.
#
# To reset the DUID (including the PD ip range), remove `/var/lib/dhcpv6/dhcp6c_duid`
# and restart wide-dhcpv6.
# Guest network
prefix-interface lan0.3 {
sla-id 3;
sla-len 4;
ifid 1;
};
# Internal network
prefix-interface lan0.4 {
sla-id 4;
sla-len 4;
ifid 1;
};
# DMZ
prefix-interface lan0.5 {
sla-id 5;
sla-len 4;
ifid 1;
};
};
wide-dhcpv6 is started by systemd. Extra configuration is present in /etc/default/wide-dhcpv6-client
.
Sample:
# Interfaces on which the client should send DHCPv6 requests and listen to
# answers. If empty, the client is deactivated.
INTERFACES="eth0"
# Verbose level for syslog. Default is 0 (0: minimal; 1: info; 2: debug)
VERBOSE=1
DNSMASQ is used to:
-
Assign internal IPv6 addresses, based on the client's ipv4 addresses and their network.
-
Send Route Advertisements (RA) to the internal networks.
To enable RA, set enable-ra
in /etc/dnsmasq.conf
.
IPv6 can also use RAs for IPs, setting the AAAA record from ipv6 dhcp_names. Sample excerpt from
/etc/dnsmasq.conf
:
# ipv6: Use RA for IPs, set AAAA records from ipv4 dhcp names.
dhcp-range=set:guest_v6,::100,constructor:lan0.3, ra-names, 24h
dhcp-range=set:internal_v6,::100,constructor:lan0.4, ra-names, 24h
dhcp-range=set:dmz_v6,::100,constructor:lan0.5, ra-names, 24h
(See dnsmasq documentation for more details.)
Use radvdump
to see the stream of RA messages.
Sample routing table on client inside internal network:
$ ip -6 route show
::1 dev lo proto kernel metric 256 pref medium
2601:646:9680:5924::/64 dev eth0 proto ra metric 100 pref medium
fe80::/64 dev eth0 proto kernel metric 100 pref medium
fe80::/64 dev veth7092176 proto kernel metric 256 pref medium
fe80::/64 dev docker0 proto kernel metric 256 pref medium
fe80::/64 dev veth8546e3b proto kernel metric 256 pref medium
fe80::/64 dev veth4f0c5a1 proto kernel metric 256 pref medium
default via fe80::6ca2:99ff:fe50:d55d dev eth0 proto ra metric 100 pref medium
Note how the fe80 (link local) addresses are used for routing. The default gateway points to the link local address of the router.
For some reason, there's no default route pointing to Comcast (on the server):
$ ip -6 r s | grep '^default'
<nothing>
Using radvdump
we see messages coming from eth0 (fe80::201:5cff:fea9:3446), but no
default routes. The following routes are present (but still don't generate entries
in the routing tables):
prefix 2001:558:4000:62::/64
prefix 2001:558:5027:c6::/64
prefix 2001:558:6045:74::/64
prefix 2001:558:8046:b6::/64
Adding a default route by hand works:
ip -6 route add default via fe80::201:5cff:fea9:3446 dev eth0
Cause: missing accept_ra = 2 in /etc/sysctl.conf
.
Instead of arp
use ip -6 neigh show
to see ipv6 and mac addresses.
- Test your ipv6 connectivity: https://test-ipv6.comcast.net/index.html.en_US
IPV6 can use DHCP6 or SLAAC (stateless) to give addresses to clients. SLAAC is simpler, but can't be used to set fixed addresses on certain hosts, for example.
Clients typically end up with two types of addresses on clients: "temporary dynamic" and "mngtmpaddr noprefixroute". The first is, as the name implies, dynamic and used by clients (for privacy purposes). The second is the "fixed" address of the machine, used for inbound connections. Once dynamic addresses expire, they become "temporary deprecated dynamic" until they eventually disappear from the address table.
Example:
$ ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether c8:60:00:5f:9f:d8 brd ff:ff:ff:ff:ff:ff
inet 172.30.1.250/24 brd 172.30.1.255 scope global dynamic noprefixroute eth0
valid_lft 49902sec preferred_lft 49902sec
inet 192.168.1.2/24 brd 192.168.1.255 scope global eth0:0
valid_lft forever preferred_lft forever
inet6 2601:646:9600:3f74:a833:98c4:93d:a967/64 scope global temporary dynamic
valid_lft 86078sec preferred_lft 84489sec
inet6 2601:646:9600:3f74:ca60:ff:fe5f:9fd8/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 86078sec preferred_lft 86078sec
inet6 2601:646:9681:22e4:db94:864b:3402:c113/64 scope global temporary deprecated dynamic
valid_lft 5220sec preferred_lft 0sec
inet6 2601:646:9681:22e4:ca60:ff:fe5f:9fd8/64 scope global deprecated dynamic mngtmpaddr noprefixroute
valid_lft 5220sec preferred_lft 0sec
inet6 2601:646:9680:5924:fa0d:1d58:9008:3626/64 scope global temporary deprecated dynamic
valid_lft 5092sec preferred_lft 0sec
inet6 2601:646:9680:5924:6ec7:e5b6:d30b:188/64 scope global temporary deprecated dynamic
valid_lft 5092sec preferred_lft 0sec
inet6 2601:646:9680:5924:ca60:ff:fe5f:9fd8/64 scope global deprecated dynamic mngtmpaddr noprefixroute
valid_lft 5092sec preferred_lft 0sec
inet6 fe80::ca60:ff:fe5f:9fd8/64 scope link noprefixroute
valid_lft forever preferred_lft forever