TUN-4699: Make quick tunnels the default in cloudflared
This commit is contained in:
parent
bd8af7d80d
commit
18992efa0c
|
@ -206,7 +206,7 @@ func runAdhocNamedTunnel(sc *subcommandContext, name, credentialsOutputPath stri
|
||||||
|
|
||||||
// runClassicTunnel creates a "classic" non-named tunnel
|
// runClassicTunnel creates a "classic" non-named tunnel
|
||||||
func runClassicTunnel(sc *subcommandContext) error {
|
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) {
|
func routeFromFlag(c *cli.Context) (route tunnelstore.Route, ok bool) {
|
||||||
|
@ -225,7 +225,6 @@ func StartServer(
|
||||||
namedTunnel *connection.NamedTunnelConfig,
|
namedTunnel *connection.NamedTunnelConfig,
|
||||||
log *zerolog.Logger,
|
log *zerolog.Logger,
|
||||||
isUIEnabled bool,
|
isUIEnabled bool,
|
||||||
quickTunnelHostname string,
|
|
||||||
) error {
|
) error {
|
||||||
_ = raven.SetDSN(sentryDSN)
|
_ = raven.SetDSN(sentryDSN)
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
@ -325,6 +324,15 @@ func StartServer(
|
||||||
|
|
||||||
observer := connection.NewObserver(log, logTransport, isUIEnabled)
|
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)
|
tunnelConfig, ingressRules, err := prepareTunnelConfig(c, buildInfo, version, log, logTransport, observer, namedTunnel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Couldn't start tunnel")
|
log.Err(err).Msg("Couldn't start tunnel")
|
||||||
|
@ -342,7 +350,7 @@ func StartServer(
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
readinessServer := metrics.NewReadyServer(log)
|
readinessServer := metrics.NewReadyServer(log)
|
||||||
observer.RegisterSink(readinessServer)
|
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 {
|
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{
|
altsrc.NewStringFlag(&cli.StringFlag{
|
||||||
Name: "quick-service",
|
Name: "quick-service",
|
||||||
Usage: "URL for a service which manages unauthenticated 'quick' tunnels.",
|
Usage: "URL for a service which manages unauthenticated 'quick' tunnels.",
|
||||||
|
Value: "https://api.trycloudflare.com",
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
}),
|
}),
|
||||||
selectProtocolFlag,
|
selectProtocolFlag,
|
||||||
|
|
|
@ -161,7 +161,7 @@ func prepareTunnelConfig(
|
||||||
log.Err(err).Str(LogFieldHostname, configHostname).Msg("Invalid hostname")
|
log.Err(err).Str(LogFieldHostname, configHostname).Msg("Invalid hostname")
|
||||||
return nil, ingress.Ingress{}, errors.Wrap(err, "Invalid hostname")
|
return nil, ingress.Ingress{}, errors.Wrap(err, "Invalid hostname")
|
||||||
}
|
}
|
||||||
isFreeTunnel := hostname == ""
|
isQuickTunnel := hostname == ""
|
||||||
clientID := c.String("id")
|
clientID := c.String("id")
|
||||||
if !c.IsSet("id") {
|
if !c.IsSet("id") {
|
||||||
clientID, err = generateRandomClientID(log)
|
clientID, err = generateRandomClientID(log)
|
||||||
|
@ -179,7 +179,7 @@ func prepareTunnelConfig(
|
||||||
tags = append(tags, tunnelpogs.Tag{Name: "ID", Value: clientID})
|
tags = append(tags, tunnelpogs.Tag{Name: "ID", Value: clientID})
|
||||||
|
|
||||||
var originCert []byte
|
var originCert []byte
|
||||||
if !isFreeTunnel {
|
if !isQuickTunnel {
|
||||||
originCertPath := c.String("origincert")
|
originCertPath := c.String("origincert")
|
||||||
originCertLog := log.With().
|
originCertLog := log.With().
|
||||||
Str(LogFieldOriginCertPath, originCertPath).
|
Str(LogFieldOriginCertPath, originCertPath).
|
||||||
|
@ -278,7 +278,6 @@ func prepareTunnelConfig(
|
||||||
HAConnections: c.Int("ha-connections"),
|
HAConnections: c.Int("ha-connections"),
|
||||||
IncidentLookup: origin.NewIncidentLookup(),
|
IncidentLookup: origin.NewIncidentLookup(),
|
||||||
IsAutoupdated: c.Bool("is-autoupdated"),
|
IsAutoupdated: c.Bool("is-autoupdated"),
|
||||||
IsFreeTunnel: isFreeTunnel,
|
|
||||||
LBPool: c.String("lb-pool"),
|
LBPool: c.String("lb-pool"),
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
Log: log,
|
Log: log,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
@ -51,7 +52,7 @@ func RunQuickTunnel(sc *subcommandContext) error {
|
||||||
TunnelName: data.Result.Name,
|
TunnelName: data.Result.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, line := range connection.AsciiBox([]string{
|
for _, line := range AsciiBox([]string{
|
||||||
"Your Quick Tunnel has been created! Visit it at:",
|
"Your Quick Tunnel has been created! Visit it at:",
|
||||||
data.Result.Hostname,
|
data.Result.Hostname,
|
||||||
}, 2) {
|
}, 2) {
|
||||||
|
@ -61,10 +62,9 @@ func RunQuickTunnel(sc *subcommandContext) error {
|
||||||
return StartServer(
|
return StartServer(
|
||||||
sc.c,
|
sc.c,
|
||||||
version,
|
version,
|
||||||
&connection.NamedTunnelConfig{Credentials: credentials},
|
&connection.NamedTunnelConfig{Credentials: credentials, QuickTunnelUrl: data.Result.Hostname},
|
||||||
sc.log,
|
sc.log,
|
||||||
sc.isUIEnabled,
|
sc.isUIEnabled,
|
||||||
data.Result.Hostname,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,3 +86,26 @@ type QuickTunnel struct {
|
||||||
AccountTag string `json:"account_tag"`
|
AccountTag string `json:"account_tag"`
|
||||||
Secret []byte `json:"secret"`
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -286,7 +286,6 @@ func (sc *subcommandContext) run(tunnelID uuid.UUID) error {
|
||||||
&connection.NamedTunnelConfig{Credentials: credentials},
|
&connection.NamedTunnelConfig{Credentials: credentials},
|
||||||
sc.log,
|
sc.log,
|
||||||
sc.isUIEnabled,
|
sc.isUIEnabled,
|
||||||
"",
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,13 @@ class TestReconnect:
|
||||||
# Repeat the test multiple times because some issues only occur after multiple reconnects
|
# Repeat the test multiple times because some issues only occur after multiple reconnects
|
||||||
self.assert_reconnect(config, cloudflared, 5)
|
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):
|
def test_classic_reconnect(self, tmp_path, component_tests_config):
|
||||||
extra_config = copy.copy(self.extra_config)
|
extra_config = copy.copy(self.extra_config)
|
||||||
extra_config["hello-world"] = True
|
extra_config["hello-world"] = True
|
||||||
config = component_tests_config(
|
config = component_tests_config(
|
||||||
additional_config=extra_config, named_tunnel=False)
|
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)
|
self.assert_reconnect(config, cloudflared, 1)
|
||||||
|
|
||||||
def send_reconnect(self, cloudflared, secs):
|
def send_reconnect(self, cloudflared, secs):
|
||||||
|
|
|
@ -31,6 +31,7 @@ type Config struct {
|
||||||
type NamedTunnelConfig struct {
|
type NamedTunnelConfig struct {
|
||||||
Credentials Credentials
|
Credentials Credentials
|
||||||
Client pogs.ClientInfo
|
Client pogs.ClientInfo
|
||||||
|
QuickTunnelUrl string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Credentials are stored in the credentials file and contain all info needed to run a tunnel.
|
// 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
|
UseReconnectToken bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClassicTunnelConfig) IsTrialZone() bool {
|
|
||||||
return c.Hostname == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type indicates the connection type of the connection.
|
// Type indicates the connection type of the connection.
|
||||||
type Type int
|
type Type int
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ const (
|
||||||
Connected
|
Connected
|
||||||
// Reconnecting means the connection to the edge is being re-established.
|
// Reconnecting means the connection to the edge is being re-established.
|
||||||
Reconnecting
|
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
|
SetURL
|
||||||
// RegisteringTunnel means the non-named tunnel is registering its connection.
|
// RegisteringTunnel means the non-named tunnel is registering its connection.
|
||||||
RegisteringTunnel
|
RegisteringTunnel
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
package connection
|
package connection
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -54,53 +48,6 @@ func (o *Observer) logServerInfo(connIndex uint8, location, msg string) {
|
||||||
o.metrics.registerServerLocation(uint8ToString(connIndex), location)
|
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) {
|
func (o *Observer) sendRegisteringEvent(connIndex uint8) {
|
||||||
o.sendEvent(Event{Index: connIndex, EventType: RegisteringTunnel})
|
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})
|
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})
|
o.sendEvent(Event{EventType: SetURL, URL: url})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,8 +159,6 @@ func (h *h2muxConnection) registerTunnel(ctx context.Context, credentialSetter C
|
||||||
return h.processRegisterTunnelError(registrationErr, register)
|
return h.processRegisterTunnelError(registrationErr, register)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send free tunnel URL to UI
|
|
||||||
h.observer.sendURL(registration.Url)
|
|
||||||
credentialSetter.SetEventDigest(h.connIndex, registration.EventDigest)
|
credentialSetter.SetEventDigest(h.connIndex, registration.EventDigest)
|
||||||
return h.processRegistrationSuccess(registration, register, credentialSetter, classicTunnel)
|
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())
|
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)
|
credentialManager.SetConnDigest(h.connIndex, registration.ConnDigest)
|
||||||
h.observer.metrics.userHostnamesCounts.WithLabelValues(registration.Url).Inc()
|
h.observer.metrics.userHostnamesCounts.WithLabelValues(registration.Url).Inc()
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,6 @@ func (rs *ReadyServer) OnTunnelEvent(c conn.Event) {
|
||||||
rs.Lock()
|
rs.Lock()
|
||||||
rs.isConnected[int(c.Index)] = false
|
rs.isConnected[int(c.Index)] = false
|
||||||
rs.Unlock()
|
rs.Unlock()
|
||||||
case conn.SetURL:
|
|
||||||
break
|
|
||||||
default:
|
default:
|
||||||
rs.log.Error().Msgf("Unknown connection event case %v", c)
|
rs.log.Error().Msgf("Unknown connection event case %v", c)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,6 @@ type TunnelConfig struct {
|
||||||
HAConnections int
|
HAConnections int
|
||||||
IncidentLookup IncidentLookup
|
IncidentLookup IncidentLookup
|
||||||
IsAutoupdated bool
|
IsAutoupdated bool
|
||||||
IsFreeTunnel bool
|
|
||||||
LBPool string
|
LBPool string
|
||||||
Tags []tunnelpogs.Tag
|
Tags []tunnelpogs.Tag
|
||||||
Log *zerolog.Logger
|
Log *zerolog.Logger
|
||||||
|
|
Loading…
Reference in New Issue