ngrok

package module
v2.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2026 License: MIT Imports: 26 Imported by: 16

README

ngrok-go

Go Reference Go MIT licensed

ngrok is an API gateway cloud service that forwards to applications running anywhere.

ngrok-go is an open source and idiomatic Go package for embedding ngrok networking directly into your Go applications. If you've used ngrok before, you can think of ngrok-go as the ngrok agent packaged as a Go library.

ngrok-go enables you to serve Go apps on the internet in a single line of code without setting up low-level network primitives like IPs, certificates, load balancers and even ports! Applications using ngrok-go listen on ngrok's global cloud service but, they receive connections using the same interface (net.Listener) that any Go app would expect if it listened on a local port.

For working with the ngrok API, check out the ngrok Go API Client Library.

Installation

Install ngrok-go with go get.

go get golang.ngrok.com/ngrok/v2

Documentation

Quickstart

The following example starts a Go web server that receives traffic from an endpoint on ngrok's cloud service with a randomly-assigned URL. The ngrok URL provided when running this example is accessible by anyone with an internet connection.

You need an ngrok authtoken to run the following example, which you can get from the ngrok dashboard.

Run this example with the following command:

NGROK_AUTHTOKEN=xxxx_xxxx go run examples/http/main.go
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"

	"golang.ngrok.com/ngrok/v2"
)

func main() {
	if err := run(context.Background()); err != nil {
		log.Fatal(err)
	}
}

func run(ctx context.Context) error {
	// ngrok.Listen uses ngrok.DefaultAgent which uses the NGROK_AUTHTOKEN
	// environment variable for auth
	ln, err := ngrok.Listen(ctx)
	if err != nil {
		return err
	}

	log.Println("Endpoint online", ln.URL())

	// Serve HTTP traffic on the ngrok endpoint
	return http.Serve(ln, http.HandlerFunc(handler))
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello from ngrok-go!")
}

Traffic Policy

You can use ngrok's Traffic Policy engine to apply API Gateway behaviors at ngrok's cloud service to auth, route, block and rate-limit the traffic. For example:

tp := `
on_http_request:
  - name: "rate limit by ip address"
    actions:
    - type: rate-limit
      config:
        name: client-ip-rate-limit
        algorithm: sliding_window
        capacity: 30
        rate: 60s
        bucket_key:
          - conn.client_ip
  - name: "federate to google for auth"
    actions:
    - type: oauth
      config:
        provider: google
  - name: "block users without an 'example.com' domain"
    expressions:
      - "!actions.ngrok.oauth.identity.email.endsWith('@example.com')"
    actions:
      - type: custom-response
        config:
          status_code: 403
          content: "${actions.ngrok.oauth.identity.name} is not allowed"
`

ln, err := ngrok.Listen(ctx, ngrok.WithTrafficPolicy(tp))
if err != nil {
	return err
}

Examples

There are many more great examples you can reference to get started:

Contributing

If you find bugs or would like to contribute code, please follow the instructions in the contributing guide.

Go Version Policy

We support the current and previous major releases of Go.

Changelog

Changes to ngrok-go are tracked under CHANGELOG.md.

Join the ngrok Community

License

ngrok-go is licensed under the terms of the MIT license.

See LICENSE for details.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultAgent, _ = NewAgent(
	WithAuthtoken(os.Getenv("NGROK_AUTHTOKEN")),
)

A default Agent instance to use when you don't need a custom one.

Functions

func IsMuxadoDiagnoseFailure added in v2.1.2

func IsMuxadoDiagnoseFailure(err error) bool

IsMuxadoDiagnoseFailure reports whether err is a muxado-level probe failure.

func IsTCPDiagnoseFailure added in v2.1.2

func IsTCPDiagnoseFailure(err error) bool

IsTCPDiagnoseFailure reports whether err is a TCP-level probe failure.

func IsTLSDiagnoseFailure added in v2.1.2

func IsTLSDiagnoseFailure(err error) bool

IsTLSDiagnoseFailure reports whether err is a TLS-level probe failure.

