netbirdio/netbird · error

failed to bind free port for eBPF proxy

Error message

failed to bind free port for eBPF proxy

What it means

Returned by portLookup.searchFreePort when every UDP port in the hardcoded range 3128-3228 (portRangeStart=3128, +100) failed a trial net.ListenPacket("udp", ":port") bind. The eBPF WireGuard proxy needs one free loopback UDP port in this fixed window because the eBPF program is loaded with a specific proxy port that kernel and userspace must agree on. When all 101 candidates are taken, Listen() aborts.

Source

Thrown at client/iface/wgproxy/ebpf/portlookup.go:22

	"fmt"
	"net"
)

var (
	portRangeStart = 3128
	portRangeEnd   = portRangeStart + 100
)

type portLookup struct {
}

func (pl portLookup) searchFreePort() (int, error) {
	for i := portRangeStart; i <= portRangeEnd; i++ {
		if pl.tryToBind(i) == nil {
			return i, nil
		}
	}
	return 0, fmt.Errorf("failed to bind free port for eBPF proxy")
}

func (pl portLookup) tryToBind(port int) error {
	l, err := net.ListenPacket("udp", fmt.Sprintf(":%d", port))
	if err != nil {
		return err
	}
	_ = l.Close()
	return nil
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Find the squatter and stop it: `ss -uapn | awk '$5 ~ /:31[0-9][0-9]|:32[0-2][0-9]/'` or `lsof -i UDP:3128-3228`
  2. Ensure only one agent instance runs: `pgrep -a netbird` and stop the duplicate service/container
  3. Free the range and retry starting the agent (the search is only done once per Listen call, so a restart is required)
  4. If the host legitimately needs those ports, run the agent where the range is free or disable the eBPF path so the userspace UDP proxy is used
Defensive patterns

Strategy: fallback

Validate before calling

// preflight: is the eBPF proxy port window usable?
func proxyRangeFree() bool {
    for p := 3128; p <= 3228; p++ {
        if l, err := net.ListenPacket("udp", fmt.Sprintf(":%d", p)); err == nil {
            _ = l.Close()
            return true
        }
    }
    return false
}

Try / catch

if err := wgProxy.Listen(); err != nil {
    if strings.Contains(err.Error(), "failed to bind free port for eBPF proxy") {
        log.Warn("eBPF proxy port window busy, falling back to userspace UDP proxy")
        wgProxy = udpProxy // run without eBPF acceleration
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: WGEBPFProxy.Listen() calling searchFreePort while another process (most commonly a second NetBird agent instance, or Squid, which defaults to TCP/3128 but other proxies scan this range too) holds every UDP port in 3128-3228, or UDP socket creation is blocked (socket/memory limits, seccomp in a hardened container).

Common situations: Two netbird daemons on one host (system service plus manually launched binary); a caching proxy or test suite squatting the 3128 range; containers with very low UDP buffer/socket limits; SELinux/seccomp denying UDP binds.

Related errors


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