netbirdio/netbird · error

allow netbird v6 interface traffic: %w

Error message

allow netbird v6 interface traffic: %w

What it means

IPv6 counterpart of the blanket overlay accept in AllowNetbird: with hasIPv6() true it appends an ACCEPT for net.IPv6zero through aclMgr6.AddPeerFiltering. Failure means the v6 accept rule could not be installed, so v6 overlay traffic may be dropped by the kernel chain while userspace filtering believes it is pre-allowed. Accumulated alongside the v4 result and returned as a multierror.

Source

Thrown at client/firewall/iptables/manager_linux.go:385

		if err := stateManager.DeleteState(&ShutdownState{}); err != nil {
			merr = multierror.Append(merr, fmt.Errorf("delete state: %w", err))
		}
	}

	return nberrors.FormatErrorOrNil(merr)
}

// AllowNetbird allows netbird interface traffic.
// This is called when USPFilter wraps the native firewall, adding blanket accept
// rules so that packet filtering is handled in userspace instead of by netfilter.
func (m *Manager) AllowNetbird() error {
	var merr *multierror.Error
	if _, err := m.AddPeerFiltering(nil, net.IP{0, 0, 0, 0}, firewall.ProtocolALL, nil, nil, firewall.ActionAccept, ""); err != nil {
		merr = multierror.Append(merr, fmt.Errorf("allow netbird v4 interface traffic: %w", err))
	}
	if m.hasIPv6() {
		if _, err := m.AddPeerFiltering(nil, net.IPv6zero, firewall.ProtocolALL, nil, nil, firewall.ActionAccept, ""); err != nil {
			merr = multierror.Append(merr, fmt.Errorf("allow netbird v6 interface traffic: %w", err))
		}
	}

	if err := firewalld.TrustInterface(m.wgIface.Name()); err != nil {
		log.Warnf("failed to trust interface in firewalld: %v", err)
	}

	return nberrors.FormatErrorOrNil(merr)
}

// Flush doesn't need to be implemented for this manager
func (m *Manager) Flush() error { return nil }

// SetLogLevel sets the log level for the firewall manager
func (m *Manager) SetLogLevel(log.Level) {
	// not supported
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Restart the agent so Init rebuilds v6 chains and AllowNetbird retries
  2. Verify with ip6tables -S NETBIRD-ACL-INPUT as root
  3. Identify and scope the external tool that flushes v6 chains
Defensive patterns

Strategy: try-catch

Validate before calling

if hasV6 := wgIface.Address().HasIPv6(); hasV6 {
    if _, err := exec.Command("ip6tables", "-S", "NETBIRD-ACL-INPUT").Output(); err != nil {
        log.Warnf("v6 ACL chain missing; v6 pre-accept may fail")
    }
}

Try / catch

if err := fm.AllowNetbird(); err != nil {
    var merr *multierror.Error
    if errors.As(err, &merr) {
        for _, e := range merr.Errors {
            if strings.Contains(e.Error(), "v6 interface traffic") {
                log.Errorf("v6 overlay traffic may be dropped: %v", e)
            }
        }
    }
}

Prevention

When it happens

Trigger: AllowNetbird on a v6-capable manager where the ip6tables append fails - v6 ACL chain missing after external flush or ip6tables erroring mid-operation.

Common situations: Firewalld/ip6tables-restore rewrites during agent startup; v6 chains removed between Init and AllowNetbird; flaky ip6tables on older kernels.

Related errors


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