Safeguard
Supply Chain Security•

IPv6 Address Autoconfiguration Explained: SLAAC, DHCPv6 and Privacy

IPv6 hosts build addresses from router advertisements (SLAAC) or lease them via DHCPv6. How M and O flags, privacy addresses and RA Guard work.

Safeguard Security Team
45 min read

An IPv6 host gets its address in one of two ways. With SLAAC (stateless address autoconfiguration, RFC 4862) it listens for a router advertisement, takes the advertised 64 bit prefix and builds the rest of the address itself. With stateful DHCPv6 (now RFC 9915) a server leases it an address. Many hosts also add short lived random "privacy" addresses (RFC 8981) for outgoing connections, and the router advertisement's M and O flags tell the host which of these mechanisms the network expects it to use.

Autoconfiguration decides whether a device can be tracked across networks by its address, whether you can tell which device used which address yesterday, and how easily one rogue machine on a LAN can redirect everyone's traffic. This post goes one level deeper than our IPv4 vs IPv6 explainer and our post on ARP and IPv6 Neighbor Discovery. If you want the IPv4 side of the same story, read DHCP explained first.

Key takeaways

  • An IPv6 interface first forms a link-local address, checks it with Duplicate Address Detection, then solicits a Router Advertisement (RA). If a prefix in the RA has the A (autonomous) flag set, the host builds its own address in it. That is SLAAC.
  • The RA's M flag says "addresses are available from DHCPv6"; the O flag says "other configuration, such as DNS, is available from DHCPv6". The default router always comes from RAs, never from DHCPv6.
  • The old modified EUI-64 method put the MAC address inside the IPv6 address, so a laptop was trackable across every network it joined. RFC 8064 (2017) says hosts should not do that by default and recommends RFC 7217 stable opaque identifiers instead.
  • RFC 7217 addresses are stable on one network but different on every network. RFC 8981 temporary addresses change about once a day by default and are commonly used for outgoing connections.
  • RFC 9915 (January 2026, Internet Standard STD 102) replaced RFC 8415 as the DHCPv6 specification. It retires temporary address leases (IA_TA) and the server unicast option.
  • DNS servers can arrive in the RA itself (RDNSS, RFC 8106) or from DHCPv6. RFC 8106 says that when both are present, DHCPv6 information should take precedence, but real operating systems do not all follow that, so send the same servers by both routes or use only one.
  • Anyone on the link can send an RA or answer as a DHCPv6 server. RA Guard (RFC 6105, hardened by RFC 7113) and DHCPv6-Shield (RFC 7610) filter those messages at the switch port.

How an IPv6 host gets an address, step by step

Step 1: the link-local address

The first thing an IPv6 interface does is form a link-local address. RFC 4291, the IPv6 addressing architecture, reserves fe80::/10 for link-local unicast and, in practice, hosts use fe80::/64 plus a 64 bit interface identifier (IID). Link-local addresses are never routed beyond the link; Neighbor Discovery itself runs over them.

RFC 4862 then requires the host to check that the address is unique before using it. This is Duplicate Address Detection (DAD). The host joins the solicited-node multicast group for the address and sends a Neighbor Solicitation asking "who has this address?" from the unspecified address ::. If nobody answers within the retransmit timer, the address moves from "tentative" to usable. The number of probes is the DupAddrDetectTransmits variable; on Linux the dad_transmits sysctl defaults to 1.

Step 2: Router Solicitation and Router Advertisement

Routers send unsolicited Router Advertisements periodically to the all-nodes multicast address ff02::1. A host that has just come up does not want to wait for the next one, so it sends a Router Solicitation to the all-routers group ff02::2. Linux sends up to three by default (router_solicitations = 3) before it assumes no router is present.

An RA, defined in RFC 4861 section 4.2, carries:

Field or optionWhat it tells the host
Cur Hop LimitThe default hop limit for outgoing packets
M flag"Managed address configuration": addresses are available via DHCPv6
O flag"Other configuration": other information, such as DNS, is available via DHCPv6
Router LifetimeHow long, in seconds, this router may be used as a default router; 0 means "do not use me as a default router"
MTU optionThe link MTU
Prefix Information Option (PIO)A prefix, its length, valid and preferred lifetimes, and the L (on-link) and A (autonomous) flags
RDNSS and DNSSL optionsRecursive DNS servers and search domains (RFC 8106)

RFC 4861 also requires every Neighbor Discovery message, RAs included, to arrive with an IP hop limit of 255. Any router in the path would have decremented it, so 255 proves the packet came from the same link. That stops RAs injected from the internet, but not from a machine on the same LAN.

Step 3: prefix information and the A and L flags

Each Prefix Information Option has two flags that matter here. The L flag says the prefix is on-link, so the host can reach other addresses in it directly without the router. The A flag says the prefix can be used for autonomous address configuration. If A is set and the prefix is 64 bits long, the host appends a 64 bit interface identifier and has a global address. That is SLAAC in one sentence.

The PIO also carries two lifetimes. The preferred lifetime says how long the address should be used for new connections. The valid lifetime says how long the address may exist at all. Between the two, the address is "deprecated": existing connections keep working but new ones should pick another address. That is how IPv6 renumbers gracefully: advertise the old prefix with a preferred lifetime of zero and the new one alongside it.

