Browse Source

TUN-4821: Make quick tunnels the default in cloudflared

pull/455/head
Rishabh Bector 5 months ago
committed by Nuno Diegues
parent
commit
a4a9f45b0a
  1. 7
      CHANGES.md
  2. 15
      cmd/cloudflared/tunnel/cmd.go
  3. 5
      cmd/cloudflared/tunnel/configuration.go
  4. 44
      cmd/cloudflared/tunnel/quick_tunnel.go
  5. 1
      cmd/cloudflared/tunnel/subcommand_context.go
  6. 9
      connection/connection.go
  7. 2
      connection/event.go
  8. 53
      connection/observer.go
  9. 4
      connection/observer_test.go
  10. 10
      connection/rpc.go
  11. 2
      metrics/readiness.go
  12. 1
      origin/tunnel.go

7
CHANGES.md

@ -1,5 +1,12 @@
**Experimental**: This is a new format for release notes. The format and availability is subject to change.
## 2021.8.4
### Improvements
- Temporary tunnels (those hosted on trycloudflare.com that do not require a Cloudflare login) now run as Named Tunnels
underneath. We recall that these tunnels should not be relied upon for production usage as they come with no guarantee
of uptime. Previous cloudflared versions will soon be unable to run legacy temporary tunnels and will require an update
(to this version or more recent).
## 2021.8.2
### Improvements
- Because Equinox os shutting down, all cloudflared releases are now present [here](https://github.com/cloudflare/cloudflared/releases).

15
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,

5
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).
@ -285,7 +285,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,

44
cmd/cloudflared/tunnel/quick_tunnel.go

@ -15,11 +15,17 @@ import (
const httpTimeout = 15 * time.Second
const disclaimer = "Thank you for trying Cloudflare Tunnel. Doing so, without a Cloudflare account, is a quick way to" +
" experiment and try it out. However, be aware that these account-less Tunnels have no uptime guarantee. If you " +
"intend to use Tunnels in production you should use a pre-created named tunnel by following: " +
"https://developers.cloudflare.com/cloudflare-one/connections/connect-apps"
// RunQuickTunnel requests a tunnel from the specified service.
// We use this to power quick tunnels on trycloudflare.com, but the
// service is open-source and could be used by anyone.
func RunQuickTunnel(sc *subcommandContext) error {
sc.log.Info().Msg("Requesting new Quick Tunnel...")
sc.log.Info().Msg(disclaimer)
sc.log.Info().Msg("Requesting new quick Tunnel on trycloudflare.com...")
client := http.Client{
Transport: &http.Transport{
@ -31,18 +37,18 @@ func RunQuickTunnel(sc *subcommandContext) error {
resp, err := client.Post(fmt.Sprintf("%s/tunnel", sc.c.String("quick-service")), "application/json", nil)
if err != nil {
return errors.Wrap(err, "failed to request quick tunnel")
return errors.Wrap(err, "failed to request quick Tunnel")
}
defer resp.Body.Close()
var data QuickTunnelResponse
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return errors.Wrap(err, "failed to unmarshal quick tunnel")
return errors.Wrap(err, "failed to unmarshal quick Tunnel")
}
tunnelID, err := uuid.Parse(data.Result.ID)
if err != nil {
return errors.Wrap(err, "failed to parse quick tunnel ID")
return errors.Wrap(err, "failed to parse quick Tunnel ID")
}
credentials := connection.Credentials{
@ -57,8 +63,8 @@ func RunQuickTunnel(sc *subcommandContext) error {
url = "https://" + url
}
for _, line := range connection.AsciiBox([]string{
"Your Quick Tunnel has been created! Visit it at:",
for _, line := range AsciiBox([]string{
"Your quick Tunnel has been created! Visit it at (it may take some time to be reachable):",
url,
}, 2) {
sc.log.Info().Msg(line)
@ -67,10 +73,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,
)
}
@ -92,3 +97,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
}

1
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,
"",
)
}

9
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

2
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

53
connection/observer.go

@ -1,13 +1,9 @@
package connection
import (
"fmt"
"net/url"
"strings"
"github.com/rs/zerolog"
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
)
const (
@ -54,53 +50,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 +58,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})
if !strings.HasPrefix(url, "https://") {

4
connection/observer_test.go

@ -14,10 +14,10 @@ import (
func TestSendUrl(t *testing.T) {
observer := NewObserver(&log, &log, false)
observer.sendURL("my-url.com")
observer.SendURL("my-url.com")
assert.Equal(t, 1.0, getCounterValue(t, observer.metrics.userHostnamesCounts, "https://my-url.com"))
observer.sendURL("https://another-long-one.com")
observer.SendURL("https://another-long-one.com")
assert.Equal(t, 1.0, getCounterValue(t, observer.metrics.userHostnamesCounts, "https://another-long-one.com"))
}

10
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()

2
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)
}

1
origin/tunnel.go

@ -48,7 +48,6 @@ type TunnelConfig struct {
HAConnections int
IncidentLookup IncidentLookup
IsAutoupdated bool
IsFreeTunnel bool
LBPool string
Tags []tunnelpogs.Tag
Log *zerolog.Logger

Loading…
Cancel
Save