Types

type Agent

type Agent interface {
	// Connect begins a new Session by connecting and authenticating to the ngrok cloud service.
	Connect(context.Context) error

	// Disconnect terminates the current Session which disconnects it from the ngrok cloud service.
	Disconnect() error

	// Session returns an object describing the connection of the Agent to the ngrok cloud service.
	Session() (AgentSession, error)

	// Endpoints returns the list of endpoints created by this Agent from calls to either Listen or Forward.
	Endpoints() []Endpoint

	// Listen creates an Endpoint which returns received connections to the caller via an EndpointListener.
	Listen(context.Context, ...EndpointOption) (EndpointListener, error)

	// Forward creates an Endpoint which forwards received connections to a target upstream URL.
	Forward(context.Context, *Upstream, ...EndpointOption) (EndpointForwarder, error)
}

Agent is the main interface for interacting with the ngrok service.

func NewAgent

func NewAgent(agentOpts ...AgentOption) (Agent, error)

NewAgent creates a new Agent object.

type AgentOption

type AgentOption func(*agentOpts)

AgentOption is a functional option used to configure NewAgent.

func WithAgentConnectCAs

func WithAgentConnectCAs(pool *x509.CertPool) AgentOption

WithAgentConnectCAs defines the CAs used to validate the TLS certificate returned by the ngrok service when establishing a session.

See https://ngrok.com/docs/agent/config/v3/#connect_cas

func WithAgentConnectURL

func WithAgentConnectURL(addr string) AgentOption

WithAgentConnectURL defines the URL the agent connects to in order to establish a connection to the ngrok cloud service.

See https://ngrok.com/docs/agent/config/v3/#connect_url

func WithAgentDescription

func WithAgentDescription(desc string) AgentOption

WithAgentDescription sets a human-readable description for the agent session.

func WithAgentMetadata

func WithAgentMetadata(meta string) AgentOption

WithAgentMetadata sets opaque, machine-readable metadata for the agent session.

See https://ngrok.com/docs/api/resources/tunnel-sessions/#response-1

func WithAuthtoken

func WithAuthtoken(token string) AgentOption

WithAuthtoken specifies the authtoken to use for authenticating to the ngrok cloud service during Connect.

See https://ngrok.com/docs/agent/#authtokens

func WithAutoConnect

func WithAutoConnect(auto bool) AgentOption

WithAutoConnect controls whether the Agent will automatically call Connect(). When enabled, if an endpoint is created via Listen() or Connect() and the Agent does not have an active session, it will automatically Connect().

func WithClientInfo

func WithClientInfo(clientType, version string, comments ...string) AgentOption

WithClientInfo provides client information to the ngrok cloud service.

func WithDialer

func WithDialer(dialer Dialer) AgentOption

WithDialer customizes how the Agent establishes connections to the ngrok cloud service.

func WithEventHandler

func WithEventHandler(handler EventHandler) AgentOption

WithEventHandler registers a callback to receive events from the Agent. If called multiple times, each handler will receive callbacks. See EventHandler for details on correctly authoring handlers.

func WithHeartbeatInterval

func WithHeartbeatInterval(interval time.Duration) AgentOption

WithHeartbeatInterval sets how often the agent will send heartbeat messages to the ngrok service.

See https://ngrok.com/docs/agent/#heartbeats

func WithHeartbeatTolerance

func WithHeartbeatTolerance(tolerance time.Duration) AgentOption

WithHeartbeatTolerance sets how long to wait for a heartbeat response before assuming the connection is dead.

See https://ngrok.com/docs/agent/#heartbeats

func WithLogger

func WithLogger(logger *slog.Logger) AgentOption

WithLogger sets the logger to use for the agent. Accepts a standard log/slog.Logger from the Go standard library.

func WithMultiLeg

func WithMultiLeg(enable bool) AgentOption

WithMultiLeg enables connecting to the ngrok service on secondary legs. This option is EXPERIMENTAL and may be removed without a breaking version change.

func WithProxyURL

func WithProxyURL(urlSpec string) AgentOption

