netbirdio/netbird · error
add mangle postrouting rule: %w
Error message
add mangle postrouting rule: %w
What it means
Companion of the prerouting error in setupDataPlaneMark(): appends a CONNMARK rule to mangle POSTROUTING stamping outbound NEW connections with nbnet.DataPlaneMarkOut. Failures are accumulated in a multierror and only logged by init(), so a failure leaves the agent running with asymmetric or missing marks, which can degrade policy routing that matches on those fwmarks.
Source
Thrown at client/firewall/iptables/router_linux.go:507
"-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)
}
func (r *router) cleanupDataPlaneMark() error {
var merr *multierror.Error
if preRule, exists := r.rules[markManglePre]; exists {
if err := r.iptablesClient.DeleteIfExists(tableMangle, chainPREROUTING, preRule...); err != nil {
merr = multierror.Append(merr, fmt.Errorf("remove mangle prerouting rule: %w", err))
} else {
delete(r.rules, markManglePre)
}
}
if postRule, exists := r.rules[markManglePost]; exists {View on GitHub (pinned to 93e97f4bf1)
Solutions
- Reproduce manually with `iptables -t mangle -A POSTROUTING -o wt0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 0x...`
- `modprobe iptable_mangle xt_conntrack xt_connmark`
- Verify privileges of the netbird daemon (root or CAP_NET_ADMIN)
- Check the full multierror in the log (both prerouting and postrouting usually fail together, confirming a table/module problem rather than the rule itself)
- Run `netbird down && netbird up` to retry setup once the host issue is fixed
Example fix
// before
if err := r.iptablesClient.AppendUnique(tableMangle, chainPOSTROUTING, postRule...); err != nil {
merr = multierror.Append(merr, fmt.Errorf("add mangle postrouting rule: %w", err))
}
// after: keep bookkeeping only on success, but surface stderr of iptables in context
if err := r.iptablesClient.AppendUnique(tableMangle, chainPOSTROUTING, postRule...); err != nil {
merr = multierror.Append(merr, fmt.Errorf("add mangle postrouting rule (iface %s): %w", r.wgIface.Name(), err))
} else {
r.rules[markManglePost] = postRule
} Defensive patterns
Strategy: try-catch
Validate before calling
func mangleWritable(ipt *iptables.IPTables) error {
probe := []string{"-j", "MARK", "--set-mark", "0x0/0xff00"}
if err := ipt.AppendUnique("mangle", "POSTROUTING", probe...); err != nil {
return err
}
return ipt.DeleteIfExists("mangle", "POSTROUTING", probe...)
} Try / catch
Treat prerouting and postrouting mark failures as one unit: log once, keep going, and re-run setupDataPlaneMark on the next Reset so a transient lock failure self-heals.
Prevention
- Ensure iptable_mangle loads on demand (modules-load.d entry) on minimal hosts
- Avoid running other iptables batch writers concurrently with agent start
- Keep the NetBird interface name stable; do not recreate interfaces while routes are applied
When it happens
Trigger: AppendUnique("mangle", "POSTROUTING", "-o", wgIface, "-m", "conntrack", "--ctstate", "NEW", "-j", "CONNMARK", ...) failing on missing iptable_mangle/xt_connmark/xt_conntrack modules, missing CAP_NET_ADMIN, xtables lock contention, or an interface that disappeared between creation and rule programming.
Common situations: Same class as the prerouting variant: stripped kernels, unprivileged containers, races with other firewall managers during `netbird up`, or hosts where the mangle table exists but connmark helpers were built as unavailable modules.
Related errors
- add mangle prerouting 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/01fc57de8693ceea.
Report an issue: GitHub.