Skip to content

Instantly share code, notes, and snippets.

@CypherpunkSamurai
Created September 15, 2025 11:01
Show Gist options
  • Save CypherpunkSamurai/2ccc0f7d11c3abb73ae509374cbd2d97 to your computer and use it in GitHub Desktop.
Save CypherpunkSamurai/2ccc0f7d11c3abb73ae509374cbd2d97 to your computer and use it in GitHub Desktop.
Minimal Cloudflare Tunnel Example
// tunnelmain.go - Standalone Cloudflare Quick Tunnel Creator
//
// This is a standalone implementation that creates a Cloudflare quick tunnel
// based on the cloudflared codebase. It provides a simplified interface for
// creating quick tunnels without the need for authentication or complex setup.
//
// Usage: tunnelmain <local-url>
// Example: tunnelmain localhost:8000
//
// Features:
// - Creates an authenticated quick tunnel on trycloudflare.com
// - Automatically handles tunnel registration and connection
// - Provides detailed call stack logging for debugging
// - Uses QUIC protocol by default for better performance
// - Supports HTTP/HTTPS local services
//
// Based on the original cloudflared implementation:
// https://github.com/cloudflare/cloudflared
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/urfave/cli/v2"
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
"github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel"
"github.com/cloudflare/cloudflared/connection"
)
const (
httpTimeout = 15 * time.Second
disclaimer = "Thank you for trying Cloudflare Tunnel. Doing so, without a Cloudflare account, is a quick way to experiment and try it out. However, be aware that these account-less Tunnels have no uptime guarantee, are subject to the Cloudflare Online Services Terms of Use (https://www.cloudflare.com/website-terms/), and Cloudflare reserves the right to investigate your use of Tunnels for violations of such terms. If you intend to use Tunnels in production you should use a pre-created named tunnel by following: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps"
)
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"`
}
// Print out the given lines in a nice ASCII box.
func AsciiBox(lines []string, padding int) (box []string) {
// Call stack logging: AsciiBox entry
fmt.Printf("[CALL_STACK] AsciiBox(lines=%v, padding=%d) --> entry\n", lines, padding)
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)
// Call stack logging: AsciiBox exit
fmt.Printf("[CALL_STACK] AsciiBox() <-- returns box with %d lines\n", len(box))
return
}
func maxLen(lines []string) int {
max := 0
for _, line := range lines {
if len(line) > max {
max = len(line)
}
}
return max
}
// RunQuickTunnel requests a tunnel from the specified service.
func RunQuickTunnel(ctx *cli.Context, log *zerolog.Logger, buildInfo *cliutil.BuildInfo) error {
// Call stack logging: RunQuickTunnel entry
fmt.Printf("[CALL_STACK] RunQuickTunnel(ctx=%p, log=%p, buildInfo=%p) --> entry\n", ctx, log, buildInfo)
log.Info().Msg(disclaimer)
log.Info().Msg("Requesting new quick Tunnel on trycloudflare.com...")
client := http.Client{
Transport: &http.Transport{
TLSHandshakeTimeout: httpTimeout,
ResponseHeaderTimeout: httpTimeout,
},
Timeout: httpTimeout,
}
quickServiceURL := ctx.String("quick-service")
if quickServiceURL == "" {
quickServiceURL = "https://api.trycloudflare.com"
}
// Call stack logging: RunQuickTunnel --> http.NewRequest
fmt.Printf("[CALL_STACK] RunQuickTunnel() --> http.NewRequest(POST, %s, nil)\n", fmt.Sprintf("%s/tunnel", quickServiceURL))
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/tunnel", quickServiceURL), nil)
// Call stack logging: RunQuickTunnel <-- http.NewRequest
fmt.Printf("[CALL_STACK] RunQuickTunnel() <-- http.NewRequest returns (req=%p, err=%v)\n", req, err)
if err != nil {
fmt.Printf("[CALL_STACK] RunQuickTunnel() <-- early exit (err=%v)\n", err)
return errors.Wrap(err, "failed to build quick tunnel request")
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("User-Agent", buildInfo.UserAgent())
// Call stack logging: RunQuickTunnel --> client.Do
fmt.Printf("[CALL_STACK] RunQuickTunnel() --> client.Do(req=%p)\n", req)
resp, err := client.Do(req)
// Call stack logging: RunQuickTunnel <-- client.Do
fmt.Printf("[CALL_STACK] RunQuickTunnel() <-- client.Do returns (resp=%p, err=%v)\n", resp, err)
if err != nil {
fmt.Printf("[CALL_STACK] RunQuickTunnel() <-- early exit (err=%v)\n", err)
return errors.Wrap(err, "failed to request quick Tunnel")
}
defer resp.Body.Close()
// This will read the entire response into memory so we can print it in case of error
rsp_body, err := io.ReadAll(resp.Body)
if err != nil {
return errors.Wrap(err, "failed to read quick-tunnel response")
}
// Call stack logging: RunQuickTunnel --> json.Unmarshal
fmt.Printf("[CALL_STACK] RunQuickTunnel() --> json.Unmarshal(rsp_body, &data)\n")
var data QuickTunnelResponse
if err := json.Unmarshal(rsp_body, &data); err != nil {
rsp_string := string(rsp_body)
log.Err(err).Msgf("Error unmarshaling QuickTunnel response: %s", rsp_string)
fmt.Printf("[CALL_STACK] RunQuickTunnel() <-- json.Unmarshal failed (err=%v)\n", err)
return errors.Wrap(err, "failed to unmarshal quick Tunnel")
}
// Call stack logging: RunQuickTunnel <-- json.Unmarshal
fmt.Printf("[CALL_STACK] RunQuickTunnel() <-- json.Unmarshal success (tunnel_id=%s, hostname=%s)\n", data.Result.ID, data.Result.Hostname)
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,
}
url := data.Result.Hostname
if !strings.HasPrefix(url, "https://") {
url = "https://" + url
}
for _, line := range AsciiBox([]string{
"Your quick Tunnel has been created! Visit it at (it may take some time to be reachable):",
url,
}, 2) {
log.Info().Msg(line)
}
// Set default protocol to QUIC for quick tunnels
if !ctx.IsSet("protocol") {
_ = ctx.Set("protocol", "quic")
}
// Override the number of connections used. Quick tunnels shouldn't be used for production usage,
// so, use a single connection instead.
_ = ctx.Set("ha-connections", "1")
// Call stack logging: RunQuickTunnel --> tunnel.StartServer
fmt.Printf("[CALL_STACK] RunQuickTunnel() --> tunnel.StartServer(ctx=%p, buildInfo, &connection.TunnelProperties{...}, log)\n", ctx)
err = tunnel.StartServer(
ctx,
buildInfo,
&connection.TunnelProperties{Credentials: credentials, QuickTunnelUrl: data.Result.Hostname},
log,
)
// Call stack logging: RunQuickTunnel <-- tunnel.StartServer
fmt.Printf("[CALL_STACK] RunQuickTunnel() <-- tunnel.StartServer returns err=%v\n", err)
return err
}
package main
import (
"fmt"
"os"
"strings"
"time"
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
"github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel"
"github.com/cloudflare/cloudflared/logger"
cli "github.com/urfave/cli/v2"
)
func main() {
fmt.Println("Starting Tunnelling...")
// Call stack logging: main() entry
fmt.Printf("[CALL_STACK] main() --> entry point (args=%v)\n", os.Args)
// Create CLI app
app := &cli.App{
Name: "tunnelmain",
Usage: "Standalone Cloudflare Quick Tunnel",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "url",
Usage: "Connect to the local webserver at URL.",
},
&cli.StringFlag{
Name: "loglevel",
Value: "info",
Usage: "Application logging level {debug, info, warn, error, fatal, panic, disabled}",
},
&cli.StringFlag{
Name: "protocol",
Value: "quic",
Usage: "Protocol implementation to connect with Cloudflare's edge network.",
},
&cli.StringFlag{
Name: "ha-connections",
Value: "1",
Usage: "Number of concurrent connections to keep with the edge",
},
&cli.StringFlag{
Name: "quick-service",
Value: "https://api.trycloudflare.com",
Usage: "URL for a service which manages unauthenticated 'quick' tunnels.",
},
&cli.StringFlag{
Name: "metrics",
Value: "localhost:0",
Usage: "Listen address for metrics reporting.",
},
&cli.StringFlag{
Name: "edge-ip-version",
Value: "4",
Usage: "Cloudflare Edge IP address version to connect with. {4, 6, auto}",
},
&cli.StringFlag{
Name: "edge-bind-address",
Value: "",
Usage: "Bind to IP address for outgoing connections to Cloudflare Edge.",
},
&cli.StringFlag{
Name: "region",
Value: "",
Usage: "Cloudflare Edge region to connect to. Omit or set to empty to connect to the global region.",
},
&cli.IntFlag{
Name: "retries",
Value: 5,
Usage: "Maximum number of retries for connection/protocol errors.",
},
&cli.DurationFlag{
Name: "grace-period",
Value: 30 * time.Second,
Usage: "Maximum amount of time that cloudflared waits to shut down if it is still serving requests.",
},
&cli.DurationFlag{
Name: "rpc-timeout",
Value: 30 * time.Second,
Usage: "Maximum time to wait for RPC requests to the edge.",
},
&cli.StringFlag{
Name: "management-hostname",
Value: "management.argotunnel.com",
Usage: "Management hostname to signify incoming management requests",
Hidden: true,
},
},
Action: func(ctx *cli.Context) error {
localURL := ctx.String("url")
if localURL == "" {
if ctx.NArg() == 0 {
fmt.Println("Usage: tunnelmain <local-url> [options]")
fmt.Println("Example: tunnelmain localhost:8000 --loglevel debug")
return cli.ShowAppHelp(ctx)
}
localURL = ctx.Args().Get(0)
}
if !strings.HasPrefix(localURL, "http://") && !strings.HasPrefix(localURL, "https://") {
localURL = "http://" + localURL
}
// Set the URL in context
ctx.Set("url", localURL)
// Create logger
log := logger.CreateLoggerFromContext(ctx, logger.EnableTerminalLog)
// Create build info
buildInfo := cliutil.GetBuildInfo("DEV", "DEV")
// Initialize tunnel module with graceful shutdown channel
graceShutdownC := make(chan struct{})
tunnel.Init(buildInfo, graceShutdownC)
// Call stack logging: main() --> RunQuickTunnel
fmt.Printf("[CALL_STACK] main() --> RunQuickTunnel(ctx=%p, log=%p, buildInfo=%p)\n", ctx, log, buildInfo)
// Run the quick tunnel
if err := RunQuickTunnel(ctx, log, buildInfo); err != nil {
log.Err(err).Msg("Failed to run quick tunnel")
fmt.Printf("[CALL_STACK] main() <-- exit with error (err=%v)\n", err)
return err
}
// Call stack logging: main() exit
fmt.Printf("[CALL_STACK] main() <-- exit\n")
return nil
},
}
// Run the CLI app
if err := app.Run(os.Args); err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment