TUN-4521: Modify cloudflared to use zoneless-tunnels-worker for free tunnels
This commit is contained in:
parent
8d99e92852
commit
3eb9efd9f0
|
@ -163,6 +163,12 @@ func TunnelCommand(c *cli.Context) error {
|
||||||
return fmt.Errorf("Use `cloudflared tunnel run` to start tunnel %s", ref)
|
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
|
// Start a classic tunnel
|
||||||
return runClassicTunnel(sc)
|
return runClassicTunnel(sc)
|
||||||
}
|
}
|
||||||
|
@ -616,6 +622,11 @@ func tunnelFlags(shouldHide bool) []cli.Flag {
|
||||||
Value: false,
|
Value: false,
|
||||||
Hidden: shouldHide,
|
Hidden: shouldHide,
|
||||||
}),
|
}),
|
||||||
|
altsrc.NewStringFlag(&cli.StringFlag{
|
||||||
|
Name: "quick-service",
|
||||||
|
Usage: "URL for a service which manages unauthenticated 'quick' tunnels.",
|
||||||
|
Hidden: true,
|
||||||
|
}),
|
||||||
selectProtocolFlag,
|
selectProtocolFlag,
|
||||||
overwriteDNSFlag,
|
overwriteDNSFlag,
|
||||||
}...)
|
}...)
|
||||||
|
|
|
@ -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"`
|
||||||
|
}
|
|
@ -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)
|
// 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 !o.uiEnabled {
|
||||||
if registrationURL, err := url.Parse(registration.Url); err == nil {
|
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)
|
o.log.Info().Msg(line)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,7 +70,7 @@ func (o *Observer) logTrialHostname(registration *tunnelpogs.TunnelRegistration)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print out the given lines in a nice ASCII box.
|
// 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)
|
maxLen := maxLen(lines)
|
||||||
spacer := strings.Repeat(" ", padding)
|
spacer := strings.Repeat(" ", padding)
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ func maxLen(lines []string) int {
|
||||||
return max
|
return max
|
||||||
}
|
}
|
||||||
|
|
||||||
func trialZoneMsg(url string) []string {
|
func TrialZoneMsg(url string) []string {
|
||||||
return []string{
|
return []string{
|
||||||
"Your free tunnel has started! Visit it:",
|
"Your free tunnel has started! Visit it:",
|
||||||
" " + url,
|
" " + url,
|
||||||
|
|
Loading…
Reference in New Issue