WithProxyURL sets the proxy URL to use when connecting to the ngrok service. The URL will be parsed and processed during Connect.

If used with WithDialer, the custom dialer will be used to establish the connection to the proxy, which will then connect to the ngrok service.

See https://ngrok.com/docs/agent/config/v3/#proxy_url

func WithRPCHandler

func WithRPCHandler(handler RPCHandler) AgentOption

WithRPCHandler registers a handler for RPC commands from the ngrok service. This handler will be called when the agent receives RPC requests like StopAgent, RestartAgent, or UpdateAgent.

func WithTLSConfig

func WithTLSConfig(tlsCustomizer func(*tls.Config)) AgentOption

WithTLSConfig customizes the TLS configuration for connections to the ngrok service.

type AgentSession

type AgentSession interface {
	// ID returns the server-assigned ID of the agent session
	ID() string
	// Warnings is a list of warnings returned by the ngrok cloud service after the Agent has connected
	Warnings() []error
	// Agent returns the agent that started this session
	Agent() Agent
	// StartedAt returns the time that the AgentSession was connected
	StartedAt() time.Time
}

AgentSession represents an active connection from an Agent to the ngrok cloud service.

type DiagnoseResult added in v2.1.2

type DiagnoseResult struct {
	// The address that was tested (ip:port or host:port).
	Addr string
	// Region reported by SrvInfo.
	Region string
	// Round-trip latency of the SrvInfo call.
	Latency time.Duration
	// PeerCertificates is the certificate chain presented by the server
	// during the TLS handshake, with the leaf certificate first. Populated
	// whenever the TLS handshake succeeded, even if a later probe step failed.
	PeerCertificates []*x509.Certificate
}

DiagnoseResult holds the outcome of a successful diagnostic probe.

type Diagnoser added in v2.1.2

type Diagnoser interface {
	Agent

	// Diagnose tests connectivity to addr by probing TCP, TLS, and the Muxado
	// tunnel protocol. It uses the Agent's configured TLS settings, CA roots,
	// and proxy/dialer settings.
	//
	// If addr is empty, the configured server address is probed.
	//
	// This method does NOT establish a persistent session or call Auth. It is
	// safe to call without affecting any existing connection.
	Diagnose(ctx context.Context, addr string) (DiagnoseResult, error)
}

Diagnoser is implemented by Agent types that support pre-connection diagnostic probing. Use a type assertion to access it:

d, ok := agent.(ngrok.Diagnoser)

type Dialer

type Dialer interface {
	Dial(network, address string) (net.Conn, error)
	DialContext(ctx context.Context, network, address string) (net.Conn, error)
}

Dialer is an interface that is satisfied by net.Dialer or you can specify your own implementation.

type Endpoint

type Endpoint interface {
	// Agent returns the Agent that created this Endpoint.
	Agent() Agent

	// PoolingEnabled returns whether the endpoint supports pooling set by WithPoolingEnabled.
	PoolingEnabled() bool

	// Bindings returns the endpoint's bindings set by WithBindings
	Bindings() []string

	// Close() is equivalent to for CloseWithContext(context.Background())
	Close() error

	// CloseWithContext closes the endpoint with the provided context.
	CloseWithContext(context.Context) error

	// Description returns the endpoint's human-readable description set by WithDescription.
	Description() string

	// Done returns a channel that is closed when the endpoint stops.
	Done() <-chan struct{}

	// Wait blocks until the endpoint stops.
	Wait()

	// ID returns the unique endpoint identifier assigned by the ngrok cloud service.
	ID() string

	// Metadata returns the endpoint's opaque user-defined metadata set by WithMetadata.
	Metadata() string

	// Name returns the endpoint's human-readable name set by WithName.
	Name() string

	// Protocol is sugar for URL().Scheme
	Protocol() string

	// AgentTLSTermination returns the TLS config that the agent uses to terminate TLS connections.
	AgentTLSTermination() *tls.Config

	// TrafficPolicy returns the traffic policy for the endpoint.
	TrafficPolicy() string

	// URL returns the Endpoint's URL
	URL() *url.URL

	// CreatedAt returns the time when the endpoint was created.
	CreatedAt() time.Time

	// UpdatedAt returns the time when the endpoint was last updated.
	UpdatedAt() time.Time

	// TunnelSessionID returns the ID of the agent session that created this endpoint.
	TunnelSessionID() string

	// TunnelID returns the tunnel resource ID.
	TunnelID() string
}