RFC 4862 section 5.5.3 adds a defence that is easy to miss. When an RA changes the valid lifetime of an address that was created by SLAAC, the host accepts the new value directly only if it is greater than two hours or greater than the time the address has left. If the address has two hours or less left, the host ignores the change unless the RA was authenticated (for example with SEND). In every other case it resets the valid lifetime to two hours. Without that rule, a single forged RA with a valid lifetime of zero could make every host on the link drop its address instantly. The Linux kernel exposes a switch, ra_honor_pio_life, that makes it trust the PIO valid lifetime instead; it is off by default.

Step 4: the M and O flags decide whether DHCPv6 joins in

The M and O flags are hints, not commands. RFC 4861 defines them like this:

  • M (Managed) set: addresses are available via DHCPv6. RFC 4861 notes that if M is set, O is redundant because DHCPv6 will return all available configuration.
  • O (Other) set, M clear: no addresses from DHCPv6, but other information such as DNS is available. The host does "stateless DHCPv6", sending an Information-request.
  • Neither set: nothing is available via DHCPv6. Everything the host needs comes from the RA.

The flags and the A flag in the prefix are independent. A network can set M and also leave A set on its prefix, in which case a host forms a SLAAC address and also requests a DHCPv6 lease, and ends up with both. A network that wants only DHCPv6 addresses must set M and clear A on the prefix. A network that wants only SLAAC sets A and leaves M clear.

RA settingsWhat a typical host doesTypical use
A=1, M=0, O=0SLAAC address; DNS from RDNSS in the RASmall and home networks, client Wi-Fi
A=1, M=0, O=1SLAAC address; DNS and other options from stateless DHCPv6Networks that need DHCPv6 only for options such as NTP or SIP servers
A=1, M=1SLAAC address and, on hosts that support it, a DHCPv6 lease as wellTransitional networks, mixed estates
A=0, M=1DHCPv6 lease only, on hosts that support stateful DHCPv6; hosts that do not will have only a link-local addressManaged enterprise networks that want one logged address per host
PIO with P=1Hosts that understand RFC 9762 request their own prefix via DHCPv6 prefix delegationLarge shared networks (RFC 9663)

Step 5: the default route and the address selection rules

The default router comes from the RA's Router Lifetime, never from DHCPv6. There is no DHCPv6 option for a default gateway. That is a deliberate design decision, and it means that even a fully "managed" DHCPv6 network still depends on Router Advertisements being correct.

A host with several addresses picks the source address for each connection using the default address selection rules of RFC 6724, which allow an implementation to prefer temporary addresses for outgoing connections.

How SLAAC builds the interface identifier

The interface identifier is the low 64 bits of the address. How a host picks those bits has changed three times, and each change was driven by privacy.

Modified EUI-64: the original method

RFC 4291 Appendix A describes "modified EUI-64". The host takes its 48 bit MAC address, splits it in half, inserts the two bytes ff:fe in the middle, and flips the universal/local bit (the second lowest bit of the first byte).

A worked example with the MAC 00:1a:2b:3c:4d:5e:

  1. Split: 00:1a:2b and 3c:4d:5e.
  2. Insert ff:fe: 00:1a:2b:ff:fe:3c:4d:5e.
  3. Flip the universal/local bit of the first byte: 0x00 becomes 0x02.
  4. Interface identifier: 021a:2bff:fe3c:4d5e.
  5. With the prefix 2001:db8:1:2::/64, the SLAAC address is 2001:db8:1:2:21a:2bff:fe3c:4d5e.

The ff:fe in the middle is a giveaway. If an address has ff:fe in the middle of its last 64 bits, it was almost certainly built from a MAC address, and you can recover the MAC by reversing the steps.

Why EUI-64 addresses leaked the MAC address

The problem is that the interface identifier is identical on every network. A laptop that joins a home network, a coffee shop, an airport and an office network keeps the same low 64 bits everywhere. Any web server, mail server or tracker that logs IPv6 source addresses can link those visits together, even though the prefix changes. The MAC also reveals the network card's vendor, and it shrinks the search space for anyone scanning a network for one vendor's devices.

RFC 8064, published in February 2017, changed the default. It says nodes "SHOULD NOT employ IPv6 address generation schemes that embed a stable link-layer address in the IID" by default, and it lists the per-link-type specifications (Ethernet's RFC 2464 among them) that it recommends hosts no longer use for stable addresses. In their place, it recommends RFC 7217.

RFC 7217: stable, semantically opaque identifiers

RFC 7217, published in April 2014, keeps the useful property of EUI-64 (an address that stays the same on a given network, which is handy for logs, firewall rules and long lived connections) and drops the harmful one (the same identifier on every network). The host computes:

RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key)
  • F is a pseudorandom function that must not be computable from outside without the secret key. RFC 7217 gives SHA-1 and SHA-256 as two possible options and notes that MD5 is considered unacceptable.
  • Prefix is the advertised prefix, so the identifier is different on every network.
  • Net_Iface identifies the interface, for example its name or index.
  • Network_ID is optional extra input, such as the Wi-Fi SSID.
  • DAD_Counter starts at 0 and is incremented if DAD finds a collision, so the host can try again.
  • secret_key is generated once, typically at install time, and kept stable.

The result: the same laptop on the same office network always gets the same address, and on every other network it gets a different, unrelated one. There is nothing in the identifier that reveals the MAC address or links the two networks.

