paulgorman.org/technical

IPv6

(April 2017)

RFC 8200 covers IPv6.

Problems IPv6 Solves

Problems IPv6 creates

IPv6 Addresses

Address Types and Scopes

IPv6 has three address types.

A unicast or anycast address has one of these scopes (multicast has its own inherent scope):

IPv6 also has a handful of “special” addresses, such as:

https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml

(The “site-local” addresses scope was deprecated in RFC 3879. Unique local addresses (ULA) fill a similar role.)

On startup, a host creates a “link-local address” for each network interface. The host creates the link-local address regardless of whether subsequent configuration of the interface is manual or automatic.

The link-local address combines the reserved prefix fe80::/10 with the interface MAC address and OS interface name (e.g. fe80::7985:c2df:fb11:62ec%em1).

Why append the interface name? Because all link local addresses share a common network prefix, even if they attach to different networks. Use of the appended interface name as a “zone index” lets the OS select the correct interface to use for outbound link-local traffic. (Note that Windows maintains separate interface indexes for IPv4 and IPv6.)

The link local address is only addressable on its particular LAN (it can’t be routed outside the broadcast domain). Routing tables use link local addresses for the “next hop” address.

ICMPv6

RFC 4443: Internet Control Message Protocol for the Internet Protocol Version 6

Fragmentation (ICMPv6)

Neighbor Discovery (ICMPv6)

RFC 4861: Neighbor Discovery for IP version 6

SLAAC (ICMPv6)

The alternatives to SLACC, where stateless configuration is inadequate for the application, are DHCPv6 or manual static configuration.

SLAAC requires a prefix length of /64. (Is this still true?)

RFC 2462: IPv6 Stateless Address Autoconfiguration

Duplicate Address Detection (ICMPv6)

A node performs duplicate address detection for most local addresses (but not anycast and loopback addresses).

When starting an interface, a node joins the interface to the link-local All-Nodes multicast group (FF02::1).

When configuring an address for the interface:

  1. The node constructs an address combining the reserved Solicited-Node prefix (FF02::1:FF00:0000/104) with the last twenty-four bits of the tentative unicast address, and joins the Solicited-Node multicast group.
  2. The node sends a Neighbor Solicitation for its tentative address to the Solicited-Node multicast address.
  3. If the node receives a Neighbor Solicitation with its own tentative address as the target (or a Neighbor Advertisement with its own tentative address as the source) it knows the address is not unique on the LAN.

[************ DAD doesn’t seem too clear. Research more. ***************]

Privacy

Because SLAAC builds an address from invariable identifiers (e.g. the interface MAC), the address effectively tags the node’s traffic with a privacy-compromising unique permanent identifier. RFC 4941 proposes a method to vary global-scope SLAAC addresses over time and include a random element in their generation, while keeping these temporary addresses globally unique.

Addresses have a limited life:

Inspecting an interface configured like this shows several addresses, most marked “deprecated” but still attached to the interface.

Windows and MacOS enable these privacy extensions by default; some linux distributions do.

RFC 4941: Privacy Extensions for Stateless Address Autoconfiguration in IPv6

DHCPv6

IPv6 implements DHCP in one of two ways.

The second scenario is more common.

Sites with a small number of machines attached to a single link may not even require a DHCPv6 server. The one remaining role for DHCP in such an environment is informing clients about DNS servers. A proposed standard (RFC 6106) would provide DNS information over NDP in Router Advertisements, but it has not been universally adopted yet.

RFC 3315: Dynamic Host Configuration Protocol for IPv6

How to Shorten/Abbreviate an IPv6 Address

128-bit IPv6 addresses are cumbersome for humans to write, but we can abbreviate them using two rules.

First, omit leading zeros in each 16-bit block:

2001:0db8:0000:000d:0000:0000:0000:003c
     ^    ^^^  ^^   ^^^  ^^^  ^^^  ^^

This pproduces the shortened address:

2001:db8:0:d:0:0:0:3c

Second, elide consecutive fields of zeros using a double-colon, so that:

2001:db8:0:d:0:0:0:3c

…becomes:

2001:db8:0:d::3c

Only elide a single set of consecutive zero fields! (With two or more sets of “::” we couldn’t tell how may fields each “::” hides.)

Using both rules, the loopback address, “0000:0000:0000:0000:0000:0000:0000:0001”, shortens to ::1.

Literal IPv6 addresses in URL’s and URI’s

Since colons are not valid in URL’s (confusion with port number), enclose literal IPv6 addresses in square brackets:

https://[2001:db8::100]:8080/example/

DNS

