netbirdio/netbird · error
allow netbird v4 interface traffic: %w
Error message
allow netbird v4 interface traffic: %w
What it means
AllowNetbird installs a blanket ACCEPT for all v4 overlay traffic (0.0.0.0, ProtocolALL) via AddPeerFiltering, so that packet filtering happens in userspace when USPFilter wraps the native firewall (called from client/firewall/create_linux.go:108). This error means the v4 accept rule could not be appended to NETBIRD-ACL-INPUT; the uspfilter wrapper logs it and continues, but the kernel chain may then drop overlay traffic that userspace expected to be pre-allowed.
Source
Thrown at client/firewall/iptables/manager_linux.go:381
}
// attempt to delete state only if all other operations succeeded
if merr == nil {
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 managerView on GitHub (pinned to 93e97f4bf1)
Solutions
- Restart the agent: Init re-creates the ACL chains and AllowNetbird is retried during firewall creation
- Verify the chain exists as root: iptables -S NETBIRD-ACL-INPUT
- If it recurs, find the external tool rewriting the filter table and exclude the NETBIRD chains
Defensive patterns
Strategy: try-catch
Validate before calling
// before relying on userspace filtering, confirm the v4 accept chain exists
if out, err := exec.Command("iptables", "-S", "NETBIRD-ACL-INPUT").Output(); err != nil {
log.Warnf("ACL chain missing; AllowNetbird rule cannot hold: %s", out)
} Try / catch
if err := fm.AllowNetbird(); err != nil {
log.Errorf("userspace pre-allow failed; overlay traffic may be dropped by kernel chains: %v", err)
// recreate chains via restart rather than proceeding degraded
} Prevention
- Call AllowNetbird only right after successful Init so chains are fresh
- Protect NETBIRD chains from external flush tools in container environments
- Treat this error as connectivity-affecting, not cosmetic
When it happens
Trigger: AllowNetbird when the v4 aclManager append fails - NETBIRD-ACL-INPUT missing after an external flush, iptables erroring, or a race with Close/reset.
Common situations: Userspace-bind agents (no kernel WireGuard) whose native chains were wiped by docker/podman/firewalld mid-run; chains removed between Init and AllowNetbird.
Related errors
- allow netbird v6 interface traffic: %w
- add IP to ipset: %w
- failed to check rule: %w
- rule already exists
- failed to delete rule: %s, %v: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/6c4eba4f0e6fe065.
Report an issue: GitHub.