On Linux this is addr_gen_mode = 2 (use the secret in stable_secret) or addr_gen_mode = 3 (use a random secret if none is set). NetworkManager calls it ipv6.addr-gen-mode stable-privacy; its documentation notes that the eui64 mode keeps the host part constant, "making it possible to track the host's presence when it changes networks". In systemd-networkd, Token=prefixstable in the [IPv6AcceptRA] section selects the RFC 7217 algorithm; the systemd manual notes that it hashes both the interface name and the MAC address, so changing either changes the address. The kernel documentation's default for addr_gen_mode is still 0, EUI-64, so whether you get RFC 7217 depends on your distribution and network manager rather than the kernel alone.

What temporary (privacy) addresses are, and how they differ from stable opaque addresses

RFC 7217 solves cross-network tracking. It does not stop a server you visit every day from recognising you every day, because on the same network your stable address is, by design, stable. Temporary addresses deal with that.

RFC 8981 temporary addresses

The idea dates back to RFC 3041 (2001), revised as RFC 4941 (2007). The current version is RFC 8981, published in February 2021, which obsoletes RFC 4941. A host generates, for each SLAAC prefix, an additional address with a random interface identifier and short lifetimes, uses it for outgoing connections, and replaces it regularly.

RFC 8981's default parameters:

ParameterDefault in RFC 8981What it means
TEMP_VALID_LIFETIME2 daysHow long a temporary address can exist
TEMP_PREFERRED_LIFETIME1 dayHow long it is used for new connections
MAX_DESYNC_FACTOR0.4 times TEMP_PREFERRED_LIFETIMEUpper bound on a random value subtracted from the preferred lifetime so hosts do not all regenerate at the same moment
REGEN_ADVANCE2 + (TEMP_IDGEN_RETRIES x DupAddrDetectTransmits x RetransTimer / 1000) secondsHow long before deprecation a new address is generated

RFC 8981 says that with these defaults a host has at most three concurrent temporary addresses per prefix. Section 5 of the RFC lists what changed from RFC 4941, and the changes are worth knowing:

  • It fixed flaws in the old generation algorithm, including the use of MD5 and the reuse of the same identifier across several prefixes.
  • It allows hosts to use only temporary addresses. RFC 4941 assumed they were always configured alongside stable ones.
  • It removed RFC 4941's recommendation that temporary addresses be disabled by default, in line with BCP 188 (RFC 7258, pervasive monitoring) and BCP 204 (RFC 7934).
  • It reduced the default valid lifetime from one week to two days, reducing the typical number of concurrent temporary addresses from seven to three.

A worked example of the address lifecycle

Assume the RFC 8981 defaults and a DESYNC_FACTOR the host randomly picked as 3 hours (under the 9.6 hour upper bound).

  • Day 0, 09:00: the host joins the network and creates temporary address T1. Its preferred lifetime is 24 hours minus 3 hours, so 21 hours. Its valid lifetime is 48 hours.
  • Day 1, 06:00 minus REGEN_ADVANCE (a few seconds): the host creates T2 so that it is ready before T1 is deprecated.
  • Day 1, 06:00: T1 becomes deprecated. New connections use T2. Long lived connections on T1 continue.
  • Day 2, 09:00: T1's valid lifetime ends and it is removed. Any connection still using it breaks.
  • Around day 2, 03:00: T3 is created and T2 is deprecated, and so on. At any moment the host has its stable address, one preferred temporary address and one or two deprecated ones, the "at most three" in the RFC.

Platform defaults differ from the RFC

Operating systems tune these values. The Linux kernel documentation lists temp_valid_lft at 172800 seconds (2 days), temp_prefered_lft at 86400 seconds (1 day), max_desync_factor at 600 seconds (a fixed 10 minutes rather than 0.4 of the preferred lifetime) and regen_max_retry at 5. Its use_tempaddr default is 0 (disabled) for most devices, which distributions and network managers can override per connection.

On the Mac we used to write this post, sysctl net.inet6.ip6 reported use_tempaddr: 1, temppltime: 86400 and tempvltime: 604800: temporary addresses on, a one day preferred lifetime, and a seven day valid lifetime. That valid lifetime matches the old RFC 4941 value rather than RFC 8981's two days. Windows exposes the same knobs through Set-NetIPv6Protocol as UseTemporaryAddresses, MaxTemporaryValidLifetime, MaxTemporaryPreferredLifetime, TemporaryRegenerateTime and MaxTemporaryDesyncTime. Check your own systems with the commands later in this post rather than relying on any table, including ours.

Stable opaque vs temporary

An RFC 7217 address stops you being the same device on every network; a temporary address stops you being the same device every day on one network. A host typically has both: the stable one for incoming connections and firewall rules, the temporary one for outgoing traffic. Neither hides you from the network you are on, because the router still sees your MAC next to every address you use. That is how operators keep traceability with SLAAC.

How DHCPv6 works: stateful, stateless and prefix delegation

DHCPv6 was first standardised in RFC 3315 (2003). RFC 8415 (November 2018) consolidated it with prefix delegation (RFC 3633), stateless DHCPv6 (RFC 3736) and several other documents. In January 2026 the IETF published RFC 9915, which obsoletes RFC 8415 and raised DHCPv6 to Internet Standard (STD 102). RFC 9915 incorporates verified errata and obsoletes two features: temporary address assignment (the IA_TA option) and server unicast (the Server Unicast option and UseMulticast status code). If you have tooling or documentation that cites RFC 8415, it still describes the protocol accurately apart from those changes.