DDNS updates a DNS server with records for clients with dynamic addresses. In some configurations, the clients directly update the DNS server. In other configurations, the DHCP server updates the DNS server after clients get addresses via DHCP. SLAAC breaks the later configuration. Furthermore, SLAAC privacy extensions complicate DNS record TTLs. Of course, for a node to update DNS it must somehow discover the DNS server (DHCPv6 or RA). RFC 4472 discusses the issue.

RFC 3596: DNS Extensions to Support IP Version 6

RFC 4472: Operational Considerations and Issues with IPv6 DNS

Jumbograms

IPv4 limits packets to 65,535 (2^16−1) octets of payload. An IPv6 node can optionally handle “jumbogram” packets as large as 4,294,967,295 (2^32−1) octets. Every hop in the path must support jumbograms.

Simplified Routing

IPv6 shift many routing duties to endpoints.

IPv6 routers don’t fragment packets; IPv6 expects hosts to do end-to-end MTU path discovery themselves, and size their packets accordingly or do their own fragmentation.

IPv6 doesn’t do checksumming. It assumes lower or higher-level layers do error detection and correction (e.g. TCP). Although IPv4 doesn’t require UDP to do checksumming, IPv6 does. Therefore, IPv6 routers don’t need to recalculate header checksums when the packet TTL changes, for example. (IPv6 renames IPv4’s “TTL” field to “Hop Limit”, reflecting the fact that routers are no longer expected to compute the time a packet spends in a queue.)

What’s the smallest network block we can advertise?

With IPv4, the smallest block is /24. Anything smaller than /24, and we can’t count on our route being propagated across the internet.

It’s pointless to advertise anything smaller than a /64, since a /64 can’t be subdivided. Can we advertise a /64 with any confidence it will propagate?

Maybe. A /64 may be advertised by BGP, but a /48 is likely.

If we’re anything except the tiniest and least ambitious of end users, it’s better to requests a /48. Almost everyone will carry a /48 announcement over BGP. However, as of 2018, what sizes get filtered is still somewhat in flux. The larger your network block size, the more likely you are to be globally reachable.

CIDR Possible /64 Subnets
64 1
63 2
62 4
61 8
60 16
59 32
58 64
57 128
56 256
55 512
54 1,024
53 2,048
52 4,096
51 8,192
50 16,384
49 32,768
48 65,536

/48 and smaller are end-user allocations. LIR’s (local internet registries, like ISP’s and large organizations) are allocated something between a /47 and a /33. /32 to /24 are assigned to large ISP’s and very large organizations. /23 and larger are assigned to RIR’s (regional internet registries, like ARIN and APNIC) and truly elephantine ISP’s and orgs.

ISP’s have been encouraged to hand out /48 blocks to customers, but in practice they’ve been more stingy. Assignments are intended to be made according to the guidelines in RFC3177 (RIRs-on-48):

If we’re multi-homed, we can request a /48 (or larger) assignment directly from ARIN.

IPsec

IPsec was conceived as part of IPv6 and later adapted for IPv4. It works the same.

RFC 4301: Security Architecture for the Internet Protocol

SeND

NDP and SLAAC are vulnerable to various abuses and spoofing. RFC 3971 proposes Secure Neighbor Discovery (SeND), which attaches RSA public key signatures to NDP messages. SeND is not universally supported. SeND itself suffers from denial-of-service and privacy concerns.

RFC 3971: SEcure Neighbor Discovery

Translation and Tunneling

Several options help IPv6 coexist with IPv4.

The first option is to run “dual stack”, where an IPv6 network exists parallel to but separate from the IPv4 network. Each network device has both an IPv4 and an IPv6 address.

The second option is “tunneling”, where IPv6 traffic is tunneled over an IPv4 network. Various tunneling methods exist, some point-to-point, like GRE, and others point-to-multipoint, like 6to4.

The third option is “translation”, where a router at the boundary between an IPv4 and an IPv6 network translates between them, mapping one type of IP address to the other. This is conceptually similar to IPv4 NAT. With translation, IPv4-only devices can talk to IPv6-only devices and vice versa. The most common translation technologies are NAT64 with DNS64.

Special Addresses (not an exhaustive list)

Unicast:

Unique local addresses (ULAs) are intended for local communication. These addresses compare roughly with IPv4 private addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), but don’t need NAT. They route only within a set of cooperating sites, not on the public internet. Despite routing only locally, the idea is for ULAs to be globally unique. The block is split into two halves, the upper half (fd00::/8) is used for “probabilistically unique” addresses in which a 40-bit pseudorandom number is used to obtain a /48 allocation. This means that there is only a small chance that two sites that wish to merge or communicate with each other will have conflicting addresses. Again, ULAs route only locally but are globally unique. We could merge LAN’s from two different organizations in the event of a merger, or tunnel between two cooperating organization, with little fear of conflicting addresses due to the unique upper bits. No allocation method for the lower half of the block (fc00::/8) is currently defined. In practice, this leaves the fd00::/8 prefix available for local addressing.

