diff --git a/cmd/cloudflared/macos_service.go b/cmd/cloudflared/macos_service.go index 48d066e0..43d36568 100644 --- a/cmd/cloudflared/macos_service.go +++ b/cmd/cloudflared/macos_service.go @@ -6,6 +6,7 @@ import ( "fmt" "os" + homedir "github.com/mitchellh/go-homedir" "github.com/pkg/errors" "github.com/urfave/cli/v2" @@ -17,7 +18,7 @@ const ( launchdIdentifier = "com.cloudflare.cloudflared" ) -func runApp(app *cli.App, graceShutdownC chan struct{}) { +func runApp(app *cli.App, _ chan struct{}) { app.Commands = append(app.Commands, &cli.Command{ Name: "service", Usage: "Manages the cloudflared launch agent", @@ -207,3 +208,15 @@ func uninstallLaunchd(c *cli.Context) error { } return err } + +func userHomeDir() (string, error) { + // This returns the home dir of the executing user using OS-specific method + // for discovering the home dir. It's not recommended to call this function + // when the user has root permission as $HOME depends on what options the user + // use with sudo. + homeDir, err := homedir.Dir() + if err != nil { + return "", errors.Wrap(err, "Cannot determine home directory for the user") + } + return homeDir, nil +} diff --git a/cmd/cloudflared/main.go b/cmd/cloudflared/main.go index b0b93cf8..af357db1 100644 --- a/cmd/cloudflared/main.go +++ b/cmd/cloudflared/main.go @@ -2,14 +2,11 @@ package main import ( "fmt" - "math/rand" "os" "strings" "time" "github.com/getsentry/sentry-go" - homedir "github.com/mitchellh/go-homedir" - "github.com/pkg/errors" "github.com/urfave/cli/v2" "go.uber.org/automaxprocs/maxprocs" @@ -52,10 +49,8 @@ var ( func main() { // FIXME: TUN-8148: Disable QUIC_GO ECN due to bugs in proper detection if supported os.Setenv("QUIC_GO_DISABLE_ECN", "1") - - rand.Seed(time.Now().UnixNano()) metrics.RegisterBuildInfo(BuildType, BuildTime, Version) - maxprocs.Set() + _, _ = maxprocs.Set() bInfo := cliutil.GetBuildInfo(BuildType, Version) // Graceful shutdown channel used by the app. When closed, app must terminate gracefully. @@ -184,18 +179,6 @@ func action(graceShutdownC chan struct{}) cli.ActionFunc { }) } -func userHomeDir() (string, error) { - // This returns the home dir of the executing user using OS-specific method - // for discovering the home dir. It's not recommended to call this function - // when the user has root permission as $HOME depends on what options the user - // use with sudo. - homeDir, err := homedir.Dir() - if err != nil { - return "", errors.Wrap(err, "Cannot determine home directory for the user") - } - return homeDir, nil -} - // In order to keep the amount of noise sent to Sentry low, typical network errors can be filtered out here by a substring match. func captureError(err error) { errorMessage := err.Error() diff --git a/cmd/cloudflared/tunnel/cmd.go b/cmd/cloudflared/tunnel/cmd.go index c8d565f2..3c95cc34 100644 --- a/cmd/cloudflared/tunnel/cmd.go +++ b/cmd/cloudflared/tunnel/cmd.go @@ -126,7 +126,7 @@ var ( routeFailMsg = fmt.Sprintf("failed to provision routing, please create it manually via Cloudflare dashboard or UI; "+ "most likely you already have a conflicting record there. You can also rerun this command with --%s to overwrite "+ "any existing DNS records for this hostname.", overwriteDNSFlag) - deprecatedClassicTunnelErr = fmt.Errorf("Classic tunnels have been deprecated, please use Named Tunnels. (https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-guide/)") + errDeprecatedClassicTunnel = fmt.Errorf("Classic tunnels have been deprecated, please use Named Tunnels. (https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-guide/)") // TODO: TUN-8756 the list below denotes the flags that do not possess any kind of sensitive information // however this approach is not maintainble in the long-term. nonSecretFlagsList = []string{ @@ -326,7 +326,7 @@ func TunnelCommand(c *cli.Context) error { // Classic tunnel usage is no longer supported if c.String("hostname") != "" { - return deprecatedClassicTunnelErr + return errDeprecatedClassicTunnel } if c.IsSet("proxy-dns") { @@ -615,8 +615,10 @@ func waitToShutdown(wg *sync.WaitGroup, log.Debug().Msg("Graceful shutdown signalled") if gracePeriod > 0 { // wait for either grace period or service termination + ticker := time.NewTicker(gracePeriod) + defer ticker.Stop() select { - case <-time.Tick(gracePeriod): + case <-ticker.C: case <-errC: } } @@ -644,7 +646,7 @@ func waitToShutdown(wg *sync.WaitGroup, func notifySystemd(waitForSignal *signal.Signal) { <-waitForSignal.Wait() - daemon.SdNotify(false, "READY=1") + _, _ = daemon.SdNotify(false, "READY=1") } func writePidFile(waitForSignal *signal.Signal, pidPathname string, log *zerolog.Logger) { diff --git a/cmd/cloudflared/tunnel/configuration.go b/cmd/cloudflared/tunnel/configuration.go index c5983273..353eb1be 100644 --- a/cmd/cloudflared/tunnel/configuration.go +++ b/cmd/cloudflared/tunnel/configuration.go @@ -36,24 +36,11 @@ const ( ) var ( - developerPortal = "https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup" - serviceUrl = developerPortal + "/tunnel-guide/local/as-a-service/" - argumentsUrl = developerPortal + "/tunnel-guide/local/local-management/arguments/" - secretFlags = [2]*altsrc.StringFlag{credentialsContentsFlag, tunnelTokenFlag} configFlags = []string{"autoupdate-freq", "no-autoupdate", "retries", "protocol", "loglevel", "transport-loglevel", "origincert", "metrics", "metrics-update-freq", "edge-ip-version", "edge-bind-address"} ) -func generateRandomClientID(log *zerolog.Logger) (string, error) { - u, err := uuid.NewRandom() - if err != nil { - log.Error().Msgf("couldn't create UUID for client ID %s", err) - return "", err - } - return u.String(), nil -} - func logClientOptions(c *cli.Context, log *zerolog.Logger) { flags := make(map[string]interface{}) for _, flag := range c.FlagNames() { @@ -233,13 +220,13 @@ func prepareTunnelConfig( Observer: observer, ReportedVersion: info.Version(), // Note TUN-3758 , we use Int because UInt is not supported with altsrc - Retries: uint(c.Int("retries")), + Retries: uint(c.Int("retries")), // nolint: gosec RunFromTerminal: isRunningFromTerminal(), NamedTunnel: namedTunnel, ProtocolSelector: protocolSelector, EdgeTLSConfigs: edgeTLSConfigs, FeatureSelector: featureSelector, - MaxEdgeAddrRetries: uint8(c.Int("max-edge-addr-retries")), + MaxEdgeAddrRetries: uint8(c.Int("max-edge-addr-retries")), // nolint: gosec RPCTimeout: c.Duration(rpcTimeout), WriteStreamTimeout: c.Duration(writeStreamTimeout), DisableQUICPathMTUDiscovery: c.Bool(quicDisablePathMTUDiscovery), diff --git a/cmd/cloudflared/tunnel/subcommands.go b/cmd/cloudflared/tunnel/subcommands.go index ee26e2ae..7042b6df 100644 --- a/cmd/cloudflared/tunnel/subcommands.go +++ b/cmd/cloudflared/tunnel/subcommands.go @@ -441,7 +441,7 @@ func fmtConnections(connections []cfapi.Connection, showRecentlyDisconnected boo sort.Strings(sortedColos) // Map each colo to its frequency, combine into output string. - var output []string + output := make([]string, 0, len(sortedColos)) for _, coloName := range sortedColos { output = append(output, fmt.Sprintf("%dx%s", numConnsPerColo[coloName], coloName)) } @@ -467,10 +467,15 @@ func readyCommand(c *cli.Context) error { } requestURL := fmt.Sprintf("http://%s/ready", metricsOpts) - res, err := http.Get(requestURL) + req, err := http.NewRequest(http.MethodGet, requestURL, nil) if err != nil { return err } + res, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer res.Body.Close() if res.StatusCode != 200 { body, err := io.ReadAll(res.Body) if err != nil { diff --git a/connection/protocol.go b/connection/protocol.go index 417c8b72..fd53c105 100644 --- a/connection/protocol.go +++ b/connection/protocol.go @@ -14,7 +14,7 @@ import ( const ( AvailableProtocolFlagMessage = "Available protocols: 'auto' - automatically chooses the best protocol over time (the default; and also the recommended one); 'quic' - based on QUIC, relying on UDP egress to Cloudflare edge; 'http2' - using Go's HTTP2 library, relying on TCP egress to Cloudflare edge" // edgeH2muxTLSServerName is the server name to establish h2mux connection with edge (unused, but kept for legacy reference). - edgeH2muxTLSServerName = "cftunnel.com" + _ = "cftunnel.com" // edgeH2TLSServerName is the server name to establish http2 connection with edge edgeH2TLSServerName = "h2.cftunnel.com" // edgeQUICServerName is the server name to establish quic connection with edge. @@ -24,11 +24,9 @@ const ( ResolveTTL = time.Hour ) -var ( - // ProtocolList represents a list of supported protocols for communication with the edge - // in order of precedence for remote percentage fetcher. - ProtocolList = []Protocol{QUIC, HTTP2} -) +// ProtocolList represents a list of supported protocols for communication with the edge +// in order of precedence for remote percentage fetcher. +var ProtocolList = []Protocol{QUIC, HTTP2} type Protocol int64 @@ -58,7 +56,7 @@ func (p Protocol) String() string { case QUIC: return "quic" default: - return fmt.Sprintf("unknown protocol") + return "unknown protocol" } } @@ -246,11 +244,11 @@ func NewProtocolSelector( return newRemoteProtocolSelector(fetchedProtocol, ProtocolList, threshold, protocolFetcher, resolveTTL, log), nil } - return nil, fmt.Errorf("Unknown protocol %s, %s", protocolFlag, AvailableProtocolFlagMessage) + return nil, fmt.Errorf("unknown protocol %s, %s", protocolFlag, AvailableProtocolFlagMessage) } func switchThreshold(accountTag string) int32 { h := fnv.New32a() _, _ = h.Write([]byte(accountTag)) - return int32(h.Sum32() % 100) + return int32(h.Sum32() % 100) // nolint: gosec } diff --git a/connection/quic_connection.go b/connection/quic_connection.go index 87e73ae2..6addfd60 100644 --- a/connection/quic_connection.go +++ b/connection/quic_connection.go @@ -103,9 +103,15 @@ func (q *quicConnection) Serve(ctx context.Context) error { // amount of the grace period, allowing requests to finish before we cancel the context, which will // make cloudflared exit. if err := q.serveControlStream(ctx, controlStream); err == nil { - select { - case <-ctx.Done(): - case <-time.Tick(q.gracePeriod): + if q.gracePeriod > 0 { + // In Go1.23 this can be removed and replaced with time.Ticker + // see https://pkg.go.dev/time#Tick + ticker := time.NewTicker(q.gracePeriod) + defer ticker.Stop() + select { + case <-ctx.Done(): + case <-ticker.C: + } } } cancel() diff --git a/features/features.go b/features/features.go index d1476285..25b5dc8b 100644 --- a/features/features.go +++ b/features/features.go @@ -11,15 +11,13 @@ const ( FeatureDatagramV3 = "support_datagram_v3" ) -var ( - defaultFeatures = []string{ - FeatureAllowRemoteConfig, - FeatureSerializedHeaders, - FeatureDatagramV2, - FeatureQUICSupportEOF, - FeatureManagementLogs, - } -) +var defaultFeatures = []string{ + FeatureAllowRemoteConfig, + FeatureSerializedHeaders, + FeatureDatagramV2, + FeatureQUICSupportEOF, + FeatureManagementLogs, +} // Features set by user provided flags type staticFeatures struct { @@ -47,7 +45,6 @@ const ( // Remove any duplicates from the slice func Dedup(slice []string) []string { - // Convert the slice into a set set := make(map[string]bool, 0) for _, str := range slice {