The basics

  • Clients listen on UDP port 546; servers and relay agents on UDP port 547.
  • A client sends to the link-scoped multicast group ff02::1:2 (All_DHCP_Relay_Agents_and_Servers) from its link-local address. Relays forward messages to servers elsewhere using Relay-forward and Relay-reply messages.
  • Clients and servers identify themselves with a DUID (DHCP Unique Identifier), not a MAC address. A DUID is often derived from a MAC and stored, so the same one can follow a device across networks; RFC 7844 (anonymity profiles for DHCP clients) addresses that tracking concern.
  • Addresses and prefixes live inside Identity Associations: IA_NA for normal addresses, IA_PD for delegated prefixes. Each IA has T1 and T2 timers for renewing and rebinding.

Stateful DHCPv6 (address assignment)

The normal exchange has four messages:

  1. Solicit: the client asks for servers, listing the IAs it wants.
  2. Advertise: each server that can help replies with what it would offer.
  3. Request: the client picks a server and asks for the offered address.
  4. Reply: the server commits the lease.

Rapid Commit shortens this to Solicit and Reply. Afterwards the client sends Renew at T1, Rebind at T2, Release when done, Decline if DAD finds the address in use and Confirm after it may have moved links.

The address comes with a /128 prefix length. DHCPv6 does not say which prefix is on-link and does not provide a default route: both come from the RA. A stateful DHCPv6 client on a network with no RAs has an address but no route to use it with.

Stateless DHCPv6

When the RA has O set and M clear, the host does not want an address from DHCPv6, only options. It sends an Information-request and gets a Reply with options such as DNS servers (option 23), the domain search list (option 24), NTP servers and others. No lease is kept, so the server holds no state about the client.

Prefix delegation

Prefix delegation (IA_PD) is how a router gets a whole prefix, rather than one address, from an upstream router. It is a common way for home routers on IPv6 broadband to get their LAN prefixes: the customer edge router asks the provider's DHCPv6 server for, say, a /56, receives it, and carves /64s out of it for each LAN and Wi-Fi network it serves.

Two recent documents extend prefix delegation to ordinary hosts. RFC 9663 (October 2024, Informational) describes giving each client on a large shared network its own /64 by DHCPv6-PD, so that a phone or laptop can use as many addresses as it needs from its own prefix. RFC 9762 (June 2025) adds a P flag to the Prefix Information Option to say "this network prefers that you ask for a prefix by DHCPv6-PD". It updates RFC 4862 so that a host that understands the P flag ignores the A flag in the same PIO. The Linux kernel already has a ra_honor_pio_pflag sysctl, off by default, meant to be enabled when a userspace DHCPv6-PD client is running.

Why Android does not support stateful DHCPv6

Android's DHCPv6 client does not do address assignment. The client in the Android network stack source (Dhcp6Client.java in the NetworkStack module) states in its own comment that it supports only IA_PD (prefix delegation) "not for IA_NA/IA_TA yet". On an IPv6 network that sets M and clears A on its prefix, an Android device therefore has no way to obtain a global IPv6 address from that network and is left with its link-local address, and with IPv4 if the network offers it. The public reasoning behind that design is set out in RFC 7934, "Host Address Availability Recommendations" (BCP 204, July 2016), written by authors from Google and Apple. It recommends that networks give general purpose hosts multiple global addresses when they attach, and that they not limit a host to a single IPv6 address, because uses such as tethering and 464XLAT translation need more than one. It notes that most DHCPv6 clients only ask for one non-temporary address, and that handing out a fixed batch by stateful assignment "sets a limit on the number of addresses" available and so limits future applications.

RFC 9663 and RFC 9762 give operators who want per-device accountability, the main reason to run stateful DHCPv6, a way to get it with a delegated prefix instead of a single address. For networks that serve phones, the practical answer today is SLAAC plus RDNSS for DNS, with traceability from the router's neighbour table, or per-client prefix delegation where your equipment supports it.

How DNS settings reach IPv6 clients

A host needs a recursive DNS server before an address is much use. IPv6 has two ways to deliver one.

RDNSS and DNSSL in the router advertisement

RFC 8106 (March 2017, which obsoleted RFC 6106) defines two RA options:

  • RDNSS (Recursive DNS Server): one or more IPv6 addresses of DNS resolvers, with a lifetime.
  • DNSSL (DNS Search List): domain suffixes for short name lookups, with a lifetime.

RFC 8106 says the lifetime of each should by default be at least three times MaxRtrAdvInterval, so a host does not lose its resolver because one RA was dropped. A lifetime of zero tells the host to remove that resolver immediately. The options have their own lifetimes, so RDNSS entries are not dropped just because the router lifetime expires.

The advantage of RDNSS is that a host can get everything it needs from a single RA, with no DHCPv6 server at all. RFC 8106 says hosts that conform to it MUST extract DNS information from RAs unless the user has configured DNS statically. For small networks, and for devices whose DHCPv6 client does not request addresses or DNS, RDNSS is often the only route DNS servers can take.

DNS options from DHCPv6

The same information is available from DHCPv6 option 23 (DNS recursive name server) and option 24 (domain search list), both defined in RFC 3646, either in a stateful lease or in stateless Information-request replies. RFC 8106 notes that the RA options and the DHCPv6 options can be used together.

When both disagree

RFC 8106 section 5.3.1 gives a rule. A host SHOULD keep DNS options from all sources, and RFC 8106 recommends room for at least three resolver addresses across them. Options from DHCP SHOULD be stored first, so that DHCPv6 information takes precedence over RA information for queries. There is one exception: RAs protected with SEND MUST be preferred over RAs without it and over unauthenticated DHCP. On a network without SEND, the practical reading is "DHCPv6 first, then RDNSS".