The ULA prefix should be globally unique. RFC 4193 specifies methods for unique generation, but this calculator automates it: https://www.sixxs.net/tools/grh/ula/

RFC 4193: Unique Local IPv6 Unicast Addresses

RFC 6879: IPv6 Enterprise Network Renumbering Scenarios, Considerations, and Methods

0100::/64 This prefix is used for discarding traffic.

Multicast:

Multihoming: An IPv6 Bugaboo

A common configuration for SMB’s is a LAN behind a gateway that connects to two different ISP’s, each with their own address space. Such multihomed configurations create problems for an IPv6 network hoping to avoid NAT.

Under IPv4, such a gateway does NAT for clients on the LAN. The clients occupy a private IPv4 address space, and (ideally) need not concern themselves with which ISP connection is active or preferred.

IPv6 naturally wishes to preserve its advantage of eliminating the complications of NAT through end-to-end transparency. Unfortunately, as of 2017, IPv6 does not offer a good NAT-free solution for multihomed gateways.

RFC 7157 spells out the current difficulties of hosts on a LAN with multiple addresses from multiple ISP’s:

RFC 7157 describes the issues very clearly. It points to a number of possible future solutions, but none of them are widely viable as of 2017. Unfortunately, IPv6-to-IPv6 Network Prefix Translation (NPTv6) is the only currently available solution.

RFC 7157: IPv6 Multihoming without Network Address Translation

NPTv6

NPTv6 translates between an “outside” IPv6 network prefix and an “inside” IPv6 network prefix. It does not touch the host part of the address (so the inside and outside networks must use the same prefix size). NPTv6 is stateless, 1:1 address mapping that does no port translation, and preserves end-to-end reachability.

Make sure the “inside” and “outside” network prefix is the same size for NPT.

RFC 6296: IPv6-to-IPv6 Network Prefix Translation

Playing with IPv6

What are some of the other IPv6 hosts on our LAN?

$ ping6 -c3 -w3 -I eth0 ff02::1
$ ip -6 neigh
$ ping6 -c3 fe80::215:65ff:fe9b:c802%eth0

Watch the ICMPv6 traffic hitting our interface:

# tcpdump -i em0 'icmp6'

Linux

Accept some IPv6 traffic using iptables:

# ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
# ip6tables -A INPUT -i lo -j ACCEPT

Activate SLAAC privacy extensions for an interface in /etc/network/interfaces:

iface eth0 inet6 auto
	privext 2

Set privacy as the system default in /etc/sysctl.conf:

net.ipv6.conf.all.use_tempaddr=2
net.ipv6.conf.default.use_tempaddr=2

Or, using NetworkManager:

$ nmcli conn show
$ nmcli conn show "Wired connection 1"
# nmcli conn mod "Wired connection 1" ipv6.ip6-privacy 2

BSD

With Comcast, pull the IPv6 address for the external interface by DHCPv6 rather than router advertisements. Assume the external interfaces is “em0”.

Remember to allow DHCPv6 through the firewall (and that DHCPv6 uses different port than DHCPv4!).

$ sudo pkg install dhcpcd

Add to /etc/pf.conf:

ifconfig_em0_ipv6="inet6 accept_rtadv"
rtsold_enable="YES"
ipv6_gateway_enable="YES"
dhcpcd_enable="YES"  
dhcpcd_interfaces="em0"

Edit /usr/local/etc/dhcpcd.conf:

controlgroup wheel
ipv6only 
allowinterfaces em0
duid
persistent
option rapid_commit
option classless_static_routes
option interface_mtu
require dhcp_server_identifier
slaac private


$ sudo service dhcpcd start

Hmm. Dhcpcd doesn’t seem to work. Not with Comcast, anhow. [EDIT: the above might have worked, but I was firewalling off DHCPv6 responses. Hmph.] Dhcp6c?

dhcp6c pfSense /var/etc/dhcp6c_opt2.conf

# pkg install dhcp6
# cp /usr/local/etc/dhcp6c.conf.sample /usr/local/etc/dhcp6c.conf

Edit /usr/local/etc/dhcp6c.conf:

# dhcp6c.conf
# "em0" is our outside interface.
# "na" is short for "network address" --- what we request for use on our outside interface.
# "pd" is short for "prefix delegation" --- what we request for use by our internal LAN.
interface em0 {
	send ia-na 0;
	send ia-pd 0;
	send rapid-commit;
};
id-assoc pd 0 {
	prefix-interface em1 {
		sla-id 0;
	};
	prefix-interface wlan0 {
		sla-id 1;
	};
};
id-assoc na 0 {
};

Add to /etc/rc.conf:

dhcp6c_enable="YES"
dhcp6c_interfaces="em0"

References