diff --git a/connection/errors.go b/connection/errors.go index 10e3b5d6..17cf58a3 100644 --- a/connection/errors.go +++ b/connection/errors.go @@ -27,6 +27,10 @@ func (e *EdgeQuicDialError) Error() string { return "failed to dial to edge with quic: " + e.Cause.Error() } +func (e *EdgeQuicDialError) Unwrap() error { + return e.Cause +} + // RegisterTunnel error from server type ServerRegisterTunnelError struct { Cause error diff --git a/ingress/origin_icmp_proxy_test.go b/ingress/origin_icmp_proxy_test.go index b38f2cd9..efb7d489 100644 --- a/ingress/origin_icmp_proxy_test.go +++ b/ingress/origin_icmp_proxy_test.go @@ -23,6 +23,10 @@ var ( // TestICMPProxyEcho makes sure we can send ICMP echo via the Request method and receives response via the // ListenResponse method +// +// Note: if this test fails on your device under Linux, then most likely you need to make sure that your user +// is allowed in ping_group_range. See the following gist for how to do that: +// https://github.com/ValentinBELYN/icmplib/blob/main/docs/6-use-icmplib-without-privileges.md func TestICMPProxyEcho(t *testing.T) { onlyDarwinOrLinux(t) const ( diff --git a/supervisor/tunnel.go b/supervisor/tunnel.go index f23eeff7..9b6f0db4 100644 --- a/supervisor/tunnel.go +++ b/supervisor/tunnel.go @@ -317,16 +317,11 @@ func selectNextProtocol( selector connection.ProtocolSelector, cause error, ) bool { - var idleTimeoutError *quic.IdleTimeoutError - isNetworkActivityTimeout := errors.As(cause, &idleTimeoutError) - edgeQuicDialError, ok := cause.(*connection.EdgeQuicDialError) - if !isNetworkActivityTimeout && ok { - isNetworkActivityTimeout = errors.As(edgeQuicDialError.Cause, &idleTimeoutError) - } + isQuicBroken := isQuicBroken(cause) _, hasFallback := selector.Fallback() - if protocolBackoff.ReachedMaxRetries() || (hasFallback && isNetworkActivityTimeout) { - if isNetworkActivityTimeout { + if protocolBackoff.ReachedMaxRetries() || (hasFallback && isQuicBroken) { + if isQuicBroken { connLog.Warn().Msg("If this log occurs persistently, and cloudflared is unable to connect to " + "Cloudflare Network with `quic` protocol, then most likely your machine/network is getting its egress " + "UDP to port 7844 (or others) blocked or dropped. Make sure to allow egress connectivity as per " + @@ -355,6 +350,20 @@ func selectNextProtocol( return true } +func isQuicBroken(cause error) bool { + var idleTimeoutError *quic.IdleTimeoutError + if errors.As(cause, &idleTimeoutError) { + return true + } + + var transportError *quic.TransportError + if errors.As(cause, &transportError) && strings.Contains(cause.Error(), "operation not permitted") { + return true + } + + return false +} + // ServeTunnel runs a single tunnel connection, returns nil on graceful shutdown, // on error returns a flag indicating if error can be retried func (e *EdgeTunnelServer) serveTunnel(