Implementations do not all behave that way. The exact number of entries kept is, in the RFC's words, a matter of local policy, and resolver software differs in how it orders servers from different sources and different interfaces. Some systems keep separate per-interface resolver lists and pick based on routing or scoped queries, so a resolver learned on one interface may never be asked about names on another.

On Linux with systemd-resolved, resolvectl dns shows the servers configured on each link. On macOS, scutil --dns shows each resolver configuration. On Windows, Get-DnsClientServerAddress -AddressFamily IPv6 lists them.

The operational rule: send the same DNS servers by both mechanisms, or use only one. Disagreeing sources cause support tickets, and an unfiltered rogue RA or DHCPv6 server can add a resolver of the attacker's choosing.

What attacks target autoconfiguration

Autoconfiguration assumes that whoever sends RAs and DHCPv6 replies on the local link is trustworthy. RFC 6105 calls Secure Neighbor Discovery (SEND, RFC 3971) the canonical solution, and offers RA Guard as a lighter alternative because complete SEND support on every device cannot be assumed. On a network without SEND, nothing authenticates these messages. NIST SP 800-119, "Guidelines for the Secure Deployment of IPv6", covers the same threats for agencies planning deployments.

This section describes the attack classes conceptually so you can recognise and defend against them. It does not give instructions.

Rogue router advertisements

Any device on a LAN can send an RA. Sometimes it is an accident: a laptop with internet connection sharing enabled, a misconfigured virtual machine host, a home router plugged in backwards on an office network. Sometimes it is deliberate. The effects:

  • Traffic interception. A rogue RA with a non-zero router lifetime can make hosts use the sender as their default IPv6 router. Because hosts generally prefer IPv6 when it works, this can capture traffic even on a network that never meant to run IPv6.
  • DNS hijacking. An RA carrying an RDNSS option can point hosts at a resolver the attacker controls.
  • Denial of service. RAs that advertise bogus prefixes, set a zero router lifetime for the real router, or flood the link with thousands of different prefixes can disrupt connectivity or exhaust host resources. Linux limits autoconfigured addresses per interface with max_addresses, default 16, for this reason; the kernel documentation warns that setting it to zero or very high makes it easy to crash the kernel.

The "IPv4 only" network is a frequent victim: if its switches do not filter RAs, its hosts still run IPv6 and will accept one.

Rogue and spoofed DHCPv6 servers

Any device can also answer a DHCPv6 Solicit or Information-request. A rogue server can hand out DNS servers, domain search lists and, where clients accept stateful leases, addresses. Because the default route always comes from RAs, a rogue DHCPv6 server alone cannot redirect traffic, but DNS control is often enough to do damage. A rogue RA that sets the O or M flag can also steer hosts toward a rogue DHCPv6 server, which is why both need filtering.

Neighbor Discovery abuse and tracking

A host that answers every DAD probe can stop new hosts from configuring any address, and neighbour cache poisoning is the IPv6 version of ARP spoofing; both are covered in our Neighbor Discovery post. Passive tracking through EUI-64 identifiers is the other class of attack, and RFC 7217 and RFC 8981 are its defences.

The timeline of standards and fixes

DateDocumentWhat changed
Jan 2001RFC 3041First privacy extensions for SLAAC
Jul 2003RFC 3315First DHCPv6 specification
Mar 2005RFC 3971SEcure Neighbor Discovery (SEND)
Feb 2006RFC 4291Current IPv6 addressing architecture, including modified EUI-64
Sep 2007RFC 4861, RFC 4862, RFC 4941Current Neighbor Discovery and SLAAC; revised privacy extensions
Dec 2010NIST SP 800-119Guidelines for secure deployment of IPv6
Feb 2011RFC 6105RA Guard
Aug 2013RFC 6980Fragmented Neighbor Discovery messages forbidden
Feb 2014RFC 7113RA Guard evasion via extension headers and fragmentation fixed
Apr 2014RFC 7217Stable, semantically opaque interface identifiers
Aug 2015RFC 7610DHCPv6-Shield
May 2016RFC 7844Anonymity profiles for DHCP clients
Jul 2016RFC 7934 (BCP 204)Host address availability recommendations
Feb 2017RFC 8064Stable IIDs should not embed MAC addresses; RFC 7217 recommended
Mar 2017RFC 8106Current RDNSS and DNSSL options
Nov 2018RFC 8415Consolidated DHCPv6
Feb 2021RFC 8981Current temporary address specification; two day default lifetime
Oct 2024RFC 9663DHCPv6 prefix delegation per client
Jun 2025RFC 9762P flag in the Prefix Information Option
Jan 2026RFC 9915DHCPv6 becomes Internet Standard STD 102; IA_TA and server unicast obsoleted

What RA Guard and DHCPv6-Shield do

RA Guard (RFC 6105)

RA Guard, published in February 2011, is a switch feature. The switch decides, per port, whether Router Advertisements arriving on that port are allowed through. RFC 6105 describes two forms:

  • Stateless RA Guard examines each RA on its own and compares it against configuration: which ports may have routers attached, which source MAC and IPv6 addresses are allowed, which prefixes may be advertised.
  • Stateful RA Guard learns. During a learning period it watches which ports legitimately carry RAs, then blocks the rest. It can also use SEND to validate RAs, where SEND is deployed.

