IPv6 is increasingly being used in corporate and home networks, but many of its mechanisms remain poorly understood even by experienced administrators. Automatic address configuration, the use of link-local, and the principles of internal trust simplify network deployment, but at the same time they create new risk surfaces. That is why IPv6 requires a separate and careful analysis, and not perception as a “safer replacement for IPv4”.
The first part of the material examines the basic principles of IPv6 in the local segment: how devices obtain addresses, why ICMPv6 plays a critical role, and how trust is formed between nodes without administrator participation.
IPv6 is far from being widely implemented, but most modern operating systems have IPv6 enabled by default. In corporate networks, this often leads to hidden vulnerabilities: even if only IPv4 is used, Windows systems prefer IPv6 by default and periodically prompt for IPv6 configuration. Attackers can exploit the trust nature of IPv6 protocols to launch attacks on a local network. Spoofing attacks are particularly dangerous, where an attacker impersonates a legitimate network node or injects fake packets for the purpose of MITM and/or DNS spoofing on the local network.
Every IPv6-enabled network device automatically receives a link-local address from the fe80::/10 range. This address is generated regardless of the presence of DHCPv6 or a global prefix and is required for all key lower-level protocols to work: SLAAC (Stateless Address Autoconfiguration), NDP, RA, RS, and others.
Link-local addresses are valid only within a single L2 segment and are not routed beyond its boundaries. However, within a segment, they are the primary node identifiers in IPv6 service traffic.
In all ICMPv6 packets, including RA and NA, the sender must use only its link-local address as the source address. This means that:
DHCPv6 servers, routers, clients, and attackers communicate using fe80::/10;
Any machine receiving an RA or NA will write the link-local address as the source route, gateway, or DNS server;
An attacker who knows their fe80:: can spoof an RA by impersonating a gateway or DNS server without knowing the global prefix.
In addition, SLAAC uses RA packets from a router that specify the global prefix of the IPv6 address. A client that receives this RA from a source with a link-local address will assume that source to be a router if the packet passes basic parameter checking.
Thus, the link-local address in IPv6 is a mandatory L2 identifier, knowledge of which is necessary for most spoofing attacks on a local network. Obtaining and forging it does not require administrator rights on the target machine.
In IPv4 networks, broadcast traffic was used to discover hosts on a segment. For example, ARP requests, NetBIOS-NS, and others. In the case of IPv6, broadcast has been abolished and replaced by multicast groups. That is, instead of sending network packets to all hosts in a row, hosts now listen to certain groups, depending on their role and context.
ff02::1- “All-host multicast address” is the address for all hosts on the local segment. In fact, any device with IPv6 enabled automatically subscribes to this group. If IPv6 is active on the computer, it must accept this address. The following data is sent using ff02::1
ICMPv6 Echo Request
Router Advertisement (ICMPv6 type=134)
ff02::2 – “All-Routers Multicast Address” – The address for all routers on the local segment. Used for specific requests, such as router solicitation. Devices that act as IPv6 routers must accept packets sent to this address. The use of the address ff02::2 by routers is required for the correct operation of the ICMPv6 Router Solicitation (type 133) that end stations send during SLAAC (stateless address autoconfiguration) or when obtaining network route information.
The addresses ff02::/16 are reserved for link-level multicast. Remember that they are never routed outside the L2 segment. Also, using these addresses for multicast регулюється RFC 4291, розділ: 2.7.1.
The multicast delivery mechanism is a fundamental function that autoconfiguration, neighbor discovery, and routing protocols depend on. In IPv6 networks, each device with an active IPv6 stack automatically handles certain multicast addresses at the L2 segment level. This is necessary for the operation of core IPv6 protocols such as NDP, SLAAC, and ICMPv6.
For example:
All nodes process packets addressed to ff02::1 (all end hosts);
Devices acting as routers process packets on ff02::2 (all routers).
This mechanism allows an attacker to communicate with all hosts or routers on a local network simultaneously, without even knowing their addresses. This is used in:
Network Information Gathering;
Attacks related to false RA (Router Advertisement)
DNS Hijacking via RDNSS
The network for demonstrating the attacks will look like this. It is small, but sufficient to demonstrate the attacks in this article. It is worth noting that the prefix 2001:db8::/64 is allocated to the network, meaning that clients obtain their addresses using SLAAC.
This is actually a very useful method for gathering information about IPv6 networks. Of course, we can use Multicast Ping on ff02::1 and ff02::2 to discover hosts and routers, but this method is quite noisy and very easy to detect. And hosts may not always respond with a response packet, as it can be easily filtered by firmware or even HIPS/HBF.
A much more interesting method is passive host discovery, which is done by analyzing traffic on the air. That is, only by analyzing the air, we can gather information about the segment. We can listen only for key protocols in NDP, SLAAC, DHCPv6 and MLD to identify active hosts and understand how the network is structured.
When passively gathering information on an IPv6 segment, it is worth focusing on intercepting certain types of packets, as they are the most valuable for understanding the network structure and the presence of active hosts. Most of the underlying protocols, from autoconfiguration to address resolution, interact via multicast, which means that the entire process can be observed simply by listening to traffic on a segment.
Unlike IPv4, where aggressive ARP scanning was the norm, actively scanning /64 networks in IPv6 is simply pointless as it takes a lot of time. Therefore, only monitoring ICMPv6, DHCPv6, and MLD gives us a positive impact. For example:
RA (Router Advertisement) analysis detects active routers and prefix configurations;
Neighbor solicitation/advertisement allows us to associate MAC addresses and IPv6 addresses on a local network, even if the devices are not communicating externally;
DAD packets are often sent first when a device is powered on, giving us an early detection point;
Through DHCPv6, we can see who is requesting configurations and who is responding;
MLD can highlight “sleeping” devices that are not sending anything to the network but are subscribed to certain groups.
You can automate the process of analyzing such traffic with a small Python script with Scapy:
#!/usr/bin/env python3
from scapy.all import *
from scapy.layers.dhcp6 import *
from datetime import datetime
from colorama import Fore, Style, init
import argparse
init(autoreset=True)
DHCP6_TYPES = {
DHCP6_Solicit: "Solicit",
DHCP6_Advertise: "Advertise",
DHCP6_Request: "Request",
DHCP6_Reply: "Reply",
DHCP6_Renew: "Renew",
DHCP6_Rebind: "Rebind",
DHCP6_RelayForward: "Relay-Forward",
DHCP6_RelayReply: "Relay-Reply"
}
ICMP6_TYPES = {
ICMPv6ND_RS: ("ICMPv6 - Router Solicitation", Fore.CYAN),
ICMPv6ND_RA: ("ICMPv6 - Router Advertisement", Fore.GREEN),
ICMPv6ND_NS: ("ICMPv6 - Neighbor Solicitation", Fore.BLUE),
ICMPv6ND_NA: ("ICMPv6 - Neighbor Advertisement", Fore.MAGENTA),
ICMPv6ND_Redirect: ("ICMPv6 - Redirect", Fore.LIGHTRED_EX),
ICMPv6MLReport: ("ICMPv6 - MLD Report", Fore.LIGHTCYAN_EX),
ICMPv6MLReport2: ("ICMPv6 - MLD Report", Fore.LIGHTCYAN_EX),
ICMPv6MLDone: ("ICMPv6 - MLD Done", Fore.LIGHTCYAN_EX),
ICMPv6EchoRequest: ("ICMPv6 - Echo Request", Fore.LIGHTBLACK_EX),
ICMPv6EchoReply: ("ICMPv6 - Echo Reply", Fore.LIGHTBLACK_EX)
}
def handle(pkt):
eth_src = pkt[Ether].src if Ether in pkt else "?"
eth_dst = pkt[Ether].dst if Ether in pkt else "?"
ip6_src = pkt[IPv6].src if IPv6 in pkt else "?"
ip6_dst = pkt[IPv6].dst if IPv6 in pkt else "?"
# ICMPv6 Detection
for proto, (desc, color) in ICMP6_TYPES.items():
if proto in pkt:
break
else:
# DHCPv6 Detection
if UDP in pkt and pkt[UDP].dport == 547:
for dhcp_type, name in DHCP6_TYPES.items():
if dhcp_type in pkt:
desc = f"DHCPv6 - {name}"
color = Fore.YELLOW
break
else:
return
else:
return
print(color + f"[{datetime.now().strftime('%H:%M:%S')}] {desc}")
print(f"{Style.DIM} MAC {eth_src} -> {eth_dst}")
print(f"{Style.DIM} IPv6 {ip6_src} -> {ip6_dst}")
print(Style.RESET_ALL + "-" * 60)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="IPv6 NDP & DHCPv6 Sniffer")
parser.add_argument("-i", "--interface", required=True, help="Interface to sniff on")
parser.add_argument("-t", "--time", type=int, default=0, help="Sniff duration (0 = infinite)")
args = parser.parse_args()
print(Fore.LIGHTWHITE_EX + f"[*] Sniffing on {args.interface} for {args.time or '∞'} seconds...\n")
sniff(iface=args.interface, prn=handle, timeout=args.time or None, store=0)
The purpose of this sniffer is to passively listen to key IPv6 protocols such as NDP, MLD, and DHCPv6, and display useful information about network nodes, including MAC addresses, IPv6 addresses, and message types. The sniffer works as follows:
Interface selection: the user specifies the network interface ( -i eth0 ) from which traffic will be intercepted. You can also set a time limit ( -t 60 ) or leave the listening mode indefinitely (default);
Packet processing: for each packet that passes, the handle_packet() function is called, which checks its contents for the message types of interest;
Traffic type determination: the sniffer distinguishes between the following messages:
ICMPv6 neighbor discovery (RS, RA, NS, NA, redirect); ICMPv6 MLD (multicast listener discovery);
DHCPv6 (request, advertisement, reply, etc.)
Data extraction: the following is extracted from each packet:
Sender and recipient MAC addresses;
IPv6 source and destination addresses.
DHCPv6 Parsing: Unlike ICMPv6, DHCPv6 requires the type to be specified by the embedded message (Solicit, Advertise, etc.), so a separate function, parse_dhcpv6(), is used.
Here is an example of real sniffer output when analyzing traffic on the local IPv6 segment:
~:$ sudo python3 sniffer.py -i eth0 -t 500

The screenshot shows how the sniffer intercepts key IPv6 packets in real time. Each of them is of interest to an attacker:
DHCPv6 Solicit – the client searches for a DHCPv6 server, which opens the possibility of its spoofing and sending malicious parameters (DNS, routes).
Router Access Request (RS) – the device requests access to the RA, which means that it is vulnerable to RA spoofing and attacks through router settings.
Neighbor Advertisement (NA) – participation in the NDP exchange allows for spoofing attacks and traffic interception.
MLD Report – shows which multicast groups the client participates in, which helps to build the network topology and identify active devices.
Thus, using simple traffic analysis, it is possible to collect network data without resorting to active scanning or mcast ping.
Thus, IPv6 by default creates a high-trust environment within the local segment. Link-local addresses, multicast, and service protocols work automatically and constantly exchange information between nodes, even if IPv6 is not formally used in the network. This makes the segment structure transparent to any device with an active IPv6 stack.
Understanding these mechanisms allows us to move from theory to practice. In the second part, we will consider how this trust is used in real networks, starting from passive traffic analysis and ending with full-fledged traffic interception and control scenarios.