From 18992efa0ce5768414de39f851e9a4478431e5e3 Mon Sep 17 00:00:00 2001 From: Rishabh Bector Date: Fri, 9 Jul 2021 12:52:41 -0500 Subject: [PATCH] TUN-4699: Make quick tunnels the default in cloudflared --- cmd/cloudflared/tunnel/cmd.go | 15 ++++-- cmd/cloudflared/tunnel/configuration.go | 5 +- cmd/cloudflared/tunnel/quick_tunnel.go | 29 +++++++++-- cmd/cloudflared/tunnel/subcommand_context.go | 1 - component-tests/test_reconnect.py | 3 +- connection/connection.go | 9 ++-- connection/event.go | 2 +- connection/observer.go | 55 +------------------- connection/rpc.go | 10 ---- metrics/readiness.go | 2 - origin/tunnel.go | 1 - 11 files changed, 47 insertions(+), 85 deletions(-) diff --git a/cmd/cloudflared/tunnel/cmd.go b/cmd/cloudflared/tunnel/cmd.go index c98d5ae4..44f7f198 100644 --- a/cmd/cloudflared/tunnel/cmd.go +++ b/cmd/cloudflared/tunnel/cmd.go @@ -206,7 +206,7 @@ func runAdhocNamedTunnel(sc *subcommandContext, name, credentialsOutputPath stri // runClassicTunnel creates a "classic" non-named tunnel func runClassicTunnel(sc *subcommandContext) error { - return StartServer(sc.c, version, nil, sc.log, sc.isUIEnabled, "") + return StartServer(sc.c, version, nil, sc.log, sc.isUIEnabled) } func routeFromFlag(c *cli.Context) (route tunnelstore.Route, ok bool) { @@ -225,7 +225,6 @@ func StartServer( namedTunnel *connection.NamedTunnelConfig, log *zerolog.Logger, isUIEnabled bool, - quickTunnelHostname string, ) error { _ = raven.SetDSN(sentryDSN) var wg sync.WaitGroup @@ -325,6 +324,15 @@ func StartServer( observer := connection.NewObserver(log, logTransport, isUIEnabled) + // Send Quick Tunnel URL to UI if applicable + var quickTunnelURL string + if namedTunnel != nil { + quickTunnelURL = namedTunnel.QuickTunnelUrl + } + if quickTunnelURL != "" { + observer.SendURL(quickTunnelURL) + } + tunnelConfig, ingressRules, err := prepareTunnelConfig(c, buildInfo, version, log, logTransport, observer, namedTunnel) if err != nil { log.Err(err).Msg("Couldn't start tunnel") @@ -342,7 +350,7 @@ func StartServer( defer wg.Done() readinessServer := metrics.NewReadyServer(log) observer.RegisterSink(readinessServer) - errC <- metrics.ServeMetrics(metricsListener, ctx.Done(), readinessServer, quickTunnelHostname, log) + errC <- metrics.ServeMetrics(metricsListener, ctx.Done(), readinessServer, quickTunnelURL, log) }() if err := ingressRules.StartOrigins(&wg, log, ctx.Done(), errC); err != nil { @@ -626,6 +634,7 @@ func tunnelFlags(shouldHide bool) []cli.Flag { altsrc.NewStringFlag(&cli.StringFlag{ Name: "quick-service", Usage: "URL for a service which manages unauthenticated 'quick' tunnels.", + Value: "https://api.trycloudflare.com", Hidden: true, }), selectProtocolFlag, diff --git a/cmd/cloudflared/tunnel/configuration.go b/cmd/cloudflared/tunnel/configuration.go index 5800a721..67e3b86f 100644 --- a/cmd/cloudflared/tunnel/configuration.go +++ b/cmd/cloudflared/tunnel/configuration.go @@ -161,7 +161,7 @@ func prepareTunnelConfig( log.Err(err).Str(LogFieldHostname, configHostname).Msg("Invalid hostname") return nil, ingress.Ingress{}, errors.Wrap(err, "Invalid hostname") } - isFreeTunnel := hostname == "" + isQuickTunnel := hostname == "" clientID := c.String("id") if !c.IsSet("id") { clientID, err = generateRandomClientID(log) @@ -179,7 +179,7 @@ func prepareTunnelConfig( tags = append(tags, tunnelpogs.Tag{Name: "ID", Value: clientID}) var originCert []byte - if !isFreeTunnel { + if !isQuickTunnel { originCertPath := c.String("origincert") originCertLog := log.With(). Str(LogFieldOriginCertPath, originCertPath). @@ -278,7 +278,6 @@ func prepareTunnelConfig( HAConnections: c.Int("ha-connections"), IncidentLookup: origin.NewIncidentLookup(), IsAutoupdated: c.Bool("is-autoupdated"), - IsFreeTunnel: isFreeTunnel, LBPool: c.String("lb-pool"), Tags: tags, Log: log, diff --git a/cmd/cloudflared/tunnel/quick_tunnel.go b/cmd/cloudflared/tunnel/quick_tunnel.go index db76d212..c81a4f32 100644 --- a/cmd/cloudflared/tunnel/quick_tunnel.go +++ b/cmd/cloudflared/tunnel/quick_tunnel.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "strings" "time" "github.com/google/uuid" @@ -51,7 +52,7 @@ func RunQuickTunnel(sc *subcommandContext) error { TunnelName: data.Result.Name, } - for _, line := range connection.AsciiBox([]string{ + for _, line := range AsciiBox([]string{ "Your Quick Tunnel has been created! Visit it at:", data.Result.Hostname, }, 2) { @@ -61,10 +62,9 @@ func RunQuickTunnel(sc *subcommandContext) error { return StartServer( sc.c, version, - &connection.NamedTunnelConfig{Credentials: credentials}, + &connection.NamedTunnelConfig{Credentials: credentials, QuickTunnelUrl: data.Result.Hostname}, sc.log, sc.isUIEnabled, - data.Result.Hostname, ) } @@ -86,3 +86,26 @@ type QuickTunnel struct { AccountTag string `json:"account_tag"` Secret []byte `json:"secret"` } + +// Print out the given lines in a nice ASCII box. +func AsciiBox(lines []string, padding int) (box []string) { + maxLen := maxLen(lines) + spacer := strings.Repeat(" ", padding) + border := "+" + strings.Repeat("-", maxLen+(padding*2)) + "+" + box = append(box, border) + for _, line := range lines { + box = append(box, "|"+spacer+line+strings.Repeat(" ", maxLen-len(line))+spacer+"|") + } + box = append(box, border) + return +} + +func maxLen(lines []string) int { + max := 0 + for _, line := range lines { + if len(line) > max { + max = len(line) + } + } + return max +} diff --git a/cmd/cloudflared/tunnel/subcommand_context.go b/cmd/cloudflared/tunnel/subcommand_context.go index 69d16478..d5b42590 100644 --- a/cmd/cloudflared/tunnel/subcommand_context.go +++ b/cmd/cloudflared/tunnel/subcommand_context.go @@ -286,7 +286,6 @@ func (sc *subcommandContext) run(tunnelID uuid.UUID) error { &connection.NamedTunnelConfig{Credentials: credentials}, sc.log, sc.isUIEnabled, - "", ) } diff --git a/component-tests/test_reconnect.py b/component-tests/test_reconnect.py index 15af88ca..78808a67 100644 --- a/component-tests/test_reconnect.py +++ b/component-tests/test_reconnect.py @@ -24,12 +24,13 @@ class TestReconnect: # Repeat the test multiple times because some issues only occur after multiple reconnects self.assert_reconnect(config, cloudflared, 5) + @pytest.mark.skipif(platform.system() == "Windows", reason=f"Currently buggy on Windows TUN-4699") def test_classic_reconnect(self, tmp_path, component_tests_config): extra_config = copy.copy(self.extra_config) extra_config["hello-world"] = True config = component_tests_config( additional_config=extra_config, named_tunnel=False) - with start_cloudflared(tmp_path, config, cfd_args=[], new_process=True, allow_input=True, capture_output=False) as cloudflared: + with start_cloudflared(tmp_path, config, cfd_args=[], new_process=True, allow_input=True, capture_output=True) as cloudflared: self.assert_reconnect(config, cloudflared, 1) def send_reconnect(self, cloudflared, secs): diff --git a/connection/connection.go b/connection/connection.go index e68afb64..dbe5ef1e 100644 --- a/connection/connection.go +++ b/connection/connection.go @@ -29,8 +29,9 @@ type Config struct { } type NamedTunnelConfig struct { - Credentials Credentials - Client pogs.ClientInfo + Credentials Credentials + Client pogs.ClientInfo + QuickTunnelUrl string } // Credentials are stored in the credentials file and contain all info needed to run a tunnel. @@ -55,10 +56,6 @@ type ClassicTunnelConfig struct { UseReconnectToken bool } -func (c *ClassicTunnelConfig) IsTrialZone() bool { - return c.Hostname == "" -} - // Type indicates the connection type of the connection. type Type int diff --git a/connection/event.go b/connection/event.go index 6afde5bb..ab6d0d33 100644 --- a/connection/event.go +++ b/connection/event.go @@ -18,7 +18,7 @@ const ( Connected // Reconnecting means the connection to the edge is being re-established. Reconnecting - // SetURL means this connection's tunnel was given a URL by the edge. Used for free tunnels. + // SetURL means this connection's tunnel was given a URL by the edge. Used for quick tunnels. SetURL // RegisteringTunnel means the non-named tunnel is registering its connection. RegisteringTunnel diff --git a/connection/observer.go b/connection/observer.go index bb0887a5..abf858d4 100644 --- a/connection/observer.go +++ b/connection/observer.go @@ -1,13 +1,7 @@ package connection import ( - "fmt" - "net/url" - "strings" - "github.com/rs/zerolog" - - tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs" ) const ( @@ -54,53 +48,6 @@ func (o *Observer) logServerInfo(connIndex uint8, location, msg string) { o.metrics.registerServerLocation(uint8ToString(connIndex), location) } -func (o *Observer) logTrialHostname(registration *tunnelpogs.TunnelRegistration) error { - // Print out the user's trial zone URL in a nice box (if they requested and got one and UI flag is not set) - if !o.uiEnabled { - if registrationURL, err := url.Parse(registration.Url); err == nil { - for _, line := range AsciiBox(TrialZoneMsg(registrationURL.String()), 2) { - o.log.Info().Msg(line) - } - } else { - o.log.Error().Msg("Failed to connect tunnel, please try again.") - return fmt.Errorf("empty URL in response from Cloudflare edge") - } - } - return nil -} - -// Print out the given lines in a nice ASCII box. -func AsciiBox(lines []string, padding int) (box []string) { - maxLen := maxLen(lines) - spacer := strings.Repeat(" ", padding) - - border := "+" + strings.Repeat("-", maxLen+(padding*2)) + "+" - - box = append(box, border) - for _, line := range lines { - box = append(box, "|"+spacer+line+strings.Repeat(" ", maxLen-len(line))+spacer+"|") - } - box = append(box, border) - return -} - -func maxLen(lines []string) int { - max := 0 - for _, line := range lines { - if len(line) > max { - max = len(line) - } - } - return max -} - -func TrialZoneMsg(url string) []string { - return []string{ - "Your free tunnel has started! Visit it:", - " " + url, - } -} - func (o *Observer) sendRegisteringEvent(connIndex uint8) { o.sendEvent(Event{Index: connIndex, EventType: RegisteringTunnel}) } @@ -109,7 +56,7 @@ func (o *Observer) sendConnectedEvent(connIndex uint8, location string) { o.sendEvent(Event{Index: connIndex, EventType: Connected, Location: location}) } -func (o *Observer) sendURL(url string) { +func (o *Observer) SendURL(url string) { o.sendEvent(Event{EventType: SetURL, URL: url}) } diff --git a/connection/rpc.go b/connection/rpc.go index 7ae55d40..e8eb6f4a 100644 --- a/connection/rpc.go +++ b/connection/rpc.go @@ -159,8 +159,6 @@ func (h *h2muxConnection) registerTunnel(ctx context.Context, credentialSetter C return h.processRegisterTunnelError(registrationErr, register) } - // Send free tunnel URL to UI - h.observer.sendURL(registration.Url) credentialSetter.SetEventDigest(h.connIndex, registration.EventDigest) return h.processRegistrationSuccess(registration, register, credentialSetter, classicTunnel) } @@ -187,14 +185,6 @@ func (h *h2muxConnection) processRegistrationSuccess( h.observer.log.Info().Msgf("Each HA connection's tunnel IDs: %v", h.observer.metrics.tunnelsHA.String()) } - // Print out the user's trial zone URL in a nice box (if they requested and got one and UI flag is not set) - if classicTunnel.IsTrialZone() { - err := h.observer.logTrialHostname(registration) - if err != nil { - return err - } - } - credentialManager.SetConnDigest(h.connIndex, registration.ConnDigest) h.observer.metrics.userHostnamesCounts.WithLabelValues(registration.Url).Inc() diff --git a/metrics/readiness.go b/metrics/readiness.go index 62d9f8f4..030f71cb 100644 --- a/metrics/readiness.go +++ b/metrics/readiness.go @@ -36,8 +36,6 @@ func (rs *ReadyServer) OnTunnelEvent(c conn.Event) { rs.Lock() rs.isConnected[int(c.Index)] = false rs.Unlock() - case conn.SetURL: - break default: rs.log.Error().Msgf("Unknown connection event case %v", c) } diff --git a/origin/tunnel.go b/origin/tunnel.go index 83a74302..e1aa4a33 100644 --- a/origin/tunnel.go +++ b/origin/tunnel.go @@ -46,7 +46,6 @@ type TunnelConfig struct { HAConnections int IncidentLookup IncidentLookup IsAutoupdated bool - IsFreeTunnel bool LBPool string Tags []tunnelpogs.Tag Log *zerolog.Logger