Skip to content

Commit ae46af9

Browse files
committed
TUN-7065: Remove classic tunnel creation
1 parent bd04667 commit ae46af9

File tree

9 files changed

+80
-270
lines changed

9 files changed

+80
-270
lines changed

cmd/cloudflared/main.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,6 @@ func action(graceShutdownC chan struct{}) cli.ActionFunc {
155155
if isEmptyInvocation(c) {
156156
return handleServiceMode(c, graceShutdownC)
157157
}
158-
tags := make(map[string]string)
159-
tags["hostname"] = c.String("hostname")
160158
func() {
161159
defer sentry.Recover()
162160
err = tunnel.TunnelCommand(c)

cmd/cloudflared/tunnel/cmd.go

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"github.com/cloudflare/cloudflared/supervisor"
3737
"github.com/cloudflare/cloudflared/tlsconfig"
3838
"github.com/cloudflare/cloudflared/tunneldns"
39+
"github.com/cloudflare/cloudflared/validation"
3940
)
4041

4142
const (
@@ -100,6 +101,7 @@ var (
100101
routeFailMsg = fmt.Sprintf("failed to provision routing, please create it manually via Cloudflare dashboard or UI; "+
101102
"most likely you already have a conflicting record there. You can also rerun this command with --%s to overwrite "+
102103
"any existing DNS records for this hostname.", overwriteDNSFlag)
104+
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/)")
103105
)
104106

105107
func Flags() []cli.Flag {
@@ -176,23 +178,40 @@ func TunnelCommand(c *cli.Context) error {
176178
return err
177179
}
178180

179-
if name := c.String("name"); name != "" { // Start a named tunnel
181+
// Run a adhoc named tunnel
182+
// Allows for the creation, routing (optional), and startup of a tunnel in one command
183+
// --name required
184+
// --url or --hello-world required
185+
// --hostname optional
186+
if name := c.String("name"); name != "" {
187+
hostname, err := validation.ValidateHostname(c.String("hostname"))
188+
if err != nil {
189+
return errors.Wrap(err, "Invalid hostname provided")
190+
}
191+
url := c.String("url")
192+
if url == hostname && url != "" && hostname != "" {
193+
return fmt.Errorf("hostname and url shouldn't match. See --help for more information")
194+
}
195+
180196
return runAdhocNamedTunnel(sc, name, c.String(CredFileFlag))
181197
}
182198

183-
// Unauthenticated named tunnel on <random>.<quick-tunnels-service>.com
199+
// Run a quick tunnel
200+
// A unauthenticated named tunnel hosted on <random>.<quick-tunnels-service>.com
201+
// We don't support running proxy-dns and a quick tunnel at the same time as the same process
184202
shouldRunQuickTunnel := c.IsSet("url") || c.IsSet("hello-world")
185-
if !dnsProxyStandAlone(c, nil) && c.String("hostname") == "" && c.String("quick-service") != "" && shouldRunQuickTunnel {
203+
if !c.IsSet("proxy-dns") && c.String("quick-service") != "" && shouldRunQuickTunnel {
186204
return RunQuickTunnel(sc)
187205
}
188206

207+
// If user provides a config, check to see if they meant to use `tunnel run` instead
189208
if ref := config.GetConfiguration().TunnelID; ref != "" {
190209
return fmt.Errorf("Use `cloudflared tunnel run` to start tunnel %s", ref)
191210
}
192211

193-
// Start a classic tunnel if hostname is specified.
212+
// Classic tunnel usage is no longer supported
194213
if c.String("hostname") != "" {
195-
return runClassicTunnel(sc)
214+
return deprecatedClassicTunnelErr
196215
}
197216

198217
if c.IsSet("proxy-dns") {
@@ -237,11 +256,6 @@ func runAdhocNamedTunnel(sc *subcommandContext, name, credentialsOutputPath stri
237256
return nil
238257
}
239258

240-
// runClassicTunnel creates a "classic" non-named tunnel
241-
func runClassicTunnel(sc *subcommandContext) error {
242-
return StartServer(sc.c, buildInfo, nil, sc.log)
243-
}
244-
245259
func routeFromFlag(c *cli.Context) (route cfapi.HostnameRoute, ok bool) {
246260
if hostname := c.String("hostname"); hostname != "" {
247261
if lbPool := c.String("lb-pool"); lbPool != "" {
@@ -343,21 +357,13 @@ func StartServer(
343357
errC <- autoupdater.Run(ctx)
344358
}()
345359

346-
// Serve DNS proxy stand-alone if no hostname or tag or app is going to run
360+
// Serve DNS proxy stand-alone if no tunnel type (quick, adhoc, named) is going to run
347361
if dnsProxyStandAlone(c, namedTunnel) {
348362
connectedSignal.Notify()
349363
// no grace period, handle SIGINT/SIGTERM immediately
350364
return waitToShutdown(&wg, cancel, errC, graceShutdownC, 0, log)
351365
}
352366

353-
url := c.String("url")
354-
hostname := c.String("hostname")
355-
if url == hostname && url != "" && hostname != "" {
356-
errText := "hostname and url shouldn't match. See --help for more information"
357-
log.Error().Msg(errText)
358-
return fmt.Errorf(errText)
359-
}
360-
361367
logTransport := logger.CreateTransportLoggerFromContext(c, logger.EnableTerminalLog)
362368

363369
observer := connection.NewObserver(log, logTransport)

cmd/cloudflared/tunnel/configuration.go

Lines changed: 51 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import (
3232
"github.com/cloudflare/cloudflared/supervisor"
3333
"github.com/cloudflare/cloudflared/tlsconfig"
3434
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
35-
"github.com/cloudflare/cloudflared/validation"
3635
)
3736

3837
const LogFieldOriginCertPath = "originCertPath"
@@ -43,8 +42,6 @@ var (
4342
serviceUrl = developerPortal + "/reference/service/"
4443
argumentsUrl = developerPortal + "/reference/arguments/"
4544

46-
LogFieldHostname = "hostname"
47-
4845
secretFlags = [2]*altsrc.StringFlag{credentialsContentsFlag, tunnelTokenFlag}
4946
defaultFeatures = []string{supervisor.FeatureAllowRemoteConfig, supervisor.FeatureSerializedHeaders, supervisor.FeatureDatagramV2, supervisor.FeatureQUICSupportEOF}
5047

@@ -127,7 +124,10 @@ func isSecretEnvVar(key string) bool {
127124
}
128125

129126
func dnsProxyStandAlone(c *cli.Context, namedTunnel *connection.NamedTunnelProperties) bool {
130-
return c.IsSet("proxy-dns") && (!c.IsSet("hostname") && !c.IsSet("tag") && !c.IsSet("hello-world") && namedTunnel == nil)
127+
return c.IsSet("proxy-dns") &&
128+
!(c.IsSet("name") || // adhoc-named tunnel
129+
c.IsSet("hello-world") || // quick or named tunnel
130+
namedTunnel != nil) // named tunnel
131131
}
132132

133133
func findOriginCert(originCertPath string, log *zerolog.Logger) (string, error) {
@@ -193,37 +193,19 @@ func prepareTunnelConfig(
193193
observer *connection.Observer,
194194
namedTunnel *connection.NamedTunnelProperties,
195195
) (*supervisor.TunnelConfig, *orchestration.Config, error) {
196-
isNamedTunnel := namedTunnel != nil
197-
198-
configHostname := c.String("hostname")
199-
hostname, err := validation.ValidateHostname(configHostname)
196+
clientID, err := uuid.NewRandom()
200197
if err != nil {
201-
log.Err(err).Str(LogFieldHostname, configHostname).Msg("Invalid hostname")
202-
return nil, nil, errors.Wrap(err, "Invalid hostname")
203-
}
204-
clientID := c.String("id")
205-
if !c.IsSet("id") {
206-
clientID, err = generateRandomClientID(log)
207-
if err != nil {
208-
return nil, nil, err
209-
}
198+
return nil, nil, errors.Wrap(err, "can't generate connector UUID")
210199
}
211-
200+
log.Info().Msgf("Generated Connector ID: %s", clientID)
212201
tags, err := NewTagSliceFromCLI(c.StringSlice("tag"))
213202
if err != nil {
214203
log.Err(err).Msg("Tag parse failure")
215204
return nil, nil, errors.Wrap(err, "Tag parse failure")
216205
}
217-
218-
tags = append(tags, tunnelpogs.Tag{Name: "ID", Value: clientID})
219-
220-
var (
221-
ingressRules ingress.Ingress
222-
classicTunnel *connection.ClassicTunnelProperties
223-
)
206+
tags = append(tags, tunnelpogs.Tag{Name: "ID", Value: clientID.String()})
224207

225208
transportProtocol := c.String("protocol")
226-
227209
needPQ := c.Bool("post-quantum")
228210
if needPQ {
229211
if FipsEnabled {
@@ -238,79 +220,55 @@ func prepareTunnelConfig(
238220

239221
protocolFetcher := edgediscovery.ProtocolPercentage
240222

241-
cfg := config.GetConfiguration()
242-
if isNamedTunnel {
243-
clientUUID, err := uuid.NewRandom()
244-
if err != nil {
245-
return nil, nil, errors.Wrap(err, "can't generate connector UUID")
246-
}
247-
log.Info().Msgf("Generated Connector ID: %s", clientUUID)
248-
features := append(c.StringSlice("features"), defaultFeatures...)
249-
if needPQ {
250-
features = append(features, supervisor.FeaturePostQuantum)
251-
}
252-
if c.IsSet(TunnelTokenFlag) {
253-
if transportProtocol == connection.AutoSelectFlag {
254-
protocolFetcher = func() (edgediscovery.ProtocolPercents, error) {
255-
// If the Tunnel is remotely managed and no protocol is set, we prefer QUIC, but still allow fall-back.
256-
preferQuic := []edgediscovery.ProtocolPercent{
257-
{
258-
Protocol: connection.QUIC.String(),
259-
Percentage: 100,
260-
},
261-
{
262-
Protocol: connection.HTTP2.String(),
263-
Percentage: 100,
264-
},
265-
}
266-
return preferQuic, nil
223+
features := append(c.StringSlice("features"), defaultFeatures...)
224+
if needPQ {
225+
features = append(features, supervisor.FeaturePostQuantum)
226+
}
227+
if c.IsSet(TunnelTokenFlag) {
228+
if transportProtocol == connection.AutoSelectFlag {
229+
protocolFetcher = func() (edgediscovery.ProtocolPercents, error) {
230+
// If the Tunnel is remotely managed and no protocol is set, we prefer QUIC, but still allow fall-back.
231+
preferQuic := []edgediscovery.ProtocolPercent{
232+
{
233+
Protocol: connection.QUIC.String(),
234+
Percentage: 100,
235+
},
236+
{
237+
Protocol: connection.HTTP2.String(),
238+
Percentage: 100,
239+
},
267240
}
241+
return preferQuic, nil
268242
}
269-
log.Info().Msg("Will be fetching remotely managed configuration from Cloudflare API. Defaulting to protocol: quic")
270-
}
271-
namedTunnel.Client = tunnelpogs.ClientInfo{
272-
ClientID: clientUUID[:],
273-
Features: dedup(features),
274-
Version: info.Version(),
275-
Arch: info.OSArch(),
276-
}
277-
ingressRules, err = ingress.ParseIngress(cfg)
278-
if err != nil && err != ingress.ErrNoIngressRules {
279-
return nil, nil, err
280-
}
281-
if !ingressRules.IsEmpty() && c.IsSet("url") {
282-
return nil, nil, ingress.ErrURLIncompatibleWithIngress
283-
}
284-
} else {
285-
286-
originCertPath := c.String("origincert")
287-
originCertLog := log.With().
288-
Str(LogFieldOriginCertPath, originCertPath).
289-
Logger()
290-
291-
originCert, err := getOriginCert(originCertPath, &originCertLog)
292-
if err != nil {
293-
return nil, nil, errors.Wrap(err, "Error getting origin cert")
294-
}
295-
296-
classicTunnel = &connection.ClassicTunnelProperties{
297-
Hostname: hostname,
298-
OriginCert: originCert,
299-
// turn off use of reconnect token and auth refresh when using named tunnels
300-
UseReconnectToken: !isNamedTunnel && c.Bool("use-reconnect-token"),
301243
}
244+
log.Info().Msg("Will be fetching remotely managed configuration from Cloudflare API. Defaulting to protocol: quic")
302245
}
303-
304-
// Convert single-origin configuration into multi-origin configuration.
305-
if ingressRules.IsEmpty() {
306-
ingressRules, err = ingress.NewSingleOrigin(c, !isNamedTunnel)
307-
if err != nil {
308-
return nil, nil, err
246+
namedTunnel.Client = tunnelpogs.ClientInfo{
247+
ClientID: clientID[:],
248+
Features: dedup(features),
249+
Version: info.Version(),
250+
Arch: info.OSArch(),
251+
}
252+
cfg := config.GetConfiguration()
253+
ingressRules, err := ingress.ParseIngress(cfg)
254+
if err != nil && err != ingress.ErrNoIngressRules {
255+
return nil, nil, err
256+
}
257+
if c.IsSet("url") {
258+
// Ingress rules cannot be provided with --url flag
259+
if !ingressRules.IsEmpty() {
260+
return nil, nil, ingress.ErrURLIncompatibleWithIngress
261+
} else {
262+
// Only for quick or adhoc tunnels will we attempt to parse:
263+
// --url, --hello-world, or --unix-socket flag for a tunnel ingress rule
264+
ingressRules, err = ingress.NewSingleOrigin(c, false)
265+
if err != nil {
266+
return nil, nil, err
267+
}
309268
}
310269
}
311270

312-
warpRoutingEnabled := isWarpRoutingEnabled(cfg.WarpRouting, isNamedTunnel)
313-
protocolSelector, err := connection.NewProtocolSelector(transportProtocol, warpRoutingEnabled, namedTunnel, protocolFetcher, supervisor.ResolveTTL, log, c.Bool("post-quantum"))
271+
protocolSelector, err := connection.NewProtocolSelector(transportProtocol, cfg.WarpRouting.Enabled, namedTunnel, protocolFetcher, supervisor.ResolveTTL, log, c.Bool("post-quantum"))
314272
if err != nil {
315273
return nil, nil, err
316274
}
@@ -362,7 +320,7 @@ func prepareTunnelConfig(
362320
GracePeriod: gracePeriod,
363321
ReplaceExisting: c.Bool("force"),
364322
OSArch: info.OSArch(),
365-
ClientID: clientID,
323+
ClientID: clientID.String(),
366324
EdgeAddrs: c.StringSlice("edge"),
367325
Region: c.String("region"),
368326
EdgeIPVersion: edgeIPVersion,
@@ -379,7 +337,6 @@ func prepareTunnelConfig(
379337
Retries: uint(c.Int("retries")),
380338
RunFromTerminal: isRunningFromTerminal(),
381339
NamedTunnel: namedTunnel,
382-
ClassicTunnel: classicTunnel,
383340
MuxerConfig: muxerConfig,
384341
ProtocolSelector: protocolSelector,
385342
EdgeTLSConfigs: edgeTLSConfigs,
@@ -421,10 +378,6 @@ func gracePeriod(c *cli.Context) (time.Duration, error) {
421378
return period, nil
422379
}
423380

424-
func isWarpRoutingEnabled(warpConfig config.WarpRoutingConfig, isNamedTunnel bool) bool {
425-
return warpConfig.Enabled && isNamedTunnel
426-
}
427-
428381
func isRunningFromTerminal() bool {
429382
return terminal.IsTerminal(int(os.Stdout.Fd()))
430383
}

component-tests/test_proxy_dns.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,12 @@ class TestProxyDns:
1212
def test_proxy_dns_with_named_tunnel(self, tmp_path, component_tests_config):
1313
run_test_scenario(tmp_path, component_tests_config, CfdModes.NAMED, run_proxy_dns=True)
1414

15-
def test_proxy_dns_with_classic_tunnel(self, tmp_path, component_tests_config):
16-
run_test_scenario(tmp_path, component_tests_config, CfdModes.CLASSIC, run_proxy_dns=True)
17-
1815
def test_proxy_dns_alone(self, tmp_path, component_tests_config):
1916
run_test_scenario(tmp_path, component_tests_config, CfdModes.PROXY_DNS, run_proxy_dns=True)
2017

2118
def test_named_tunnel_alone(self, tmp_path, component_tests_config):
2219
run_test_scenario(tmp_path, component_tests_config, CfdModes.NAMED, run_proxy_dns=False)
2320

24-
def test_classic_tunnel_alone(self, tmp_path, component_tests_config):
25-
run_test_scenario(tmp_path, component_tests_config, CfdModes.CLASSIC, run_proxy_dns=False)
26-
2721

2822
def run_test_scenario(tmp_path, component_tests_config, cfd_mode, run_proxy_dns):
2923
expect_proxy_dns = run_proxy_dns
@@ -33,10 +27,6 @@ def run_test_scenario(tmp_path, component_tests_config, cfd_mode, run_proxy_dns)
3327
expect_tunnel = True
3428
pre_args = ["tunnel"]
3529
args = ["run"]
36-
elif cfd_mode == CfdModes.CLASSIC:
37-
expect_tunnel = True
38-
pre_args = []
39-
args = []
4030
elif cfd_mode == CfdModes.PROXY_DNS:
4131
expect_proxy_dns = True
4232
pre_args = []

component-tests/test_reconnect.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,6 @@ def test_named_reconnect(self, tmp_path, component_tests_config, protocol):
3333
# Repeat the test multiple times because some issues only occur after multiple reconnects
3434
self.assert_reconnect(config, cloudflared, 5)
3535

36-
def test_classic_reconnect(self, tmp_path, component_tests_config):
37-
extra_config = copy.copy(self.extra_config)
38-
extra_config["hello-world"] = True
39-
config = component_tests_config(additional_config=extra_config, cfd_mode=CfdModes.CLASSIC)
40-
with start_cloudflared(tmp_path, config, cfd_args=[], new_process=True, allow_input=True, capture_output=False) as cloudflared:
41-
self.assert_reconnect(config, cloudflared, 1)
42-
4336
def send_reconnect(self, cloudflared, secs):
4437
# Although it is recommended to use the Popen.communicate method, we cannot
4538
# use it because it blocks on reading stdout and stderr until EOF is reached

0 commit comments

Comments
 (0)