slackhq/nebula · error

failed to set tun address %s: %s

Error message

failed to set tun address %s: %s

What it means

addIp configures an IPv4 address on the FreeBSD tun interface via the SIOCAIFADDR ioctl on a routing socket. When that ioctl fails, the address string and the raw errno are wrapped in this error. It means the kernel rejected the ifaliasreq for this interface/address combination.

Source

Thrown at overlay/tun_freebsd.go:433

				Len:    unix.SizeofSockaddrInet4,
				Family: unix.AF_INET,
				Addr:   getBroadcast(cidr).As4(),
			},
			MaskAddr: unix.RawSockaddrInet4{
				Len:    unix.SizeofSockaddrInet4,
				Family: unix.AF_INET,
				Addr:   prefixToMask(cidr).As4(),
			},
			VHid: 0,
		}
		s, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_IP)
		if err != nil {
			return err
		}
		defer syscall.Close(s)
		// Note: unix.SIOCAIFADDR corresponds to FreeBSD's OSIOCAIFADDR
		if err := ioctl(uintptr(s), unix.SIOCAIFADDR, uintptr(unsafe.Pointer(&ifr))); err != nil {
			return fmt.Errorf("failed to set tun address %s: %s", cidr.Addr().String(), err)
		}
		return nil
	}

	if cidr.Addr().Is6() {
		ifr := ifreqAlias6{
			Name: t.deviceBytes(),
			Addr: unix.RawSockaddrInet6{
				Len:    unix.SizeofSockaddrInet6,
				Family: unix.AF_INET6,
				Addr:   cidr.Addr().As16(),
			},
			PrefixMask: unix.RawSockaddrInet6{
				Len:    unix.SizeofSockaddrInet6,
				Family: unix.AF_INET6,
				Addr:   prefixToMask(cidr).As16(),
			},
			Lifetime: addrLifetime{

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Check the wrapped errno in the message — EPERM/EACCES means run as root or grant privileges; EINVAL/EADDRNOTAVAIL means the address/subnet is invalid
  2. Ensure the configured CIDR is a valid IPv4 prefix (e.g. 10.0.0.1/24) and the address is inside the declared network
  3. Verify the tun device was created and named correctly before Activate is called
  4. Check kernel logs (dmesg) for ifconfig/ioctl rejections

Example fix

// before
vpnNetworks: []netip.Prefix{netip.MustParsePrefix("10.0.0.1/16")}, // host bits set
// after
p, _ := netip.ParsePrefix("10.0.0.1/16")
p = p.Masked() // 10.0.0.0/16
vpnNetworks: []netip.Prefix{netip.MustParsePrefix("10.0.0.1/16"), } // ensure .Masked() applied where required
Defensive patterns

Strategy: validation

Validate before calling

p, err := netip.ParsePrefix(cfgAddr)
if err != nil || !p.Addr().Is4() {
    return fmt.Errorf("invalid IPv4 tun address %q", cfgAddr)
}

Type guard

func isIPv4Prefix(p netip.Prefix) bool { return p.IsValid() && p.Addr().Is4() }

Try / catch

if err := dev.Activate(); err != nil {
    var serr syscall.Errno
    if strings.Contains(err.Error(), "failed to set tun address") && errors.As(err, &serr) && (serr == syscall.EPERM || serr == syscall.EACCES) {
        return fmt.Errorf("insufficient privileges to assign tun address: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Activate() (which calls addIp per configured VPN network prefix) where the ioctl SIOCAIFADDR on the routing socket returns an error — invalid CIDR, address not belonging to the interface's subnet, or device not properly opened.

Common situations: Configuring an address whose subnet doesn't match the destination in the ifreq; the tun interface not yet up / wrong device name; running without sufficient privileges (ioctl on routing socket requires root or CAP_NET_ADMIN-equivalent on FreeBSD); malformed vpnNetworks config.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/bf112f9255455f4d. Report an issue: GitHub.