{"record":{"id":"3696bc9b68e1fd99","repo":"netbirdio/netbird","slug":"create-ipset-w","errorCode":null,"errorMessage":"create ipset: %w","messagePattern":"create ipset: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/iptables/acl_linux.go","lineNumber":140,"sourceCode":"\t\t\treturn []firewall.Rule{&Rule{\n\t\t\t\truleID:    uuid.New().String(),\n\t\t\t\tipsetName: ipsetName,\n\t\t\t\tip:        ip.String(),\n\t\t\t\tchain:     chain,\n\t\t\t\tspecs:     specs,\n\t\t\t\tv6:        m.v6,\n\t\t\t}}, nil\n\t\t}\n\n\t\tif err := m.flushIPSet(ipsetName); err != nil {\n\t\t\tif errors.Is(err, ipset.ErrSetNotExist) {\n\t\t\t\tlog.Debugf(\"flush ipset %s before use: %v\", ipsetName, err)\n\t\t\t} else {\n\t\t\t\tlog.Errorf(\"flush ipset %s before use: %v\", ipsetName, err)\n\t\t\t}\n\t\t}\n\t\tif err := m.createIPSet(ipsetName); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"create ipset: %w\", err)\n\t\t}\n\t\tif err := m.addToIPSet(ipsetName, ip); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"add IP to ipset: %w\", err)\n\t\t}\n\n\t\tipList := newIpList(ip.String())\n\t\tm.ipsetStore.addIpList(ipsetName, ipList)\n\t}\n\n\tok, err := m.iptablesClient.Exists(tableFilter, chain, specs...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to check rule: %w\", err)\n\t}\n\tif ok {\n\t\treturn nil, fmt.Errorf(\"rule already exists\")\n\t}\n\n\t// Insert DROP rules at the beginning, append ACCEPT rules at the end","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/acl_linux.go#L122-L158","documentation":"The ACL manager needed a new ipset for a ruleset, flushed the old one (tolerating absence), then ipset.Create with TypeHashNet and Replace:true failed at the netlink layer. Create fails when the process lacks CAP_NET_ADMIN, when the ip_set/ip_set_hash_net kernel modules are not loaded, or when the set name is invalid (ipset names are limited to 31 characters). The error wraps the raw netlink errno from ipset-go.","triggerScenarios":"First AddPeerFiltering call for a new ruleset while the agent runs unprivileged; a minimal VM/container image where `ip_set` and `ip_set_hash_net` are not modules-loaded; a generated ruleset name longer than 31 chars or containing characters ipset rejects; ipset namespace support disabled on old kernels.","commonSituations":"Distroless/minimal containers without kmod auto-load and no `modprobe ip_set_hash_net` in the entrypoint; running the binary via a non-root systemd unit; NAT-mode kernels with ipset compiled out; long auto-generated ipset names exceeding the 31-char ipset limit.","solutions":["Ensure the agent runs as root or with CAP_NET_ADMIN+CAP_NET_MODULE.","Pre-load the modules: `modprobe ip_set ip_set_hash_net` (or package them in the image).","Shorten/validate generated ipset names to <=31 chars before calling AddPeerFiltering.","If ipset support is genuinely unavailable, force the non-ipset code path (the manager already probes support via probeIPSetSupport; check why the probe passed but Create failed, e.g. modules unloaded after startup)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"func checkIPSetPrereqs() error {\n    if os.Geteuid() != 0 {\n        return errors.New(\"ipset CREATE requires root\")\n    }\n    if _, err := os.Stat(\"/proc/net/ipset\"); err != nil {\n        return errors.New(\"ipset kernel support missing (modprobe ip_set)\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := mgr.AddPeerFiltering(...); err != nil {\n    if strings.Contains(err.Error(), \"create ipset\") {\n        // inspect inner netlink error: EPERM -> privileges, ENOENT-ish -> modules\n        log.Errorf(\"ipset creation failed; check root and ip_set_hash_net module: %v\", err)\n        return // or fall back to a ruleset without ipset\n    }\n}","preventionTips":["Pre-load ip_set and ip_set_hash_net at image build time (`modprobe` in the entrypoint or baked into the kernel config).","Keep generated ipset names within the 31-character ipset limit.","Grant the daemon CAP_NET_ADMIN and CAP_NET_MODULE in container security contexts.","Monitor probeIPSetSupport's outcome at startup so the non-ipset fallback is chosen when support is absent."],"tags":["go","linux","ipset","netlink","firewall","permissions","netbird"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}