TUN-4521: Modify cloudflared to use zoneless-tunnels-worker for free tunnels

This commit is contained in:
Rishabh Bector 2021-06-21 19:31:24 -05:00 committed by Nuno Diegues
parent 8d99e92852
commit 3eb9efd9f0
3 changed files with 101 additions and 3 deletions

View File

@ -163,6 +163,12 @@ func TunnelCommand(c *cli.Context) error {
return fmt.Errorf("Use `cloudflared tunnel run` to start tunnel %s", ref)
}
// Unauthenticated named tunnel on <random>.<quick-tunnels-service>.com
// For now, default to legacy setup unless quick-service is specified
if c.String("hostname") == "" && c.String("quick-service") != "" {
return RunQuickTunnel(sc)
}
// Start a classic tunnel
return runClassicTunnel(sc)
}
@ -616,6 +622,11 @@ func tunnelFlags(shouldHide bool) []cli.Flag {
Value: false,
Hidden: shouldHide,
}),
altsrc.NewStringFlag(&cli.StringFlag{
Name: "quick-service",
Usage: "URL for a service which manages unauthenticated 'quick' tunnels.",
Hidden: true,
}),
selectProtocolFlag,
overwriteDNSFlag,
}...)

View File

@ -0,0 +1,87 @@
package tunnel
import (
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/cloudflare/cloudflared/connection"
)
const httpTimeout = 15 * time.Second
// 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...")
client := http.Client{
Transport: &http.Transport{
TLSHandshakeTimeout: httpTimeout,
ResponseHeaderTimeout: httpTimeout,
},
Timeout: httpTimeout,
}
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")
}
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")
}
tunnelID, err := uuid.Parse(data.Result.ID)
if err != nil {
return errors.Wrap(err, "failed to parse quick tunnel ID")
}
credentials := connection.Credentials{
AccountTag: data.Result.AccountTag,
TunnelSecret: data.Result.Secret,
TunnelID: tunnelID,
TunnelName: data.Result.Name,
}
for _, line := range connection.AsciiBox([]string{
"Your Quick Tunnel has been created! Visit it at:",
data.Result.Hostname,
}, 2) {
sc.log.Info().Msg(line)
}
return StartServer(
sc.c,
version,
&connection.NamedTunnelConfig{Credentials: credentials},
sc.log,
sc.isUIEnabled,
)
}
type QuickTunnelResponse struct {
Success bool
Result QuickTunnel
Errors []QuickTunnelError
}
type QuickTunnelError struct {
Code int
Message string
}
type QuickTunnel struct {
ID string `json:"id"`
Name string `json:"name"`
Hostname string `json:"hostname"`
AccountTag string `json:"account_tag"`
Secret []byte `json:"secret"`
}

View File

@ -58,7 +58,7 @@ func (o *Observer) logTrialHostname(registration *tunnelpogs.TunnelRegistration)
// 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) {
for _, line := range AsciiBox(TrialZoneMsg(registrationURL.String()), 2) {
o.log.Info().Msg(line)
}
} else {
@ -70,7 +70,7 @@ func (o *Observer) logTrialHostname(registration *tunnelpogs.TunnelRegistration)
}
// Print out the given lines in a nice ASCII box.
func asciiBox(lines []string, padding int) (box []string) {
func AsciiBox(lines []string, padding int) (box []string) {
maxLen := maxLen(lines)
spacer := strings.Repeat(" ", padding)
@ -94,7 +94,7 @@ func maxLen(lines []string) int {
return max
}
func trialZoneMsg(url string) []string {
func TrialZoneMsg(url string) []string {
return []string{
"Your free tunnel has started! Visit it:",
" " + url,