cloudflare/cloudflared · error

cannot create ICMPv4 proxy: %v nor ICMPv6 proxy: %v

Error message

cannot create ICMPv4 proxy: %v nor ICMPv6 proxy: %v

What it means

NewICMPRouter tries to create both an ICMPv4 and an ICMPv6 proxy. Only if BOTH fail does it return this combined error (and disable the ICMP proxy feature); if one succeeds, the failed family is merely logged and skipped. Both usually fail for the same reason: inability to bind a raw ICMP socket.

Source

Thrown at ingress/origin_icmp_proxy.go:71

	ReplySpan(ctx context.Context, logger *zerolog.Logger) (context.Context, trace.Span)
	ExportSpan()
}

type icmpRouter struct {
	ipv4Proxy *icmpProxy
	ipv4Src   netip.Addr
	ipv6Proxy *icmpProxy
	ipv6Src   netip.Addr
}

// NewICMPRouter doesn't return an error if either ipv4 proxy or ipv6 proxy can be created. The machine might only
// support one of them.
// funnelIdleTimeout controls how long to wait to close a funnel without send/return
func NewICMPRouter(ipv4Addr, ipv6Addr netip.Addr, logger *zerolog.Logger, funnelIdleTimeout time.Duration) (ICMPRouterServer, error) {
	ipv4Proxy, ipv4Err := newICMPProxy(ipv4Addr, logger, funnelIdleTimeout)
	ipv6Proxy, ipv6Err := newICMPProxy(ipv6Addr, logger, funnelIdleTimeout)
	if ipv4Err != nil && ipv6Err != nil {
		err := fmt.Errorf("cannot create ICMPv4 proxy: %v nor ICMPv6 proxy: %v", ipv4Err, ipv6Err)
		logger.Debug().Err(err).Msg("ICMP proxy feature is disabled")
		return nil, err
	}
	if ipv4Err != nil {
		logger.Debug().Err(ipv4Err).Msg("failed to create ICMPv4 proxy, only ICMPv6 proxy is created")
		ipv4Proxy = nil
	}
	if ipv6Err != nil {
		logger.Debug().Err(ipv6Err).Msg("failed to create ICMPv6 proxy, only ICMPv4 proxy is created")
		ipv6Proxy = nil
	}
	return &icmpRouter{
		ipv4Proxy: ipv4Proxy,
		ipv4Src:   ipv4Addr,
		ipv6Proxy: ipv6Proxy,
		ipv6Src:   ipv6Addr,
	}, nil
}

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Run cloudflared with sufficient privileges (root or CAP_NET_RAW capability)
  2. Set the --icmpv4-src / --icmpv6-src host addresses to IPs actually assigned to a local interface
  3. Enable ICMP in the kernel/sysctl if disabled (e.g. in restricted containers)
  4. If only one family fails, treat the debug log as expected degraded behavior — the router still serves the other family

Example fix

// before (unprivileged)
./cloudflared tunnel run NAME
// after
sudo setcap cap_net_raw+ep ./cloudflared
./cloudflared tunnel run NAME
Defensive patterns

Strategy: try-catch

Validate before calling

if !hasCapNetRaw() && runtime.GOOS == "linux" {
	// ICMP proxy will likely fail on both families; skip or elevate first
}

Try / catch

router, err := ingress.NewICMPRouter(ipv4, ipv6, logger, timeout)
if err != nil {
	if strings.Contains(err.Error(), "cannot create ICMPv4 proxy") {
		logger.Warn().Msg("ICMP proxy disabled: need NET_RAW privileges")
		return nil // continue without ICMP
	}
	return err
}

Prevention

When it happens

Trigger: Calling newICMPRouter (or NewICMPRouter directly in tests) on a host where neither an IPv4 nor an IPv6 ICMP proxy can be created — e.g. running without root/CAP_NET_RAW, ICMP disabled via sysctl, or no IPv4/IPv6 addresses configured.

Common situations: Running cloudflared as an unprivileged user or in a container without NET_RAW capability; icmpv4/icmpv6 host addresses not configured on any interface.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/5bf00030453fdfbc. Report an issue: GitHub.