Endpoint is the interface implemented by both EndpointListener and EndpointForwarder.

type EndpointForwarder

type EndpointForwarder interface {
	Endpoint

	// UpstreamProtocol returns the protocol used to communicate with the upstream server.
	// This differs from UpstreamURL().Scheme if http2 is used.
	UpstreamProtocol() string

	// UpstreamURL returns the URL that the endpoint forwards its traffic to.
	UpstreamURL() url.URL

	// UpstreamTLSClientConfig returns the TLS client configuration used for upstream connections.
	UpstreamTLSClientConfig() *tls.Config

	// ProxyProtocol returns the PROXY protocol version used for the endpoint.
	// Returns a ProxyProtoVersion or empty string if not enabled.
	ProxyProtocol() ProxyProtoVersion
}

EndpointForwarder is an Endpoint that forwards traffic to an upstream service.

func Forward

func Forward(ctx context.Context, upstream *Upstream, opts ...EndpointOption) (EndpointForwarder, error)

Forward is sugar for DefaultAgent.Forward().

type EndpointListener

type EndpointListener interface {
	Endpoint

	// Accept returns the next connection received the Endpoint.
	Accept() (net.Conn, error)

	// Addr() returns where the Endpoint is listening.
	Addr() net.Addr
}

EndpointListener is an endpoint that you may treat as a net.Listener.

func Listen

func Listen(ctx context.Context, opts ...EndpointOption) (EndpointListener, error)

Listen is equivalent to DefaultAgent.Listen().

type EndpointOption

type EndpointOption func(*endpointOpts)

EndpointOption is a functional option used to configure endpoints.

func WithAgentTLSTermination

func WithAgentTLSTermination(config *tls.Config) EndpointOption

WithAgentTLSTermination sets a TLS configuration that the agent will use to terminate connections received on the Endpoint.

See https://ngrok.com/docs/agent/agent-tls-termination/

func WithBindings

func WithBindings(bindings ...string) EndpointOption

WithBindings sets the endpoint's bindings.

See https://ngrok.com/docs/universal-gateway/bindings/

func WithDescription

func WithDescription(desc string) EndpointOption

WithDescription sets a human-readable description for the endpoint.

func WithMetadata

func WithMetadata(meta string) EndpointOption

WithMetadata sets opaque, machine-readable metadata for the endpoint.

func WithName added in v2.1.2

func WithName(name string) EndpointOption

WithName sets a human-readable name for the endpoint.

func WithPoolingEnabled

func WithPoolingEnabled(pool bool) EndpointOption

WithPoolingEnabled controls whether the endpoint supports connection pooling.

See https://ngrok.com/docs/universal-gateway/endpoint-pooling/

func WithTrafficPolicy

func WithTrafficPolicy(policy string) EndpointOption

WithTrafficPolicy defines the Endpoint's Traffic Policy.

See https://ngrok.com/docs/traffic-policy/

func WithURL

func WithURL(urlSpec string) EndpointOption

WithURL defines the Endpoint's URL.

type Error

type Error interface {
	error
	// The unique ngrok error code
	Code() string
}

Error is a custom error type that includes a unique ngrok error code. All errors that are returned by the ngrok cloud service are of this type.

type Event

type Event interface {
	EventType() EventType
	Timestamp() time.Time
}

Event is the interface implemented by all event types

type EventAgentConnectSucceeded

type EventAgentConnectSucceeded struct {
	Agent   Agent
	Session AgentSession
	// contains filtered or unexported fields
}

EventAgentConnectSucceeded is emitted when an agent successfully establishes a connection

func (EventAgentConnectSucceeded) EventType

