Skip to content
WSLDeep Dive Published Updated 8 min readViews unavailable

IPv6 and Multicast Service Discovery in WSL 2

Test IPv6 and multicast discovery in WSL 2 with mirrored networking while separating Linux sockets, Windows firewall policy, and LAN behavior.

A Linux service can bind successfully in WSL 2 and still fail to discover peers. Unicast reachability, multicast membership, IPv6 address selection, broadcast, DNS, and firewall policy are distinct behaviors. Treating them all as “networking works” hides the failure boundary.

Microsoft documents IPv6 and multicast support among the benefits of mirrored networking for WSL 2 on Windows 11 22H2 and later. That is not a promise that every protocol, interface, VPN, firewall rule, or application discovery library behaves exactly like native Linux. Record the Windows build, WSL version, selected networking mode, and the actual Linux interfaces before interpreting a test. NAT and mirrored networking have different packet paths, and a result in one mode should not be generalized to the other.

Separate address families and discovery mechanisms

IPv4 multicast uses multicast group addresses rather than the limited broadcast address. IPv6 has no broadcast address; it uses multicast with defined scopes and an interface context. A service may use multicast for discovery and then open a separate unicast connection to the discovered peer. Seeing a discovery announcement therefore does not prove that the subsequent service port is reachable.

Application protocols choose their own groups, ports, TTL or hop limit, and interface behavior. mDNS, SSDP, and proprietary discovery protocols are not interchangeable. Some libraries bind an interface automatically, others require an interface or scope identifier. A receiver that joins the wrong group or listens on the wrong address family can look like a network failure while unicast connectivity is healthy.

First inventory the guest:

ip -br addr
ip -6 route
ip maddress show
ip route
ss -ulpen

Record which interface owns each address and whether the process has a UDP socket on the expected port. The multicast address list shows memberships visible to Linux interfaces; it does not prove that a packet crossed the Windows host boundary. For IPv6 link-local addresses and groups, an interface scope matters. A global-looking application log that omits the interface can conceal a scope mismatch.

Select a supported networking mode deliberately

The WSL networking documentation lists mirrored mode on Windows 11 version 22H2 and higher and names IPv6, multicast, improved VPN compatibility, and LAN connectivity as its benefits. Its availability and exact behavior depend on supported WSL and Windows versions. Configure it in the global Windows-user .wslconfig file, then shut down the managed WSL VM and restart before testing:

[wsl2]
networkingMode=mirrored

This is a global setting for WSL 2 distributions, not a per-process switch. Keep the previous configuration so you can return to NAT for comparison. Confirm effective behavior from Linux instead of treating a saved INI value as proof that the mode is active. Record interface addresses and routes after restart and note any mode fallback reported by the WSL version or logs.

NAT mode may provide ordinary outbound unicast connectivity while a discovery protocol remains unavailable across a boundary. Do not label that result as “multicast is broken in WSL” until the same packet, group, interface, and port have been tested in mirrored mode on a supported host. Conversely, a successful multicast exchange between two processes inside one environment does not prove discovery across the physical LAN.

An interface can have a valid IPv6 address and route while a link-local discovery packet still fails because the application selected the wrong interface index. Likewise, a successful IPv4 multicast probe does not test IPv6 group membership. Keep address-family tests separate, and include the interface index or name in diagnostics. A dual-stack application should log which socket it opened and whether it joined each group rather than collapsing all discovery into one “online” flag.

Use a receiver-first, bounded test

For a protocol-specific test, start a receiver on the intended interface and group, then send a single known payload from another host or process. Capture the local socket state and packet evidence at the same time. A minimal Linux Python receiver can test IPv4 multicast membership on a chosen interface address:

import socket

group = "239.255.42.99"
port = 50000
interface = "0.0.0.0"

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("", port))
membership = socket.inet_aton(group) + socket.inet_aton(interface)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, membership)
sock.settimeout(15)
print(sock.recvfrom(2048))

