netbirdio/netbird · warning

address %s is part of the NetBird network %s, refusing to wr

Error message

address %s is part of the NetBird network %s, refusing to write

What it means

UDPConn.WriteTo on the universal UDP mux refuses datagrams whose destination falls inside the NetBird overlay network (the v4 Network or v6 IPv6Net prefixes attached to that shared underlay socket). The mux carries peer/ICE underlay traffic; writing to an overlay address would send underlay packets into the tunnel and create a routing loop, so the guard logs a warning and returns this error with zero bytes written.

Source

Thrown at client/iface/udpmux/universal.go:131

	mux     *UniversalUDPMuxDefault
	logger  logging.LeveledLogger
	address wgaddr.Address
}

// GetPacketConn returns the underlying PacketConn
func (u *UDPConn) GetPacketConn() net.PacketConn {
	return u.PacketConn
}

func (u *UDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
	udpAddr, ok := addr.(*net.UDPAddr)
	if !ok {
		return u.PacketConn.WriteTo(b, addr)
	}
	dst := udpAddr.AddrPort().Addr().Unmap()
	if (u.address.Network.IsValid() && u.address.Network.Contains(dst)) || (u.address.IPv6Net.IsValid() && u.address.IPv6Net.Contains(dst)) {
		log.Warnf("address %s is part of the NetBird network %s, refusing to write", addr, u.address)
		return 0, fmt.Errorf("address %s is part of the NetBird network %s, refusing to write", addr, u.address)
	}
	return u.PacketConn.WriteTo(b, addr)
}

// GetSharedConn returns the shared udp conn
func (m *UniversalUDPMuxDefault) GetSharedConn() net.PacketConn {
	return m.params.UDPConn
}

// GetListenAddresses returns the listen addr of this UDP
func (m *UniversalUDPMuxDefault) GetListenAddresses() []net.Addr {
	return []net.Addr{m.LocalAddr()}
}

// GetRelayedAddr creates relayed connection to the given TURN service and returns the relayed addr.
// Not implemented yet.
func (m *UniversalUDPMuxDefault) GetRelayedAddr(turnAddr net.Addr, deadline time.Duration) (*net.Addr, error) {
	return nil, fmt.Errorf("not implemented yet")

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Ensure relay/management/peer hostnames resolve to underlay addresses, not overlay IPs
  2. Do not reuse the mux's shared conn for application traffic
  3. Check the configured network ranges for accidental overlap with the intended destination space
  4. After fixing, verify WriteTo destinations sit outside both overlay prefixes

Example fix

// before
target := resolve("relay.example.net") // returned 100.96.4.7, an overlay IP
_, err := sharedConn.WriteTo(pkt, target) // refused, 0 bytes

// after
target := resolveUnderlay("relay.example.net") // public/underlay IP enforced
_, err := sharedConn.WriteTo(pkt, target)
Defensive patterns

Strategy: validation

Validate before calling

func isOverlayDestination(dst netip.Addr, v4, v6 netip.Prefix) bool {
    dst = dst.Unmap()
    return (v4.IsValid() && v4.Contains(dst)) || (v6.IsValid() && v6.Contains(dst))
}

if isOverlayDestination(udpAddr.AddrPort().Addr(), overlayV4, overlayV6) {
    return fmt.Errorf("refusing overlay destination %s", udpAddr)
}

Prevention

When it happens

Trigger: WriteTo with a destination inside the configured NetBird range: a relay or peer endpoint resolved to its overlay IP (100.64/10-style or the v6 ULA), or application code reusing the shared conn (GetSharedConn) to dial overlay addresses.

Common situations: DNS returning the overlay IP for a management or relay hostname; a stale network map mixing overlay IPs into underlay candidates; user code grabbing the shared conn for application data.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/15c5ecf3f7b455be. Report an issue: GitHub.