func (e EventAgentConnectSucceeded) EventType() EventType

func (EventAgentConnectSucceeded) Timestamp

func (e EventAgentConnectSucceeded) Timestamp() time.Time

type EventAgentDisconnected

type EventAgentDisconnected struct {
	Agent   Agent
	Session AgentSession
	Error   error
	// contains filtered or unexported fields
}

EventAgentDisconnected is emitted when an agent disconnects

func (EventAgentDisconnected) EventType

func (e EventAgentDisconnected) EventType() EventType

func (EventAgentDisconnected) Timestamp

func (e EventAgentDisconnected) Timestamp() time.Time

type EventAgentHeartbeatReceived

type EventAgentHeartbeatReceived struct {
	Agent   Agent
	Session AgentSession
	Latency time.Duration
	// contains filtered or unexported fields
}

EventAgentHeartbeatReceived is emitted when a heartbeat is successful

func (EventAgentHeartbeatReceived) EventType

func (e EventAgentHeartbeatReceived) EventType() EventType

func (EventAgentHeartbeatReceived) Timestamp

func (e EventAgentHeartbeatReceived) Timestamp() time.Time

type EventConnectionClosed added in v2.1.2

type EventConnectionClosed struct {
	Endpoint   Endpoint
	RemoteAddr string
	Duration   time.Duration
	BytesIn    int64
	BytesOut   int64
	// contains filtered or unexported fields
}

EventConnectionClosed is emitted when a forwarded connection is closed

func (EventConnectionClosed) EventType added in v2.1.2

func (e EventConnectionClosed) EventType() EventType

func (EventConnectionClosed) Timestamp added in v2.1.2

func (e EventConnectionClosed) Timestamp() time.Time

type EventConnectionOpened added in v2.1.2

type EventConnectionOpened struct {
	Endpoint   Endpoint
	RemoteAddr string
	// contains filtered or unexported fields
}

EventConnectionOpened is emitted when a new connection is accepted by a forwarder

func (EventConnectionOpened) EventType added in v2.1.2

func (e EventConnectionOpened) EventType() EventType

func (EventConnectionOpened) Timestamp added in v2.1.2

func (e EventConnectionOpened) Timestamp() time.Time

type EventHTTPRequestComplete added in v2.1.2

type EventHTTPRequestComplete struct {
	Endpoint   Endpoint
	Method     string
	Path       string
	StatusCode int
	Duration   time.Duration
	// contains filtered or unexported fields
}

EventHTTPRequestComplete is emitted when an HTTP request/response cycle completes

func (EventHTTPRequestComplete) EventType added in v2.1.2

func (e EventHTTPRequestComplete) EventType() EventType

func (EventHTTPRequestComplete) Timestamp added in v2.1.2

func (e EventHTTPRequestComplete) Timestamp() time.Time

type EventHandler

type EventHandler func(Event)

EventHandler is the function type for event callbacks. EventHandlers must not block. If you would like to run operations on an event that will block or fail, instead write your handler to either non-blockingly push the Event onto a channel or spin up a goroutine.

Example
// Define an event handler that logs known event types. For unknown events,
// it logs a warning message with the event type.
// This is useful for debugging and understanding the flow of events.
// Note: the pointer to event types is used when using a type switch.
var handler EventHandler = func(e Event) {
	switch v := e.(type) {
	case *EventAgentHeartbeatReceived:
		slog.Info("ngrok agent heartbeat received")
	case *EventAgentConnectSucceeded:
		slog.Info("ngrok agent connected")
	case *EventAgentDisconnected:
		slog.Error("ngrok agent disconnected", "error", v.Error)
	default:
		slog.Warn("Received unknown event", "type", e.EventType())
	}
}

agent, err := NewAgent(WithEventHandler(handler))
if err != nil {
	slog.Error("Failed to create ngrok agent", "error", err)
	return
}

_ = agent.Connect(context.Background())
Example (WithChannel)
// Create a buffered channel to receive events.
eventChan := make(chan Event, 10)