The simple, common deployment: mark the uplink ports to real routers as "router" ports and every access port as "host", so that RAs from access ports are dropped.

Why RA Guard needed RFC 7113

Early RA Guard implementations looked for the ICMPv6 header right after the fixed IPv6 header. RFC 7113 (February 2014) documented that some implementations could be evaded by inserting IPv6 extension headers before the ICMPv6 header, or by fragmenting the packet so that the ICMPv6 header was in the second fragment. The switch saw no RA and forwarded the packet; the host reassembled it and processed the RA.

RFC 7113 updated RFC 6105. Among its requirements: RA Guard must parse the entire IPv6 header chain to find the upper layer header. If a packet is a first fragment and does not contain the entire header chain up to and including the upper layer header, RA Guard must drop it. And if RA Guard cannot find the upper layer protocol because of an unknown extension header or similar, the configurable behaviour must default to "drop". Hosts also tightened up: RFC 6980 forbids fragmented Neighbor Discovery messages, so modern stacks discard them anyway. When you buy or configure switches, ask specifically for RA Guard that complies with RFC 7113.

DHCPv6-Shield (RFC 7610)

DHCPv6-Shield, published in August 2015 as BCP 199, does the same for DHCPv6 that DHCP snooping does for IPv4. The switch drops DHCPv6 server messages (Advertise, Reply, Reconfigure, Relay-reply) arriving on ports that are not configured as server ports. RFC 7610 says DHCPv6-Shield implementations MUST parse the entire IPv6 header chain, and it requires dropping first fragments that do not contain the full chain, the same lesson RFC 7113 taught RA Guard.

What these controls do not cover

Both only work where a supporting switch sits between hosts. Wi-Fi clients, guests on a hypervisor's virtual switch and anyone on a hotel network are protected only if that access point or virtual switch filters too, which is why host settings still matter.

Step by step: inspect your addresses and RA flags, and set privacy behaviour

The commands below are read only unless marked. They work on current releases as of October 2026; option names change, so check the linked documentation for your version.

Linux

Show your addresses and their types:

ip -6 addr show dev eth0

Look at the flags after each address. scope link is link-local. scope global dynamic mngtmpaddr is a stable SLAAC address used as the base for temporary addresses. scope global temporary dynamic is an RFC 8981 temporary address. valid_lft and preferred_lft show the remaining lifetimes in seconds. An address with ff:fe in the middle of the identifier is EUI-64.

Show the default route and where it came from:

ip -6 route show default

A route with proto ra was learned from a Router Advertisement.

See the RA itself, including M and O flags, prefixes and RDNSS. The rdisc6 tool comes from the ndisc6 package on most distributions:

rdisc6 eth0

The output shows whether stateful address configuration (M) and stateful other configuration (O) are set, the router lifetime, each prefix with its on-link and autonomous flags and lifetimes, and any recursive DNS servers.

Watch RAs and DHCPv6 on the wire. ICMPv6 type 134 is Router Advertisement; UDP 546 and 547 are DHCPv6:

sudo tcpdump -i eth0 -vv 'icmp6 and ip6[40] == 134'
sudo tcpdump -i eth0 -vv 'udp port 546 or udp port 547'

The ip6[40] offset assumes no extension headers, which is fine for normal traffic; it will miss exactly the kind of evasive RA that RFC 7113 describes, so treat it as a diagnostic, not a monitor.

Check the kernel settings for an interface:

sysctl net.ipv6.conf.eth0.accept_ra \
       net.ipv6.conf.eth0.autoconf \
       net.ipv6.conf.eth0.use_tempaddr \
       net.ipv6.conf.eth0.addr_gen_mode \
       net.ipv6.conf.eth0.temp_valid_lft \
       net.ipv6.conf.eth0.temp_prefered_lft

Change privacy behaviour (this changes configuration). Where NetworkManager manages the connection:

# Prefer temporary addresses for outgoing connections (2 = enabled, prefer temporary)
nmcli connection modify "Wired connection 1" ipv6.ip6-privacy 2
# Use RFC 7217 stable addresses instead of EUI-64
nmcli connection modify "Wired connection 1" ipv6.addr-gen-mode stable-privacy
nmcli connection up "Wired connection 1"

With systemd-networkd, in the .network file for the interface. IPv6PrivacyExtensions=yes enables temporary addresses and prefers them over public ones; prefer-public enables them but prefers the stable address:

[Network]
IPv6AcceptRA=yes
IPv6PrivacyExtensions=yes

[IPv6AcceptRA]
Token=prefixstable

On a server where you want neither surprise routers nor surprise addresses, disable RA processing on that interface and configure addresses statically:

sudo sysctl -w net.ipv6.conf.eth0.accept_ra=0

Make sure you have a static IPv6 address and route configured first, or you will lose IPv6 connectivity on that interface. To make sysctl changes persistent, put them in a file under /etc/sysctl.d/.

Check DNS servers per link:

resolvectl dns

macOS

Show addresses, their flags and their remaining lifetimes:

ifconfig -L en0 inet6

On the Mac we checked, the link-local address and the stable global address carried the flag secured and had no ff:fe pattern in their identifiers, so they were not built from the MAC address; SLAAC addresses carried autoconf, privacy addresses carried temporary, and older temporary addresses that had passed their preferred lifetime carried deprecated. The -L option adds pltime and vltime, the remaining preferred and valid lifetimes in seconds.

