netbirdio/netbird · error

add mangle prerouting rule: %w

Error message

add mangle prerouting rule: %w

What it means

One half of setupDataPlaneMark(): the agent appends a CONNMARK rule to mangle PREROUTING that stamps incoming NEW connections on the NetBird interface with nbnet.DataPlaneMarkIn. go-iptables AppendUnique() fails when the iptables invocation errors (it is not a duplicate-rule error, duplicates are tolerated), and the error is accumulated into a multierror that init() only logs, so the agent keeps running but without inbound data-plane marks.

Source

Thrown at client/firewall/iptables/router_linux.go:495

	if err := r.addMSSClampingRules(); err != nil {
		log.Errorf("failed to add MSS clamping rules: %s", err)
	}

	return nil
}

// setupDataPlaneMark configures the fwmark for the data plane
func (r *router) setupDataPlaneMark() error {
	var merr *multierror.Error
	preRule := []string{
		"-i", r.wgIface.Name(),
		"-m", "conntrack", "--ctstate", "NEW",
		"-j", "CONNMARK", "--set-mark", fmt.Sprintf("%#x", nbnet.DataPlaneMarkIn),
	}

	if err := r.iptablesClient.AppendUnique(tableMangle, chainPREROUTING, preRule...); err != nil {
		merr = multierror.Append(merr, fmt.Errorf("add mangle prerouting rule: %w", err))
	} else {
		r.rules[markManglePre] = preRule
	}

	postRule := []string{
		"-o", r.wgIface.Name(),
		"-m", "conntrack", "--ctstate", "NEW",
		"-j", "CONNMARK", "--set-mark", fmt.Sprintf("%#x", nbnet.DataPlaneMarkOut),
	}

	if err := r.iptablesClient.AppendUnique(tableMangle, chainPOSTROUTING, postRule...); err != nil {
		merr = multierror.Append(merr, fmt.Errorf("add mangle postrouting rule: %w", err))
	} else {
		r.rules[markManglePost] = postRule
	}

	return nberrors.FormatErrorOrNil(merr)
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Check the agent log for the sibling 'add mangle postrouting rule' entry to see the full multierror
  2. Manually run: `iptables -t mangle -A PREROUTING -i wt0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 0x...`
  3. `modprobe iptable_mangle xt_conntrack xt_connmark` (ip6table_mangle for IPv6)
  4. Confirm the NetBird service runs as root (`systemctl show netbird -p User`)
  5. Restart the agent after freeing the xtables lock so init() retries the mark setup

Example fix

// before
if err := r.iptablesClient.AppendUnique(tableMangle, chainPREROUTING, preRule...); err != nil {
    merr = multierror.Append(merr, fmt.Errorf("add mangle prerouting rule: %w", err))
}

// after: distinguish 'already there' (benign) from real failure
exists, xerr := r.iptablesClient.Exists(tableMangle, chainPREROUTING, preRule...)
if xerr == nil && exists {
    r.rules[markManglePre] = preRule
} else if err := r.iptablesClient.AppendUnique(tableMangle, chainPREROUTING, preRule...); err != nil {
    merr = multierror.Append(merr, fmt.Errorf("add mangle prerouting rule: %w", err))
}
Defensive patterns

Strategy: try-catch

Validate before calling

func connmarkSupported(ipt *iptables.IPTables) bool {
    probe := []string{"-m", "conntrack", "--ctstate", "NEW", "-j", "CONNMARK", "--set-mark", "0x0"}
    if err := ipt.AppendUnique("mangle", "PREROUTING", probe...); err != nil {
        return false
    }
    _ = ipt.DeleteIfExists("mangle", "PREROUTING", probe...)
    return true
}

Try / catch

Accumulate both mangle errors in the existing multierror, then log a single warning with remediation hints (module list) instead of two bare wrapped errors; keep the agent running since marks are an optimization.

Prevention

When it happens

Trigger: AppendUnique("mangle", "PREROUTING", "-i", wgIface, "-m", "conntrack", "--ctstate", "NEW", "-j", "CONNMARK", ...) failing because iptable_mangle, xt_conntrack, or xt_connmark is missing, the process lacks CAP_NET_ADMIN, or the xtables lock is contended. Also fails when the interface name referenced does not exist at rule-programming time.

Common situations: Minimal/container hosts without conntrack helper modules; NetBird running as a non-root service after a permission change; CONNMARK support compiled out of the kernel (rare, custom kernels); concurrent iptables batch updates from other tooling.

Related errors


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