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
- Check the agent log for the sibling 'add mangle postrouting rule' entry to see the full multierror
- Manually run: `iptables -t mangle -A PREROUTING -i wt0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 0x...`
- `modprobe iptable_mangle xt_conntrack xt_connmark` (ip6table_mangle for IPv6)
- Confirm the NetBird service runs as root (`systemctl show netbird -p User`)
- 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
- Load xt_conntrack and xt_connmark on routed peers
- Monitor agent logs for 'failed to set up data plane mark' after upgrades
- Test mangle programmability in your base image CI (`iptables -t mangle -L`)
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
- add mangle postrouting rule: %w
- remove mangle prerouting rule: %w
- remove mangle postrouting rule: %w
- add jump to MSS clamp chain: %w
- failed to insert established rule: %v
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/b280800916f88394.
Report an issue: GitHub.