Show learned prefixes and default routers:

ndp -p
ndp -r

Show the last Router Advertisement received, and the DHCPv6 packet if any. The ipconfig manual page shipped with macOS documents both:

ipconfig getra en0
ipconfig getv6packet en0
ipconfig getsummary en0

Show the kernel's temporary address settings:

sysctl net.inet6.ip6.use_tempaddr net.inet6.ip6.temppltime net.inet6.ip6.tempvltime

Show the resolver configuration:

scutil --dns

To turn IPv6 off and on for a service while testing (this changes configuration), use networksetup -setv6off "Wi-Fi" and networksetup -setv6automatic "Wi-Fi".

Windows

In PowerShell, list IPv6 addresses with their origin:

Get-NetIPAddress -AddressFamily IPv6 |
  Select-Object InterfaceAlias, IPAddress, PrefixOrigin, SuffixOrigin, AddressState, ValidLifetime, PreferredLifetime

Microsoft lists the PrefixOrigin values as Other, Manual, WellKnown, Dhcp and RouterAdvertisement; RouterAdvertisement means SLAAC and Dhcp means DHCPv6. Microsoft's documentation lists the accepted SuffixOrigin values as Other, Manual, WellKnown, Dhcp, Link and Random: Link marks an interface identifier derived from the link-layer address, Random a randomised one.

Show global privacy settings:

Get-NetIPv6Protocol | Select-Object RandomizeIdentifiers, UseTemporaryAddresses, MaxTemporaryValidLifetime, MaxTemporaryPreferredLifetime

Show the per-interface router discovery and DHCPv6 settings. Microsoft documents RouterDiscovery (Disabled, Enabled, ControlledByDHCP), ManagedAddressConfiguration and OtherStatefulConfiguration (Disabled or Enabled) as interface properties:

Get-NetIPInterface -AddressFamily IPv6 |
  Select-Object InterfaceAlias, RouterDiscovery, ManagedAddressConfiguration, OtherStatefulConfiguration

Change privacy behaviour (this changes configuration; run as administrator):

Set-NetIPv6Protocol -UseTemporaryAddresses Enabled
Set-NetIPv6Protocol -RandomizeIdentifiers Enabled

Microsoft documents RandomizeIdentifiers as whether the interface randomises identifiers when it creates an address, with a default of Enabled. UseTemporaryAddresses accepts Disabled, Enabled and Always; Always means the computer always generates temporary addresses using random numbers.

Show DNS servers learned for IPv6:

Get-DnsClientServerAddress -AddressFamily IPv6

On the switch or access point

Configuration syntax varies by vendor, so the steps are generic:

  1. Identify which ports connect to real routers or DHCPv6 servers or relays.
  2. Enable RA Guard with those ports set as router ports and all access ports as host ports.
  3. Enable DHCPv6-Shield (often called DHCPv6 guard) with the same split for server ports.
  4. Confirm the implementation follows RFC 7113: it must drop RAs hidden behind extension headers and first fragments without the full header chain.
  5. On Wi-Fi, enable the controller's equivalent RA and DHCPv6 filtering for client traffic, and client isolation where clients do not need to reach each other.
  6. Test from an access port with a lab host that sends a harmless RA for a documentation prefix (2001:db8::/32), and confirm no other host learns it.

Comparison: which addressing method fits which goal

MethodPrivacy across networksPrivacy on one networkTraceability for the operatorOperational fit
SLAAC with modified EUI-64Poor: same IID everywhere, MAC recoverablePoor: same address every dayEasy: address maps directly to MACLegacy only; RFC 8064 says not by default
SLAAC with RFC 7217 stable IIDGood: different IID per networkPoor by design: stable on that networkGood: stable address, map MAC via router neighbour tableDefault choice for stable addresses; servers, printers, anything you firewall by address
RFC 8981 temporary addressesGoodGood: changes daily by defaultNeeds logging of the router's neighbour table, since addresses rotateCommon choice for outgoing client traffic on desktop and mobile systems
Stateful DHCPv6 (IA_NA)Depends on DUID; a stable DUID is trackableLease is stable while renewedStrong: server logs which DUID had which addressManaged enterprise networks; not supported by Android
DHCPv6 prefix delegation per client (RFC 9663)Depends on DUIDHost chooses addresses within its prefixStrong at prefix level: one prefix per clientLarge shared networks; needs router and host support for RFC 9762

In practice: on client networks that include phones, use SLAAC with RFC 7217 and temporary addresses, and log the router's neighbour table if you need to answer "who had this address at 10:42?". For servers, use static addresses or DHCPv6 reservations. Everywhere, filter RAs and DHCPv6 server messages on access ports.

Common mistakes

  • Treating an "IPv4 only" network as having no IPv6 attack surface. Hosts still accept RAs. Filter RAs even if you have never deployed IPv6.
  • Setting M and expecting it to disable SLAAC. It does not. You must clear the A flag on the prefix to stop SLAAC addresses.
  • Expecting DHCPv6 to provide the default gateway. It never does. If RAs are blocked or misconfigured, DHCPv6 clients have no route.
  • Deploying stateful DHCPv6 only, with A=0, on a network with Android devices. They get no global IPv6 address.
  • Sending different DNS servers in RDNSS and DHCPv6. Hosts will disagree about which to use.
  • Using a single long lived temporary address because the OS default was tuned for an older RFC. Check temp_valid_lft, tempvltime or MaxTemporaryValidLifetime against the two day default in RFC 8981 and decide whether you agree.
  • Logging only DHCPv6 leases for attribution. SLAAC and temporary addresses never touch the DHCPv6 server. Log neighbour tables or use switch binding tables instead.
  • Buying switches with RA Guard that ignores extension headers. Ask for RFC 7113 behaviour and test it.
  • Disabling IPv6 on hosts as a "fix". It hides the symptom on the hosts you remember and leaves every other device on the link exposed. Filtering RAs and DHCPv6 at the switch fixes the network, not just one machine.