This is a bounded lab receiver, not a production daemon. On Linux, selecting 0.0.0.0 as the local interface in the membership request leaves the kernel to choose an interface; replace it with a specific local IPv4 address when the host has multiple interfaces. The sender must use the same group and port and a TTL suitable for the test path. A router usually does not forward multicast by default, so do not expect a LAN-wide result without multicast routing policy.

For IPv6, use a separate test with an IPv6 socket, the protocol’s multicast group, and an explicit interface index when the group is link-local. Do not paste IPv4 group-membership code into an IPv6 client. RFC 4291 defines IPv6 addressing architecture and multicast address scope; the application protocol defines which group is correct.

Use a short receive timeout and one marker payload so the test has a clear end condition. Test a sender and receiver in the same distro first, then across two WSL processes, then from the Windows host or a separate LAN peer according to the support requirement. The progression identifies where the boundary changes. Do not begin by capturing all interfaces for several minutes; a narrow group, port, interface, and timestamp makes the trace easier to interpret and limits unrelated data collection.

Distinguish Linux firewall, Hyper-V firewall, and host network policy

A guest-side packet capture can establish whether Linux sees an incoming datagram. Windows Hyper-V firewall policy can affect WSL traffic separately from a Linux firewall. The physical network can also suppress multicast or isolate wireless clients. Check each boundary independently and apply only the narrow rule needed for the test. Do not disable every firewall to make a discovery demo pass.

For a WSL-to-Windows or WSL-to-LAN failure, use a sequence: prove local receiver works, prove Linux socket membership, capture at the Linux interface, observe Windows firewall events or policy, and then test a peer on the same segment. A Windows-only packet trace and a Linux-only capture are different vantage points. If no packet reaches the Linux interface, changing the application’s membership code may be premature; if packets arrive but the app ignores them, inspect its group, interface selection, and parser.

Remember that multicast discovery often carries names or endpoints followed by ordinary TCP or UDP traffic. Once discovery succeeds, test the advertised unicast address and service port independently. Mirrored mode’s support for multicast does not automatically open inbound ports; Windows firewall rules and the application listener still matter.

Verify DNS separately from multicast

DNS tunneling is a separate WSL feature from multicast. A service that resolves a hostname through DNS can work even if multicast is unavailable; a service-discovery protocol can find a peer without DNS. Run a DNS query and a multicast test independently and preserve their outputs separately. Avoid using ping as the only proof because ICMP policy says little about UDP discovery or service ports.

For application-level diagnostics, log the interface, address family, multicast group, UDP port, membership result, and received datagram length. Redact payloads if discovery messages contain device identifiers or internal hostnames. Keep the test duration and expected sender count bounded so repeated packets do not create noisy or privacy-sensitive captures.

Watch for duplicate listeners and stale membership

During repeated tests, stop the old receiver before starting a new one and inspect all matching sockets. UDP reuse options can allow more than one process to bind a port, and packet delivery among those sockets can depend on operating-system behavior and socket configuration. A discovery daemon left running in another distro or container can make a test appear nondeterministic. Record process IDs and interface names, not only a port number.

If an interface disappears or changes after a VPN transition, multicast membership may need to be re-established by the application. Re-run ip address, ip route, and membership inspection after the transition. Avoid hard-coding a transient interface index in a service configuration unless the application re-resolves it when networking changes. A successful first discovery is not evidence that a long-lived daemon survived a network topology change.

Acceptance matrix for discovery applications

Validate each supported host configuration: NAT or mirrored mode, exact Windows build and WSL version, VPN disconnected and connected if relevant, local receiver, second WSL process, Windows host, and a physical LAN peer. Not every product needs every case, but production acceptance should define which boundaries it promises. Repeat after WSL or Windows updates that affect networking.

A pass requires the intended address family and socket membership, a received discovery packet from the expected source, and a successful follow-up unicast connection. If a test passes only in mirrored mode, document the Windows and WSL prerequisites instead of implying that all WSL 2 installations behave identically. If it passes locally but not across a router or Wi-Fi segment, investigate multicast routing and client isolation outside WSL.

Related:

Sources:

Comments