// Start a goroutine to handle events from the channel.
go func() {
	for e := range eventChan {
		switch v := e.(type) {
		case *EventAgentHeartbeatReceived:
			slog.Info("ngrok agent heartbeat received", "latency", v.Latency)
			// Some long potentially blocking operation here
		case *EventAgentConnectSucceeded:
			slog.Info("ngrok agent connected", "agent", v.Agent, "session", v.Session)
			// Some long potentially blocking operation here
		case *EventAgentDisconnected:
			slog.Error("ngrok agent disconnected", "error", v.Error, "agent", v.Agent, "session", v.Session)
			// Some long potentially blocking operation here
		default:
			slog.Warn("Received unknown event", "type", e.EventType())
		}
	}
}()

// The event handler will send events to the channel, if the channel is full,
// it will log a warning and drop the event to prevent blocking the agent's event processing.
var handler EventHandler = func(e Event) {
	select {
	case eventChan <- e:
	default:
		slog.Warn("Event channel is full, dropping event", "type", e.EventType())
	}
}

agent, err := NewAgent(WithEventHandler(handler))
if err != nil {
	slog.Error("Failed to create ngrok agent", "error", err)
	return
}

_ = agent.Connect(context.Background())

type EventType

type EventType int

EventType represents the type of event that occurred

const (
	EventTypeAgentConnectSucceeded EventType = iota
	EventTypeAgentDisconnected
	EventTypeAgentHeartbeatReceived
	EventTypeConnectionOpened
	EventTypeConnectionClosed
	EventTypeHTTPRequestComplete
)

func (EventType) String

func (t EventType) String() string

type ProxyProtoVersion

type ProxyProtoVersion string

ProxyProtoVersion represents PROXY protocol version

const (
	ProxyProtoV1 ProxyProtoVersion = "v1"
	ProxyProtoV2 ProxyProtoVersion = "v2"
)

type RPCHandler

type RPCHandler func(context.Context, AgentSession, rpc.Request) ([]byte, error)

RPCHandler is a function that processes RPC requests from the ngrok service. It receives the context, agent session, and request, and returns an optional response payload and error.

type Upstream

type Upstream struct {
	// contains filtered or unexported fields
}

Upstream represents configuration for forwarding to an upstream service.

func WithUpstream

func WithUpstream(addr string, opts ...UpstreamOption) *Upstream

WithUpstream creates an Upstream configuration with a required address. The address can be in various formats such as: - "80" (a port number for local services) - "example.com:8080" (a host:port combination) - "http://example.com" (a full URL)

type UpstreamOption

type UpstreamOption func(*Upstream)

UpstreamOption configures an Upstream instance.

func WithUpstreamDialer

func WithUpstreamDialer(dialer Dialer) UpstreamOption

WithUpstreamDialer sets a custom dialer to use when connecting to the upstream server. This allows for custom network configurations or connection methods when reaching the upstream.

func WithUpstreamProtocol

func WithUpstreamProtocol(proto string) UpstreamOption

WithUpstreamProtocol sets the protocol to use when forwarding to the upstream. This is typically used to specify "http2" when communicating with an upstream HTTP/2 server.

func WithUpstreamProxyProto

func WithUpstreamProxyProto(proxyProto ProxyProtoVersion) UpstreamOption

WithUpstreamProxyProto sets the PROXY protocol version to use when connecting to the upstream server. Valid values are ProxyProtoV1 or ProxyProtoV2.

See https://ngrok.com/docs/agent/config/v3/#upstreamproxy_protocol

func WithUpstreamTLSClientConfig

func WithUpstreamTLSClientConfig(config *tls.Config) UpstreamOption

WithUpstreamTLSClientConfig sets the TLS client configuration to use when connecting to the upstream server over TLS.

Directories

Path Synopsis
internal
pb
testcontext
Package testcontext provides a function to obtain a context.Context in a test.
Package testcontext provides a function to obtain a context.Context in a test.
tlstest
Package tlstest provides a function for creating a TLS certificate suitable for testing.
Package tlstest provides a function for creating a TLS certificate suitable for testing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL