Recommendations

Segments

Unless there is only one client, networks need to be segmented into multiple subnets on different VLANs. Different classes of nodes require different services from the network. Separating them makes it easier to meet those requirements.

Use separate VLANs for (non exhaustive list):

  • Printers

  • IoT devices

  • VoIP phones

  • Servers, VMs, Containers

  • Wi-Fi controllers and access points

  • Laptops and Workstations

  • Temporary devices / Guests

  • Experiments

Hint

Segments and Autoconfiguration

Do not mix statically addressed and autoconfigured nodes in the same subnet.

Laptops and Workstations typically are configured using router advertisements and/or DHCP while static addresses should be assigned to servers. Keeping dynamic and static clients in separate subnets prevents potential address collision without additional configuration overhead. It also allows for servers to deactivate DAD (duplicate address detection).

Hint

Dual stacking only when needed

Printers placed in a separate subnet are easier to isolate from the internet (if necessary). In some situations, IPv4 might not be needed at all for a printer subnet, hence such a network segment can be operated using IPv6 exclusively. Same goes for other internal-only services (e.g., media server).

Networks and Routes

Subnets

An IPv6 prefix with a size of /60 can be divided into 16 /64 subnets, a prefix with the size of /56 has space for 256 subnets and a /48 prefix holds 65536 subnets. This guide is going to use 2001:db8:1020:ff00::/56 as the block used to allocate subnets from. Note, the IPv6 address range is assigned by the upstream provider. It cannot be chosen freely.

If IPv4 is still a thing when you read this guide, choose an IPv4 block from RFC 1918 big enough to be split into several /24 networks. It is best to avoid blocks which include ranges used broadly in factory defaults like 192.168.0.0/24, 192.168.1.0/24 and 10.0.0.0/24. Instead opt for lesser used IPs. This guide is going to use 10.20.0.0/16 as the block used to allocate subnets from.

Hint

VLAN id == subnet id

When creating new network segments, choose the VLAN id to be identical to the subnet id. E.g. for a new network segment with VLAN id 8 allocate 2001:db8:1020:ff08::/64 for the IPv6 range and 10.20.8.0/24 for IPv4. For a new network segment with VLAN id 33 (hex: 0x21) allocate 2001:db8:1020:ff21::/64 for the IPv6 range and 10.20.33.0/24 for IPv4. Note: If the IPv6 prefix is a /48, then it is also possible to use the VLAN id in decimal notation for the IPv6 subnet.

Default Gateway

IPv6 routers advertise their link-local address and not a globally routable one (see RFC 4861 section 6.1.2). Hence, the default gateway on connected nodes is supposed to point to a link local address (i.e., an address within fe80::/64). Usually, IPv6 link-local addresses are derived automatically from the MAC address of the network interface. However, using generated addresses is not very practical in server subnets where hosts are configured statically. Therefore it is advisable to manually configure the link-local address for every subnet on routers.

Hint

Use fe80::1/64

Fortunately link-local addresses are link-local. Therefore, it is perfectly valid to use the same address (i.e., fe80::1/64) on every interface of a router (see: Blog post: fe80::1 is a Perfectly Valid IPv6 Default Gateway Address)

Names

Most people cannot be bothered to remember IPv4 addresses. IPv6 does not make things any easier.

DNS Hosting

DNS zones need to be hosted somewhere. SOHO routers typically provide point and click interfaces where DNS entries can be added to some internal DNS server which typically doubles as recursive DNS resolver. In order for this to work, the address of that internal DNS server needs to be configured (maunally or via autoconfiguration) on all nodes who wish to resolve those entries.

This configuration is known as split-horizon DNS. And it falls short if people start to use validating resolvers (DNSSEC) and alternative DNS resolvers, sometimes over encrypted protocols (DoT, DoH).

Hint

Place RRs in public DNS

Avoid deploying private DNS zones and split-horizon DNS. Instead place all resource records into public DNS.

Node Names

Every node which provides any type of service should have a name. This includes routers, servers, VMs, containers, printers, WiFi access points etc. A popular choice is to just add AAAA records to the domain name of the family website or the primary domain of a business.

While convenient in the beginning, this can pose problems down the road. The website might be managed by contractors while the network stays inhouse or vice-versa. Node records might be managed by an orchestrator while access to the DNS zone of the main website needs to be restricted due to policy reasons. Maintaining separate DNS zones for different purposes also simplifies gradual rollouts, e.g. of DNSSEC.

Hint

Use a dedicated domain for nodes

Thus it is recommended to register and maintain a dedicated domain and only add AAAA records for network nodes there. Additional records like SSHFP could be added as well, this will simplify node administration greatly.

Nodes need to be replaced over time. In order to simplify this process, old names should not be reused for new nodes. Instead each node keeps its name over its whole lifespan in a network. Holding on to this practice simplifies the development of a network since old and new equipment can be operated in parallel for some time.

Service Names

Every service should have a name. This includes webapps, file sharing, directory services, etc. A popular choice is to just use the node name where the service happens to be hosted.

Services need to keep their name, otherwise people are forced to update bookmarks and printer queues. It follows that reusing node names for services will pose problems in the long run when nodes need to be replaced.

In addition, services might be composed from several applications running on different nodes, VMs or containers. The service name is then simply pointing towards the node hosting the frontend server for TLS termination, reverse proxying and/or load balancing.

Hint

Use a dedicated domain for services

Thus it is recommended to register and maintain a dedicated domain for internal services. Either add AAAA records containing IPs of the nodes hosting a service or add CNAME pointing towards the node names.

Caution

Service enumeration via CT logs

TLS certificates issued by trusted certificate authorities are recorded in public certificate transparency logs (e.g. crt.sh). Organisations which are reusing subdomains of their main website or brand name for internal systems secured by TLS certificates might unknowingly expose this information to the public.

Using a dedicated domain name for internal services unrelated to the main website, name or brand of an organisation and deploying wildcard TLS certificate can reduce the risk of service enumeration via certificate transparency logs.

Addressing

Nodes providing services to connected clients need a fixed IP address. IPv6 addresses assigned automatically via SLAAC do not change over time. Thus, such IPs are quite suitable as a stable identifier for a given node connected to a specific network.

However, SLAAC can be problematic when used with servers and VMs. Some operating systems will not wait for autoconfiguration to complete and some server software will either fail to start or even fall back to the loopback interface to listen on when the primary interface is not ready early enough upon startup. Due to those potential race conditions it is recommended to use static IP configuration on servers.

Hint

Maintain the SLAAC IP for printers in DNS

In order to be easily reachable from clients, the SLAAC IP of every printer should be recorded in the DNS zone for nodes and a separate record should be maintained in the DNS zone for services pointing to the respective node name.

Using SLAAC for printers spares administrators from the tedious exercise to input verbose IPv6 addresses via single button interfaces.

Hint

Use a predictable addressing scheme for servers

An IPv6 /64 subnet has room for 18446744073709551616 addresses. The wast size of those subnets opens the opportunity to discourage host discovery by network scans (there are many pitfalls though, see RFC 7707). In order to avoid clustering hosts around likely scanned ranges, one could use a cryptographic hash of the hostname as the basis for an IP address. Implementations of this method are available as an ansible filter (znerol/ipaddr_hash on galaxy.ansible.com) and as a JavaSrcipt isomorphic library (ipaddrhash on npmjs.com). For convenience, the fully functional example webapp can be found and used at znerol.github.io/ipaddrhash-js/