netbirdio/netbird · error

add jump rules: %w

Error message

add jump rules: %w

What it means

Returned when addJumpRules() fails during router container setup. It inserts three jump rules (-j NETBIRD-RT-NAT into nat POSTROUTING, -j NETBIRD-RT-PRE into mangle PREROUTING, -j NETBIRD-RT-RDR into nat PREROUTING) at position 1 of built-in chains via go-iptables Insert(). The first failing insert aborts createContainers(), so traffic never reaches NetBird's custom chains and routing/NAT is dead.

Source

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

		if err := r.iptablesClient.NewChain(chainInfo.table, chainInfo.chain); err != nil {
			return fmt.Errorf("create chain %s in table %s: %w", chainInfo.chain, chainInfo.table, err)
		}
	}

	if err := r.insertEstablishedRule(chainRTFWDIN); err != nil {
		return fmt.Errorf("insert established rule: %w", err)
	}

	if err := r.insertEstablishedRule(chainRTFWDOUT); err != nil {
		return fmt.Errorf("insert established rule: %w", err)
	}

	if err := r.addPostroutingRules(); err != nil {
		return fmt.Errorf("add static nat rules: %w", err)
	}

	if err := r.addJumpRules(); err != nil {
		return fmt.Errorf("add jump rules: %w", err)
	}

	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),
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Run the failing insert manually: `iptables -t mangle -I PREROUTING 1 -j NETBIRD-RT-PRE` and `iptables -t nat -I POSTROUTING 1 -j NETBIRD-RT-NAT` to see stderr
  2. `modprobe iptable_mangle iptable_nat` (plus ip6table_mangle/ip6table_nat for IPv6)
  3. Install iptables (iptables-nft) and ensure the same implementation exists for ip6tables when the peer network is dual-stack
  4. Verify root/CAP_NET_ADMIN: `capsh --print | grep cap_net_admin`
  5. Retry after releasing /run/xtables.lock (stop docker/firewalld temporarily or rerun `netbird up`)

Example fix

// before: single wrapper hides which of the three jump rules failed
if err := r.addJumpRules(); err != nil {
    return fmt.Errorf("add jump rules: %w", err)
}

// after: fail on the first unusable table before mutating built-in chains
for _, t := range []string{"nat", "mangle"} {
    if err := r.iptablesClient.List(t, "PREROUTING"); err != nil {
        return fmt.Errorf("table %s unusable: %w", t, err)
    }
}
if err := r.addJumpRules(); err != nil {
    return fmt.Errorf("add jump rules: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

func jumpTargetsReady(ipt *iptables.IPTables) error {
    for _, c := range []struct{ table, chain string }{
        {"nat", "POSTROUTING"}, {"mangle", "PREROUTING"}, {"nat", "PREROUTING"},
    } {
        if _, err := ipt.List(c.table, c.chain); err != nil {
            return fmt.Errorf("%s/%s not programmable: %w", c.table, c.chain, err)
        }
    }
    return nil
}

Type guard

func isExitCode(err error, code int) bool {
    var ee *exec.ExitError
    return errors.As(err, &ee) && ee.ExitCode() == code
}

Try / catch

Wrap addJumpRules failures as fatal for router init; on error, invoke cleanJumpRules + cleanUpDefaultForwardRules to unwind the earlier inserts before propagating.

Prevention

When it happens

Trigger: router.init() -> addJumpRules() when `iptables -t nat -I POSTROUTING 1 -j NETBIRD-RT-NAT` (or the mangle/nat PREROUTING equivalents) exits non-zero: iptable_mangle module not loaded, nat table absent, CAP_NET_ADMIN missing, xtables.lock contention, or iptables-legacy vs nft family mismatch.

Common situations: Host kernels without iptable_mangle (common in stripped VPS/OpenVZ kernels); agents inside Kubernetes/Docker pods without NET_ADMIN; systems where another tool (Docker, firewalld) rewrites built-in chains concurrently; WSL2 or nftables-only images lacking iptables compat binaries.

Related errors


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