netbirdio/netbird · error
create IPv6 firewall: %w
Error message
create IPv6 firewall: %w
What it means
Manager creation took the IPv6 branch (wgIface.Address().HasIPv6()) and createIPv6Components failed, wrapping the ip6tables client init, the v6 router, or the v6 ACL manager construction. In practice the error is the ip6tables binary being missing/unusable, or v6 chain/table operations failing because the kernel has IPv6 disabled (ipv6.disable=1) while the NetBird interface was given a v6 address, or missing ip6table_* modules.
Source
Thrown at client/firewall/iptables/manager_linux.go:72
m := &Manager{
wgIface: wgIface,
ipv4Client: iptablesClient,
}
m.router, err = newRouter(iptablesClient, wgIface, mtu)
if err != nil {
return nil, fmt.Errorf("create router: %w", err)
}
m.aclMgr, err = newAclManager(iptablesClient, wgIface)
if err != nil {
return nil, fmt.Errorf("create acl manager: %w", err)
}
if wgIface.Address().HasIPv6() {
if err := m.createIPv6Components(wgIface, mtu); err != nil {
return nil, fmt.Errorf("create IPv6 firewall: %w", err)
}
}
return m, nil
}
func (m *Manager) createIPv6Components(wgIface iFaceMapper, mtu uint16) error {
ip6Client, err := iptables.NewWithProtocol(iptables.ProtocolIPv6)
if err != nil {
return fmt.Errorf("init ip6tables: %w", err)
}
m.ipv6Client = ip6Client
m.router6, err = newRouter(ip6Client, wgIface, mtu)
if err != nil {
return fmt.Errorf("create v6 router: %w", err)
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- If the host should be v4-only, stop assigning IPv6 to the NetBird interface (management setting / network range) so HasIPv6() is false.
- If dual-stack is intended, install ip6tables and load ip6table_filter/ip6table_mangle; ensure /proc/net/if_inet6 exists (no ipv6.disable=1).
- Run the agent as root so v6 table operations succeed.
- Check `ip6tables -L` manually in the daemon's environment.
Defensive patterns
Strategy: validation
Validate before calling
func verifyV6FirewallReadiness(hasIPv6 bool) error {
if !hasIPv6 {
return nil
}
if _, err := os.Stat("/proc/net/if_inet6"); err != nil {
return errors.New("interface has IPv6 but kernel IPv6 is disabled; remove the v6 address or enable IPv6")
}
if _, err := exec.LookPath("ip6tables"); err != nil {
return fmt.Errorf("ip6tables required for dual-stack: %w", err)
}
if os.Geteuid() != 0 {
return errors.New("v6 firewall setup requires root")
}
return nil
}
// call with wgIface.Address().HasIPv6() before iptables.Create() Type guard
func ifaceHasIPv6(a wgaddr.Address) bool { return a.HasIPv6() } Try / catch
if _, err := iptablesMgr.Create(wgIface, mtu); err != nil {
if strings.Contains(err.Error(), "create IPv6 firewall") {
// either install ip6tables/enable IPv6, or drop the v6 address so HasIPv6() is false
log.Errorf("v6 firewall init failed: %v; align IPv6 enablement with the interface config", err)
}
} Prevention
- Only assign IPv6 addresses to the NetBird interface on hosts with real kernel IPv6 support.
- Install ip6tables whenever iptables is installed; they ship together in mainstream distros.
- Never boot with ipv6.disable=1 on hosts expected to run dual-stack overlays.
- Test `ip6tables -L` in the daemon environment as part of deployment checks.
When it happens
Trigger: Interface address reports IPv6 but the host lacks ip6tables (common in minimal images that ship only v4 iptables); kernel booted with ipv6.disable=1 or blacklisted ipv6 module while the overlay got a v6 address; ip6table_filter/ip6table_mangle modules not loadable; non-root daemon.
Common situations: Dual-stack misconfiguration where management assigns v6 addresses to peers on v4-only hosts; slim containers; hardened kernels with CONFIG_IPV6=m but no module; hosts where /proc/net/if_inet6 is absent.
Related errors
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/c6c41d6145a99ee2.
Report an issue: GitHub.