mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 16:01:05 +00:00
TUN-3462: Refactor cloudflared to separate origin from connection
This commit is contained in:
@@ -2,7 +2,6 @@ package access
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudflare/cloudflared/carrier"
|
||||
@@ -17,16 +16,11 @@ import (
|
||||
|
||||
// StartForwarder starts a client side websocket forward
|
||||
func StartForwarder(forwarder config.Forwarder, shutdown <-chan struct{}, logger logger.Service) error {
|
||||
validURLString, err := validation.ValidateUrl(forwarder.Listener)
|
||||
validURL, err := validation.ValidateUrl(forwarder.Listener)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error validating origin URL")
|
||||
}
|
||||
|
||||
validURL, err := url.Parse(validURLString)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error parsing origin URL")
|
||||
}
|
||||
|
||||
// get the headers from the config file and add to the request
|
||||
headers := make(http.Header)
|
||||
if forwarder.TokenClientID != "" {
|
||||
@@ -106,12 +100,7 @@ func ssh(c *cli.Context) error {
|
||||
wsConn := carrier.NewWSConnection(logger, false)
|
||||
|
||||
if c.NArg() > 0 || c.IsSet(sshURLFlag) {
|
||||
localForwarder, err := config.ValidateUrl(c, true)
|
||||
if err != nil {
|
||||
logger.Errorf("Error validating origin URL: %s", err)
|
||||
return errors.Wrap(err, "error validating origin URL")
|
||||
}
|
||||
forwarder, err := url.Parse(localForwarder)
|
||||
forwarder, err := config.ValidateUrl(c, true)
|
||||
if err != nil {
|
||||
logger.Errorf("Error validating origin URL: %s", err)
|
||||
return errors.Wrap(err, "error validating origin URL")
|
||||
|
@@ -2,6 +2,7 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -189,11 +190,11 @@ func ValidateUnixSocket(c *cli.Context) (string, error) {
|
||||
|
||||
// ValidateUrl will validate url flag correctness. It can be either from --url or argument
|
||||
// Notice ValidateUnixSocket, it will enforce --unix-socket is not used with --url or argument
|
||||
func ValidateUrl(c *cli.Context, allowFromArgs bool) (string, error) {
|
||||
func ValidateUrl(c *cli.Context, allowFromArgs bool) (*url.URL, error) {
|
||||
var url = c.String("url")
|
||||
if allowFromArgs && c.NArg() > 0 {
|
||||
if c.IsSet("url") {
|
||||
return "", errors.New("Specified origin urls using both --url and argument. Decide which one you want, I can only support one.")
|
||||
return nil, errors.New("Specified origin urls using both --url and argument. Decide which one you want, I can only support one.")
|
||||
}
|
||||
url = c.Args().Get(0)
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/ui"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/updater"
|
||||
"github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/dbconnect"
|
||||
"github.com/cloudflare/cloudflared/ingress"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
@@ -247,7 +248,7 @@ func StartServer(
|
||||
version string,
|
||||
shutdownC,
|
||||
graceShutdownC chan struct{},
|
||||
namedTunnel *origin.NamedTunnelConfig,
|
||||
namedTunnel *connection.NamedTunnelConfig,
|
||||
log logger.Service,
|
||||
isUIEnabled bool,
|
||||
) error {
|
||||
@@ -366,7 +367,7 @@ func StartServer(
|
||||
return errors.Wrap(err, "error setting up transport logger")
|
||||
}
|
||||
|
||||
tunnelConfig, err := prepareTunnelConfig(c, buildInfo, version, log, transportLogger, namedTunnel)
|
||||
tunnelConfig, err := prepareTunnelConfig(c, buildInfo, version, log, transportLogger, namedTunnel, isUIEnabled)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -386,10 +387,6 @@ func StartServer(
|
||||
}()
|
||||
|
||||
if isUIEnabled {
|
||||
const tunnelEventChanBufferSize = 16
|
||||
tunnelEventChan := make(chan ui.TunnelEvent, tunnelEventChanBufferSize)
|
||||
tunnelConfig.TunnelEventChan = tunnelEventChan
|
||||
|
||||
tunnelInfo := ui.NewUIModel(
|
||||
version,
|
||||
hostname,
|
||||
@@ -402,7 +399,7 @@ func StartServer(
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tunnelInfo.LaunchUI(ctx, log, logLevels, tunnelEventChan)
|
||||
tunnelInfo.LaunchUI(ctx, log, logLevels, tunnelConfig.TunnelEventChan)
|
||||
}
|
||||
|
||||
return waitToShutdown(&wg, errC, shutdownC, graceShutdownC, c.Duration("grace-period"), log)
|
||||
@@ -986,7 +983,7 @@ func configureLoggingFlags(shouldHide bool) []cli.Flag {
|
||||
altsrc.NewStringFlag(&cli.StringFlag{
|
||||
Name: "transport-loglevel",
|
||||
Aliases: []string{"proto-loglevel"}, // This flag used to be called proto-loglevel
|
||||
Value: "fatal",
|
||||
Value: "info",
|
||||
Usage: "Transport logging level(previously called protocol logging level) {fatal, error, info, debug}",
|
||||
EnvVars: []string{"TUNNEL_PROTO_LOGLEVEL", "TUNNEL_TRANSPORT_LOGLEVEL"},
|
||||
Hidden: shouldHide,
|
||||
|
@@ -9,6 +9,9 @@ import (
|
||||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/buildinfo"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/ui"
|
||||
"github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/h2mux"
|
||||
"github.com/cloudflare/cloudflared/ingress"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/origin"
|
||||
@@ -154,10 +157,10 @@ func prepareTunnelConfig(
|
||||
version string,
|
||||
logger logger.Service,
|
||||
transportLogger logger.Service,
|
||||
namedTunnel *origin.NamedTunnelConfig,
|
||||
namedTunnel *connection.NamedTunnelConfig,
|
||||
uiIsEnabled bool,
|
||||
) (*origin.TunnelConfig, error) {
|
||||
isNamedTunnel := namedTunnel != nil
|
||||
compatibilityMode := !isNamedTunnel
|
||||
|
||||
hostname, err := validation.ValidateHostname(c.String("hostname"))
|
||||
if err != nil {
|
||||
@@ -189,10 +192,11 @@ func prepareTunnelConfig(
|
||||
}
|
||||
}
|
||||
|
||||
tunnelMetrics := origin.NewTunnelMetrics()
|
||||
|
||||
var ingressRules ingress.Ingress
|
||||
if namedTunnel != nil {
|
||||
var (
|
||||
ingressRules ingress.Ingress
|
||||
classicTunnel *connection.ClassicTunnelConfig
|
||||
)
|
||||
if isNamedTunnel {
|
||||
clientUUID, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "can't generate clientUUID")
|
||||
@@ -210,6 +214,13 @@ func prepareTunnelConfig(
|
||||
if !ingressRules.IsEmpty() && c.IsSet("url") {
|
||||
return nil, ingress.ErrURLIncompatibleWithIngress
|
||||
}
|
||||
} else {
|
||||
classicTunnel = &connection.ClassicTunnelConfig{
|
||||
Hostname: hostname,
|
||||
OriginCert: originCert,
|
||||
// turn off use of reconnect token and auth refresh when using named tunnels
|
||||
UseReconnectToken: !isNamedTunnel && c.Bool("use-reconnect-token"),
|
||||
}
|
||||
}
|
||||
|
||||
// Convert single-origin configuration into multi-origin configuration.
|
||||
@@ -220,43 +231,71 @@ func prepareTunnelConfig(
|
||||
}
|
||||
}
|
||||
|
||||
toEdgeTLSConfig, err := tlsconfig.CreateTunnelConfig(c, isNamedTunnel)
|
||||
protocol := determineProtocol(namedTunnel)
|
||||
toEdgeTLSConfig, err := tlsconfig.CreateTunnelConfig(c, protocol.ServerName())
|
||||
if err != nil {
|
||||
logger.Errorf("unable to create TLS config to connect with edge: %s", err)
|
||||
return nil, errors.Wrap(err, "unable to create TLS config to connect with edge")
|
||||
}
|
||||
return &origin.TunnelConfig{
|
||||
BuildInfo: buildInfo,
|
||||
ClientID: clientID,
|
||||
CompressionQuality: c.Uint64("compression-quality"),
|
||||
EdgeAddrs: c.StringSlice("edge"),
|
||||
GracePeriod: c.Duration("grace-period"),
|
||||
HAConnections: c.Int("ha-connections"),
|
||||
|
||||
proxyConfig := &origin.ProxyConfig{
|
||||
Client: httpTransport,
|
||||
URL: originURL,
|
||||
TLSConfig: httpTransport.TLSClientConfig,
|
||||
HostHeader: c.String("http-host-header"),
|
||||
NoChunkedEncoding: c.Bool("no-chunked-encoding"),
|
||||
Tags: tags,
|
||||
}
|
||||
originClient := origin.NewClient(proxyConfig, logger)
|
||||
transportConfig := &connection.Config{
|
||||
OriginClient: originClient,
|
||||
GracePeriod: c.Duration("grace-period"),
|
||||
ReplaceExisting: c.Bool("force"),
|
||||
}
|
||||
muxerConfig := &connection.MuxerConfig{
|
||||
HeartbeatInterval: c.Duration("heartbeat-interval"),
|
||||
Hostname: hostname,
|
||||
IncidentLookup: origin.NewIncidentLookup(),
|
||||
IsAutoupdated: c.Bool("is-autoupdated"),
|
||||
IsFreeTunnel: isFreeTunnel,
|
||||
LBPool: c.String("lb-pool"),
|
||||
Logger: logger,
|
||||
TransportLogger: transportLogger,
|
||||
MaxHeartbeats: c.Uint64("heartbeat-count"),
|
||||
Metrics: tunnelMetrics,
|
||||
CompressionSetting: h2mux.CompressionSetting(c.Uint64("compression-quality")),
|
||||
MetricsUpdateFreq: c.Duration("metrics-update-freq"),
|
||||
OriginCert: originCert,
|
||||
ReportedVersion: version,
|
||||
Retries: c.Uint("retries"),
|
||||
RunFromTerminal: isRunningFromTerminal(),
|
||||
Tags: tags,
|
||||
TlsConfig: toEdgeTLSConfig,
|
||||
NamedTunnel: namedTunnel,
|
||||
ReplaceExisting: c.Bool("force"),
|
||||
IngressRules: ingressRules,
|
||||
// turn off use of reconnect token and auth refresh when using named tunnels
|
||||
UseReconnectToken: compatibilityMode && c.Bool("use-reconnect-token"),
|
||||
}
|
||||
|
||||
var tunnelEventChan chan ui.TunnelEvent
|
||||
if uiIsEnabled {
|
||||
tunnelEventChan = make(chan ui.TunnelEvent, 16)
|
||||
}
|
||||
|
||||
return &origin.TunnelConfig{
|
||||
ConnectionConfig: transportConfig,
|
||||
ProxyConfig: proxyConfig,
|
||||
BuildInfo: buildInfo,
|
||||
ClientID: clientID,
|
||||
EdgeAddrs: c.StringSlice("edge"),
|
||||
HAConnections: c.Int("ha-connections"),
|
||||
IncidentLookup: origin.NewIncidentLookup(),
|
||||
IsAutoupdated: c.Bool("is-autoupdated"),
|
||||
IsFreeTunnel: isFreeTunnel,
|
||||
LBPool: c.String("lb-pool"),
|
||||
Logger: logger,
|
||||
Observer: connection.NewObserver(transportLogger, tunnelEventChan, protocol),
|
||||
ReportedVersion: version,
|
||||
Retries: c.Uint("retries"),
|
||||
RunFromTerminal: isRunningFromTerminal(),
|
||||
TLSConfig: toEdgeTLSConfig,
|
||||
NamedTunnel: namedTunnel,
|
||||
ClassicTunnel: classicTunnel,
|
||||
MuxerConfig: muxerConfig,
|
||||
TunnelEventChan: tunnelEventChan,
|
||||
IngressRules: ingressRules,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func isRunningFromTerminal() bool {
|
||||
return terminal.IsTerminal(int(os.Stdout.Fd()))
|
||||
}
|
||||
|
||||
func determineProtocol(namedTunnel *connection.NamedTunnelConfig) connection.Protocol {
|
||||
if namedTunnel != nil {
|
||||
return namedTunnel.Protocol
|
||||
}
|
||||
return connection.H2mux
|
||||
}
|
||||
|
@@ -14,8 +14,8 @@ import (
|
||||
|
||||
"github.com/cloudflare/cloudflared/certutil"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/origin"
|
||||
"github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
"github.com/cloudflare/cloudflared/tunnelstore"
|
||||
)
|
||||
@@ -260,7 +260,7 @@ func (sc *subcommandContext) run(tunnelID uuid.UUID) error {
|
||||
return err
|
||||
}
|
||||
|
||||
protocol, ok := origin.ParseProtocol(sc.c.String("protocol"))
|
||||
protocol, ok := connection.ParseProtocol(sc.c.String("protocol"))
|
||||
if !ok {
|
||||
return fmt.Errorf("%s is not valid protocol. %s", sc.c.String("protocol"), availableProtocol)
|
||||
}
|
||||
@@ -269,7 +269,7 @@ func (sc *subcommandContext) run(tunnelID uuid.UUID) error {
|
||||
version,
|
||||
shutdownC,
|
||||
graceShutdownC,
|
||||
&origin.NamedTunnelConfig{Auth: *credentials, ID: tunnelID, Protocol: protocol},
|
||||
&connection.NamedTunnelConfig{Auth: *credentials, ID: tunnelID, Protocol: protocol},
|
||||
sc.logger,
|
||||
sc.isUIEnabled,
|
||||
)
|
||||
|
@@ -78,28 +78,31 @@ var (
|
||||
Name: "credentials-file",
|
||||
Aliases: []string{credFileFlagAlias},
|
||||
Usage: "File path of tunnel credentials",
|
||||
EnvVars: []string{"TUNNEL_CRED_FILE"},
|
||||
})
|
||||
forceDeleteFlag = &cli.BoolFlag{
|
||||
Name: "force",
|
||||
Aliases: []string{"f"},
|
||||
Usage: "Allows you to delete a tunnel, even if it has active connections.",
|
||||
EnvVars: []string{"TUNNEL_RUN_FORCE_OVERWRITE"},
|
||||
}
|
||||
selectProtocolFlag = &cli.StringFlag{
|
||||
Name: "protocol",
|
||||
Value: "h2mux",
|
||||
Aliases: []string{"p"},
|
||||
Usage: fmt.Sprintf("Protocol implementation to connect with Cloudflare's edge network. %s", availableProtocol),
|
||||
EnvVars: []string{"TUNNEL_TRANSPORT_PROTOCOL"},
|
||||
Hidden: true,
|
||||
}
|
||||
)
|
||||
|
||||
func buildCreateCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "create",
|
||||
Action: cliutil.ErrorHandler(createCommand),
|
||||
Usage: "Create a new tunnel with given name",
|
||||
UsageText: "cloudflared tunnel [tunnel command options] create [subcommand options] NAME",
|
||||
Description: `Creates a tunnel, registers it with Cloudflare edge and generates credential file used to run this tunnel.
|
||||
Name: "create",
|
||||
Action: cliutil.ErrorHandler(createCommand),
|
||||
Usage: "Create a new tunnel with given name",
|
||||
UsageText: "cloudflared tunnel [tunnel command options] create [subcommand options] NAME",
|
||||
Description: `Creates a tunnel, registers it with Cloudflare edge and generates credential file used to run this tunnel.
|
||||
Use "cloudflared tunnel route" subcommand to map a DNS name to this tunnel and "cloudflared tunnel run" to start the connection.
|
||||
|
||||
For example, to create a tunnel named 'my-tunnel' run:
|
||||
|
Reference in New Issue
Block a user