FAQ

What is SLAAC in IPv6?

SLAAC (RFC 4862) is how an IPv6 host builds its own global address: it takes a 64 bit prefix from a Router Advertisement with the A flag set, appends an interface identifier it generates itself and checks the result with Duplicate Address Detection. No server tracks the address.

What do the M and O flags mean in a router advertisement?

The M (Managed) flag means addresses are available from DHCPv6. The O (Other) flag means other configuration, such as DNS servers, is available from DHCPv6. If neither is set, nothing is available from DHCPv6. The flags are hints defined in RFC 4861, and they do not turn SLAAC off; only clearing the A flag on a prefix does that.

Does my IPv6 address reveal my MAC address?

Only if your device uses modified EUI-64 identifiers, recognisable by ff:fe in the middle of the last 64 bits. RFC 8064 says hosts should not do that by default, and many current systems use RFC 7217 style or randomised identifiers plus temporary addresses for outgoing traffic. Check yours with the commands in this post; on Linux the kernel default for addr_gen_mode is still EUI-64 unless your network manager changes it. Your local router still sees your MAC address, as it does on IPv4.

What is an IPv6 privacy address?

A privacy address, formally a temporary address under RFC 8981, is an extra IPv6 address with a random interface identifier that a host uses for outgoing connections and replaces regularly. RFC 8981's defaults are a one day preferred lifetime and a two day valid lifetime, so it changes roughly daily.

What is the difference between RFC 7217 and RFC 8981 addresses?

An RFC 7217 address is stable on one network and different on every other, so it stops cross-network tracking. An RFC 8981 temporary address also changes on a schedule, so it stops day to day recognition. Many hosts use both.

Why does Android not support DHCPv6?

Android's DHCPv6 client, according to its own source code, supports only prefix delegation (IA_PD), not address assignment (IA_NA). RFC 7934 (BCP 204), written by authors from Google and Apple, sets out why one server assigned address does not meet the needs of hosts that use several addresses for privacy, tethering and translation. Prefix delegation per client (RFC 9663, RFC 9762) is the newer alternative.

How do I stop rogue router advertisements?

On the network, enable RA Guard on switch access ports and the equivalent on Wi-Fi controllers, using an implementation that follows RFC 7113. On hosts that should never learn routes from the network, such as servers with static configuration, disable RA processing. On the hosts you cannot control, rely on the network filtering.

Does DHCPv6 give out a default gateway?

No. The default router always comes from Router Advertisements, so RA filtering matters even on stateful DHCPv6 networks.

Where Safeguard fits

Safeguard does not configure networks, filter Router Advertisements or watch switch ports, and nothing in this post depends on it. The fit is indirect: IPv6 autoconfiguration is implemented in software you ship or run, from the DHCPv6 clients and servers and RA daemons in your container images and appliances to the networking libraries in your services. When one of those open source components has a known vulnerability, Safeguard can show which of your projects and images contain the affected version and help you move to a fixed one.

Fix it without waiting for upstream

The DHCPv6 clients and servers, router advertisement daemons and Neighbor Discovery tools that implement everything above are mostly open source, and many of them reach you inside the container images and packages you build and ship. When one of those has a published vulnerability, the job is the same as for any other dependency: find every image and project that carries it and move to a fixed version, and where no fix exists yet, the fork and patch route described below is early access.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

The first demo is a real Safeguard CLI session. It asks the assistant to fix a lodash CVE in a repository, reads the finding, asks before each command, edits package.json and runs the tests with approval. The same flow applies if a scan of an image shows an outdated DHCPv6 client or RA daemon library: you ask for the upgrade and approve each step.

Click through it at your own pace, or open it full screen.

The second demo sets up the local runner on your own machine, approves it with a device code and then scans from the terminal. It suits network teams who want to scan the container images and SBOMs of their DHCP, DNS and routing services without sending source anywhere first.

Click through it at your own pace, or open it full screen.

The third demo connects Claude to the Safeguard MCP server with OAuth and chooses which tools Claude can use. It is useful when you want to ask an assistant which of your projects carry a given component version while you work through an IPv6 rollout plan.

Click through it at your own pace, or open it full screen.

To try it on your own projects, download Safeguard and follow the CLI documentation.

Quick check

A network sets the M flag in its router advertisements but leaves the A flag set on its prefix. What addresses does a Linux laptop end up with?

Both. The A flag still triggers SLAAC, so the laptop forms a stable address and usually a temporary one, and the M flag makes it request a DHCPv6 lease as well. To stop SLAAC you must clear the A flag on the prefix.

Why can a rogue router advertisement redirect traffic on a network that uses stateful DHCPv6?

Because DHCPv6 never provides a default route. Hosts learn their default router only from router advertisements, so an unfiltered rogue RA can make itself the default router whatever the DHCPv6 server says.

Sources

Last reviewed: 23 October 2026. Operating system defaults and command options change between releases; check the documentation linked above for the version you run.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.