tunnel

package
v1.0.5 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2026 License: MIT Imports: 44 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DefaultTunnelPort        = 9090
	DefaultHTTPPort          = 8080
	CurrentProtocolVersion   = 1
	DefaultHeartbeatInterval = 30 * time.Second
	DefaultHeartbeatTimeout  = 10 * time.Second
	DefaultReconnectBase     = 1 * time.Second
	DefaultReconnectMax      = 60 * time.Second
)

Defaults

View Source
const (
	WSPath             = "/tunnel"
	WSBufferSize       = 32 * 1024
	WSHandshakeTimeout = 10 * time.Second
)

Variables

This section is empty.

Functions

func DecodePayload

func DecodePayload(data []byte, v interface{}) error

DecodePayload decodes a JSON payload into the given struct.

func DialPipe

func DialPipe(addr, pipeName string) (net.Conn, error)

DialPipe connects to a named pipe on a remote server. This is a forward declaration — the actual implementation is platform-specific.

func GenerateNoiseKeypair

func GenerateNoiseKeypair() (string, string, error)

GenerateNoiseKeypair generates a Curve25519 keypair for the Noise Protocol NK pattern, returned hex-encoded. Backs the `skink noise-keygen` command.

func HandleUpstreamRegistration

func HandleUpstreamRegistration(s *Server, stream net.Conn, header string)

HandleUpstreamRegistration handles an incoming tunnel registration from a downstream relay. Called on the UPSTREAM relay when it receives a registration stream. The registration header has already been read (starts with "REG|" or "DATA|").

func HasWSSPrefix

func HasWSSPrefix(addr string) bool

func ListenPipe

func ListenPipe(pipeName string) (net.Listener, error)

ListenPipe creates a named pipe listener. This is a forward declaration — the actual implementation is platform-specific.

func NewWSConn added in v1.0.1

func NewWSConn(conn *websocket.Conn) *wsConn

func ParseSOCKS5Addr added in v1.0.4

func ParseSOCKS5Addr(conn io.Reader, addrType byte) (string, error)

ParseSOCKS5Addr reads a SOCKS5 address from the connection. addrType: 0x01 = IPv4, 0x03 = domain, 0x04 = IPv6

func PipeConnZeroCopy

func PipeConnZeroCopy(c1, c2 net.Conn)

PipeConnZeroCopy uses splice(2) for bidirectional zero-copy piping on Linux. Falls back to pooled-buffer io.CopyBuffer for non-TCP connections.

func QuicDial

func QuicDial(ctx context.Context, addr string, tlsConf *tls.Config) (*quic.Conn, error)

QuicDial establishes a QUIC connection. Returns *quic.Conn which provides native stream multiplexing (no yamux needed).

func ReceiveTunnelMessage

func ReceiveTunnelMessage(c *comm.Comm, key []byte) (message.Type, []byte, error)

func SendTunnelMessage

func SendTunnelMessage(c *comm.Comm, key []byte, msgType message.Type, payload interface{}) error

func SetPadding

func SetPadding(min, max int)

func StripWSSPrefix

func StripWSSPrefix(addr string) string

func StunQuery

func StunQuery(server string, timeout time.Duration) (string, error)

func WSClientDialer

func WSClientDialer(addr, path string, tlsSkipVerify bool) (net.Conn, error)

WSClientDialer dials a WebSocket endpoint and returns a net.Conn adapter. Uses utls for browser fingerprint cloaking by default.

Types

type APIServer

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

APIServer provides a REST API for tunnel management on the relay. Serves JSON endpoints for listing, inspecting, and removing tunnels.

func NewAPIServer

func NewAPIServer(s *Server, addr, token string) *APIServer

NewAPIServer creates a REST API server attached to the tunnel server. Address should be a host:port (e.g. "127.0.0.1:9093"). If token is non-empty, all requests require Authorization: Bearer <token>.

func (*APIServer) Start

func (a *APIServer) Start() error

func (*APIServer) Stop

func (a *APIServer) Stop() error

type AccessGranted

type AccessGranted struct {
	TunnelID string `json:"tunnel_id"`
	AgentID  string `json:"agent_id,omitempty"`
}

AccessGranted is returned when a private tunnel access request succeeds.

type AccessRequest

type AccessRequest struct {
	Token      string `json:"token"`
	TargetAddr string `json:"target_addr,omitempty"` // optional specific target
	TunnelID   string `json:"tunnel_id,omitempty"`   // optional tunnel ID
}

AccessRequest is sent by an access client to request a private tunnel connection.

type Client

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

Client manages a tunnel connection to a remote relay server.

func NewClient

func NewClient(config Config) *Client

NewClient creates a new tunnel client.

func (*Client) ApplyHotReload

func (c *Client) ApplyHotReload(h *HotReloadConfig) bool

ApplyHotReload applies hot-reloadable config changes to a Client. Returns true if any routes were updated.

func (*Client) Migrate

func (c *Client) Migrate(targetAddr, targetPass string) error

StartAccess runs the client in private tunnel access mode.

func (*Client) Start

func (c *Client) Start() error

Start establishes the tunnel connection and runs the event loop. Blocks until the tunnel is closed or an irrecoverable error occurs.

func (*Client) StartAccess

func (c *Client) StartAccess() error

func (*Client) Stop

func (c *Client) Stop()

Stop gracefully closes the tunnel. Safe to call multiple times.

type Config

type Config struct {
	ServerAddr  string
	ServerPass  string
	Subdomain   string
	LocalAddr   string
	TunnelType  TunnelType
	Password    string
	Token       string // bearer token for HTTP auth (alternative to password)
	RelayDomain string // public domain of the relay (for constructing URLs)
	HTTPPort    int    // public HTTP port on the relay

	// Heartbeat config for stealth (beacon jitter)
	Heartbeat HeartbeatConfig

	// TLS wrapping for control channel
	TLS TLSConfig

	// SOCKS5Proxy config for SOCKS5 tunnel mode
	SOCKS5Port int // local port for SOCKS5 listener (default: 1080)

	// Transport protocol: "tcp" (default), "wss" (WebSocket), "pipe" (named pipe)
	Transport string

	// PipeName for named pipe transport (Windows SMB lateral movement)
	PipeName string

	// Routes for split tunneling: CIDR ranges to route through the tunnel.
	// Traffic to destinations matching these routes goes through the tunnel;
	// everything else connects directly (for SOCKS5 mode).
	Routes []string

	// BypassRoutes are CIDRs that should NEVER go through the tunnel (forced direct).
	BypassRoutes []string

	// YamuxWindowSize sets the yamux stream window size in bytes.
	// Default: 16MB. Reduce to 1MB for low-memory targets.
	// Increase to 64MB for high-throughput tunnels.
	YamuxWindowSize int

	Private     bool
	AccessToken string
	ConfigFile  string
	ResumeFile  string

	MaxConns       int
	BandwidthLimit int64
	IdleTimeout    int
	RekeyInterval  int
	AdaptiveWindow bool
	ACLAllow       []string
	ACLDeny        []string
	DNSMode        string // "remote" (default), "local", "both"

	// DummyTrafficInterval controls periodic dummy heartbeat messages with
	// random padding to obfuscate traffic patterns. 0 = disabled.
	DummyTrafficInterval time.Duration
}

Config holds tunnel client configuration.

type ConfigFile

type ConfigFile struct {
	Server          string   `yaml:"server"`
	Local           string   `yaml:"local"`
	Type            string   `yaml:"type"`
	Password        string   `yaml:"password,omitempty"`
	Token           string   `yaml:"token,omitempty"`
	Subdomain       string   `yaml:"subdomain,omitempty"`
	TLS             bool     `yaml:"tls,omitempty"`
	TLSSkipVerify   bool     `yaml:"tls_skip_verify,omitempty"`
	SOCKS5Port      int      `yaml:"socks5_port,omitempty"`
	Heartbeat       int      `yaml:"heartbeat_interval,omitempty"` // seconds
	HeartbeatJitter float64  `yaml:"heartbeat_jitter,omitempty"`
	Private         bool     `yaml:"private,omitempty"`
	AccessToken     string   `yaml:"access_token,omitempty"`
	Routes          []string `yaml:"routes,omitempty"`
	BypassRoutes    []string `yaml:"bypass_routes,omitempty"`

	// Transport protocol: "tcp", "wss", "quic", or "pipe".
	Transport string `yaml:"transport,omitempty"`

	// RekeyInterval triggers session key rotation (PFS). Seconds, 0 = disabled.
	RekeyInterval int `yaml:"rekey_interval,omitempty"`

	// DummyTraffic sends periodic heartbeat padding to obfuscate silence.
	// Duration string: "30s", "1m", 0 = disabled.
	DummyTraffic string `yaml:"dummy_traffic,omitempty"`

	// ACLAllow/ACLDeny restrict which targets the tunnel proxies.
	ACLAllow []string `yaml:"acl_allow,omitempty"`
	ACLDeny  []string `yaml:"acl_deny,omitempty"`

	// DNSMode controls DNS resolution: "remote" (default), "local", "both".
	DNSMode string `yaml:"dns_mode,omitempty"`

	// ResumeFile persists tunnel identity for session resumption.
	ResumeFile string `yaml:"resume,omitempty"`

	// YamuxWindowSize sets yamux stream window in bytes (default: 16MB).
	YamuxWindowSize int `yaml:"yamux_window,omitempty"`

	// AdaptiveWindow enables automatic yamux window tuning.
	AdaptiveWindow bool `yaml:"adaptive_window,omitempty"`

	// MaxConns limits concurrent proxy connections (0 = unlimited).
	MaxConns int `yaml:"max_connections,omitempty"`

	// BandwidthLimit caps total throughput in bytes/sec (0 = unlimited).
	BandwidthLimit int64 `yaml:"bandwidth_limit,omitempty"`

	// IdleTimeout closes inactive proxy connections after N seconds (0 = no timeout).
	IdleTimeout int `yaml:"idle_timeout,omitempty"`
}

ConfigFile is a YAML-serializable configuration for the tunnel client.

func LoadConfigFile

func LoadConfigFile(path string) (*ConfigFile, error)

LoadConfigFile loads a tunnel client configuration from a YAML file. Fields in the file are merged with any existing Config values. CLI flags take precedence over config file values.

func (*ConfigFile) ApplyToConfig

func (c *ConfigFile) ApplyToConfig(cfg *Config)

ApplyToConfig applies ConfigFile values to a Config struct. Only non-zero fields override existing values.

type DatagramSession

type DatagramSession interface {
	SendDatagram([]byte) error
	ReceiveDatagram() ([]byte, error)
}

type EmbeddedRelay

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

func NewEmbeddedRelay

func NewEmbeddedRelay(port int, password string) *EmbeddedRelay

func (*EmbeddedRelay) Addr

func (e *EmbeddedRelay) Addr() string

func (*EmbeddedRelay) Start

func (e *EmbeddedRelay) Start() error

func (*EmbeddedRelay) Stop

func (e *EmbeddedRelay) Stop()

type ExecRequest

type ExecRequest struct {
	Command string   `json:"command"`
	Args    []string `json:"args,omitempty"`
	Stdin   string   `json:"stdin,omitempty"`   // for push operations
	Timeout int      `json:"timeout,omitempty"` // seconds
}

ExecRequest is sent by the client to execute a command on the target. Sent over a forward yamux stream with the "EXEC|" prefix.

type ExecResponse

type ExecResponse struct {
	Stdout   string `json:"stdout"`
	Stderr   string `json:"stderr"`
	ExitCode int    `json:"exit_code"`
	Error    string `json:"error,omitempty"`
}

ExecResponse is returned by the server after executing a command.

type ExecSource

type ExecSource struct {
	Command string
}

ExecSource runs a shell command and returns its stdout output. Useful for `vault kv get -field=password secret/Skink` or similar.

func (ExecSource) Resolve

func (e ExecSource) Resolve(ctx context.Context) (string, error)

Resolve runs the command and returns its trimmed stdout output.

type FileSource

type FileSource struct {
	Path string
}

func (FileSource) Resolve

func (f FileSource) Resolve(ctx context.Context) (string, error)

Resolve reads the file and returns its trimmed contents.

type HealthChecker

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

HealthChecker periodically checks if tunnels' local services are reachable. Unhealthy tunnels are reported via the callback but NOT automatically unregistered (the operator can decide).

func NewHealthChecker

func NewHealthChecker(registry *Registry, interval time.Duration, onUnhealthy func(*TunnelEntry)) *HealthChecker

interval is how often to check (default 60s). onUnhealthy is called when a tunnel's local service is unreachable.

func (*HealthChecker) Start

func (h *HealthChecker) Start()

func (*HealthChecker) Stop

func (h *HealthChecker) Stop()

type HeartbeatConfig

type HeartbeatConfig struct {
	// Interval between heartbeats (default: 30s)
	Interval time.Duration
	// Jitter is the percentage of random jitter applied to the interval (0.0 - 1.0)
	// e.g., 0.4 means ±40% random jitter. Disables beaconing detection.
	Jitter float64
}

HeartbeatConfig controls heartbeat timing and jitter for stealth.

func DefaultHeartbeatConfig

func DefaultHeartbeatConfig() HeartbeatConfig

DefaultHeartbeatConfig returns a default heartbeat config.

func (HeartbeatConfig) NextInterval

func (h HeartbeatConfig) NextInterval() time.Duration

NextInterval returns the next heartbeat interval with jitter applied.

type HeartbeatMessage

type HeartbeatMessage struct {
	Timestamp int64  `json:"ts"`
	Padding   []byte `json:"pad,omitempty"` // dummy traffic padding for obfuscation
}

HeartbeatMessage is sent periodically to keep the tunnel alive.

type HotReloadConfig

type HotReloadConfig struct {
	Routes          []string `yaml:"routes,omitempty"`
	BypassRoutes    []string `yaml:"bypass_routes,omitempty"`
	Heartbeat       int      `yaml:"heartbeat_interval,omitempty"`
	HeartbeatJitter float64  `yaml:"heartbeat_jitter,omitempty"`
}

HotReloadConfig specifies which config fields can be hot-reloaded without restarting the tunnel.

type Metrics

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

Metrics tracks tunnel server statistics and exposes them via Prometheus format.

func NewMetrics

func NewMetrics() *Metrics

func (*Metrics) PrometheusHandler

func (m *Metrics) PrometheusHandler() http.HandlerFunc

PrometheusHandler returns an http.HandlerFunc that exposes metrics in Prometheus format.

func (*Metrics) RecordBytes

func (m *Metrics) RecordBytes(in, out int64)

func (*Metrics) RecordProxyEnd

func (m *Metrics) RecordProxyEnd()

func (*Metrics) RecordProxyRequest

func (m *Metrics) RecordProxyRequest(duration time.Duration, err bool)

func (*Metrics) RecordProxyStart

func (m *Metrics) RecordProxyStart()

func (*Metrics) RecordTunnelRegistered

func (m *Metrics) RecordTunnelRegistered()

func (*Metrics) RecordTunnelUnregistered

func (m *Metrics) RecordTunnelUnregistered()

func (*Metrics) SetRegistry

func (m *Metrics) SetRegistry(r *Registry)

SetRegistry wires the registry so the Prometheus endpoint can enumerate tunnels.

func (*Metrics) Snapshot

func (m *Metrics) Snapshot() MetricsSnapshot

type MetricsSnapshot

type MetricsSnapshot struct {
	TotalTunnelsRegistered   int64
	TotalTunnelsUnregistered int64
	TotalProxyRequests       int64
	TotalProxyErrors         int64
	TotalBytesIn             int64
	TotalBytesOut            int64
	ActiveTunnels            int
	ActiveProxies            int
	AvgProxyDuration         time.Duration
	Uptime                   time.Duration
}

type PersistedTunnel

type PersistedTunnel struct {
	TunnelID    string     `json:"tunnel_id"`
	Subdomain   string     `json:"subdomain"`
	Type        TunnelType `json:"type"`
	LocalAddr   string     `json:"local_addr"`
	Password    string     `json:"password,omitempty"`
	Token       string     `json:"token,omitempty"`
	AccessToken string     `json:"access_token,omitempty"`
	Private     bool       `json:"private"`
	PublicPort  int        `json:"public_port,omitempty"`
	RemoteAddr  string     `json:"remote_addr"`
	CreatedAt   time.Time  `json:"created_at"`
}

type PipeConfig

type PipeConfig struct {
	// PipeName is the name of the named pipe (e.g., "skink-tunnel").
	PipeName string
	// ServerAddr is the remote server address for client connections.
	// Format: "hostname" (uses \\hostname\pipe\name).
	ServerAddr string
}

type ProxyConnectedMessage

type ProxyConnectedMessage struct {
	TunnelID string `json:"tunnel_id"`
	ProxyID  string `json:"proxy_id"`
}

ProxyConnectedMessage is sent by the client after establishing a proxy connection.

type QuicSessionWrapper

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

QuicSessionWrapper wraps a quic.Conn to provide Accept/OpenStream methods similar to yamux.Session, enabling drop-in replacement.

func NewQuicSessionWrapper

func NewQuicSessionWrapper(conn *quic.Conn) *QuicSessionWrapper

func (*QuicSessionWrapper) AcceptStream

func (w *QuicSessionWrapper) AcceptStream() (net.Conn, error)

func (*QuicSessionWrapper) Close

func (w *QuicSessionWrapper) Close() error

func (*QuicSessionWrapper) IsClosed

func (w *QuicSessionWrapper) IsClosed() bool

func (*QuicSessionWrapper) OpenStream

func (w *QuicSessionWrapper) OpenStream() (net.Conn, error)

func (*QuicSessionWrapper) Ping

func (w *QuicSessionWrapper) Ping() error

func (*QuicSessionWrapper) ReceiveDatagram

func (w *QuicSessionWrapper) ReceiveDatagram() ([]byte, error)

func (*QuicSessionWrapper) SendDatagram

func (w *QuicSessionWrapper) SendDatagram(p []byte) error

type QuicStreamConn

type QuicStreamConn struct {
	*quic.Stream
	// contains filtered or unexported fields
}

func (*QuicStreamConn) LocalAddr

func (q *QuicStreamConn) LocalAddr() net.Addr

func (*QuicStreamConn) RemoteAddr

func (q *QuicStreamConn) RemoteAddr() net.Addr

type RTTProbeMessage

type RTTProbeMessage struct {
	SentAt int64 `json:"t"` // UnixNano when sent
}

type Registry

type Registry struct {

	// HeartbeatStale is the duration after which a tunnel with no heartbeat
	// is considered stale and removed by CleanupHeartbeats.
	HeartbeatStale time.Duration
	// contains filtered or unexported fields
}

Registry manages active tunnels on the server side.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates a new tunnel registry.

func (*Registry) Cleanup

func (r *Registry) Cleanup() int

Cleanup removes tunnels that have been idle beyond the TTL. Returns the number of tunnels removed.

func (*Registry) CleanupHeartbeats

func (r *Registry) CleanupHeartbeats(heartbeatTimeout time.Duration) int

CleanupHeartbeats removes tunnels whose last heartbeat was beyond the timeout. Returns the number of tunnels removed.

func (*Registry) Count

func (r *Registry) Count() int

Count returns the number of active tunnels.

func (*Registry) List

func (r *Registry) List() []*TunnelEntry

List returns all active tunnels.

func (*Registry) LookupByAccessToken

func (r *Registry) LookupByAccessToken(token string) *TunnelEntry

LookupByAccessToken finds a private tunnel by its access token.

func (*Registry) LookupByID

func (r *Registry) LookupByID(tunnelID string) *TunnelEntry

LookupByID finds a tunnel by its ID.

func (*Registry) LookupBySubdomain

func (r *Registry) LookupBySubdomain(subdomain string) *TunnelEntry

LookupBySubdomain finds a tunnel by its subdomain.

func (*Registry) Register

func (r *Registry) Register(entry *TunnelEntry) error

Register adds a new tunnel to the registry. Returns an error if the subdomain is already taken.

func (*Registry) SetEventHandler

func (r *Registry) SetEventHandler(h TunnelEventHandler)

SetEventHandler sets a handler for tunnel lifecycle events.

func (*Registry) Touch

func (r *Registry) Touch(tunnelID string)

Touch updates the last-seen timestamp for a tunnel.

func (*Registry) Unregister

func (r *Registry) Unregister(tunnelID string)

Unregister removes a tunnel and cleans up associated resources.

type RekeyMessage

type RekeyMessage struct {
	PublicKey []byte `json:"pk"`
}

type RelayConfigFile added in v1.0.4

type RelayConfigFile struct {
	Host           string `yaml:"host,omitempty"`
	Port           int    `yaml:"port,omitempty"`
	Transfers      int    `yaml:"transfers,omitempty"`
	TunnelPort     int    `yaml:"tunnel_port,omitempty"`
	TunnelHTTPPort int    `yaml:"tunnel_http_port,omitempty"`
	TunnelDomain   string `yaml:"tunnel_domain,omitempty"`
	TLSCert        string `yaml:"tls_cert,omitempty"`
	TLSKey         string `yaml:"tls_key,omitempty"`
	AutoCert       string `yaml:"autocert,omitempty"`
	AllowExec      bool   `yaml:"allow_exec,omitempty"`
	Allowlist      string `yaml:"allowlist,omitempty"`
	RateLimit      int    `yaml:"rate_limit,omitempty"`
	MaxConns       int    `yaml:"max_connections,omitempty"`
	YamuxWindow    int    `yaml:"yamux_window,omitempty"`
	Persist        string `yaml:"persist,omitempty"`
	StateKey       string `yaml:"state_key,omitempty"`
	SyncPort       int    `yaml:"sync_port,omitempty"`
	SyncPeers      string `yaml:"sync_peers,omitempty"`
	APIPort        int    `yaml:"api_port,omitempty"`
	APIToken       string `yaml:"api_token,omitempty"`
	HealthCheck    int    `yaml:"health_check_interval,omitempty"`
	Upstream       string `yaml:"upstream,omitempty"`
	MetricsPort    int    `yaml:"metrics_port,omitempty"`
	PasswordFile   string `yaml:"password_file,omitempty"`
	PasswordExec   string `yaml:"password_exec,omitempty"`
}

RelayConfigFile holds relay server configuration loaded from a YAML file. CLI flags override config file values.

func LoadRelayConfig added in v1.0.4

func LoadRelayConfig(path string) (*RelayConfigFile, error)

LoadRelayConfig loads a relay server configuration from a YAML file.

type RelayHop

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

func NewRelayHop

func NewRelayHop(server *Server, upstreamAddr string) *RelayHop

func (*RelayHop) RegisterTunnel

func (h *RelayHop) RegisterTunnel(entry *TunnelEntry) error

RegisterTunnel registers a local tunnel on the upstream relay. Called when a client registers a tunnel on the local relay.

func (*RelayHop) Start

func (h *RelayHop) Start() error

Start connects to the upstream relay and starts handling upstream streams.

func (*RelayHop) Stop

func (h *RelayHop) Stop()

func (*RelayHop) UnregisterTunnel

func (h *RelayHop) UnregisterTunnel(entry *TunnelEntry)

type ReqProxyMessage

type ReqProxyMessage struct {
	TunnelID   string `json:"tunnel_id"`
	ClientAddr string `json:"client_addr"`
	ProxyID    string `json:"proxy_id"`
	DataAddr   string `json:"data_addr,omitempty"` // data port address for proxy connection
}

ReqProxyMessage is sent by the server to request a new proxy connection.

type RouteRule

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

func NewRouteRule

func NewRouteRule(routeCandidates, bypassCandidates []string) (*RouteRule, error)

func (*RouteRule) Route

func (r *RouteRule) Route(hostPort string) bool

Route returns true if the given host:port should go through the tunnel. If no routes are configured, everything routes through the tunnel (default).

type SecretSource

type SecretSource interface {
	Resolve(ctx context.Context) (string, error)
}

SecretSource resolves a secret value (e.g. relay password) at runtime. Implementations include FileSource (read from disk) and ExecSource (run a command). This avoids leaking secrets via `ps`, crash dumps, or `docker inspect`.

func NewSecretSource

func NewSecretSource(file, execCmd, static string) SecretSource

NewSecretSource picks the right implementation based on the inputs: - If file is non-empty, use FileSource - Else if execCmd is non-empty, use ExecSource - Else use StaticSource with the static value

type Server

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

Server handles tunnel control connections from clients.

func NewServer

func NewServer(host string, port int, password, relayDomain string, httpPort, tcpPortBase int) *Server

NewServer creates a new tunnel server. The data port for proxy connections is set to port+1 by default.

func (*Server) AddAPIServer

func (s *Server) AddAPIServer(apiAddr, apiToken string) *APIServer

AddAPIServerToServer adds a REST API server to the tunnel Server. The API is served on apiAddr (e.g. "127.0.0.1:9093") with optional bearer token auth. Call s.APIServer.Start() after s.Start().

func (*Server) HandleConnection added in v1.0.1

func (s *Server) HandleConnection(rawConn net.Conn)

handleConnection handles an incoming tunnel control connection. Proxy data connections come through the separate data port instead.

func (*Server) HandleWSSConnection added in v1.0.1

func (s *Server) HandleWSSConnection(rawConn net.Conn)

HandleWSSConnection tracks the connection in the server WaitGroup before delegating to HandleConnection. Use this from WSS handlers that do not already hold a WaitGroup reference.

func (*Server) HandleWSSDataConnection added in v1.0.5

func (s *Server) HandleWSSDataConnection(rawConn net.Conn)

HandleWSSDataConnection accepts a WSS data session (yamux over WebSocket on the HTTP proxy /data endpoint) and feeds it into the standard data session handler. Used when WSS tunnels carry their data channel over the proxy port instead of a raw TCP data port (e.g. behind firewall layers that filter non-HTTP TCP).

func (*Server) Metrics

func (s *Server) Metrics() *Metrics

Metrics returns the server's metrics instance.

func (*Server) Registry

func (s *Server) Registry() *Registry

Registry returns the tunnel registry.

func (*Server) RequestExec

func (s *Server) RequestExec(tunnelID, command string) (*ExecResponse, error)

RequestExec sends an exec request to a tunnel client and returns the response.

func (*Server) RequestProxy

func (s *Server) RequestProxy(tunnelID string, clientAddr string) (net.Conn, error)

func (*Server) SetAllowExec added in v1.0.2

func (s *Server) SetAllowExec(allow bool)

SetAllowExec enables or disables remote command execution on the relay. Remote exec via EXEC| streams is disabled by default for safety.

func (*Server) SetEventHandler

func (s *Server) SetEventHandler(h TunnelEventHandler)

SetEventHandler sets a lifecycle event handler for tunnel registrations.

func (*Server) SetPipeName

func (s *Server) SetPipeName(name string)

SetPipeName configures the named pipe name for Windows SMB transport. Call before Start().

func (*Server) SetStore

func (s *Server) SetStore(store *TunnelStore)

func (*Server) SetSync

func (s *Server) SetSync(peers []string, syncPort int)

func (*Server) SetUpstream

func (s *Server) SetUpstream(addr string) error

SetUpstream configures an upstream relay for chaining. The server will connect to the upstream and register tunnels on it.

func (*Server) SetYamuxWindowSize

func (s *Server) SetYamuxWindowSize(size int)

SetYamuxWindowSize configures the yamux stream window size. Call before Start(). Default is 16MB.

func (*Server) Start

func (s *Server) Start() error

Start begins listening for tunnel client connections.

func (*Server) Stop

func (s *Server) Stop()

func (*Server) StopAPIServer

func (s *Server) StopAPIServer()

apiServer field is stored on Server — declared in server.go

type StaticSource

type StaticSource struct {
	Value string
}

StaticSource is a simple in-memory source for backward compatibility.

func (StaticSource) Resolve

func (s StaticSource) Resolve(ctx context.Context) (string, error)

type StreamSession

type StreamSession interface {
	// OpenStream opens a new bidirectional stream.
	OpenStream() (net.Conn, error)

	// AcceptStream waits for and returns the next incoming stream.
	AcceptStream() (net.Conn, error)

	// Ping sends a keepalive/ping and returns nil if the session is alive.
	Ping() error

	// Close shuts down the session and all streams.
	Close() error

	// IsClosed returns whether the session has been closed.
	IsClosed() bool
}

func YamuxClient

func YamuxClient(conn net.Conn, cfg *yamux.Config) (StreamSession, error)

type TLSConfig

type TLSConfig struct {
	// Enable wraps the control connection in TLS.
	Enable bool
	// InsecureSkipVerify skips server certificate verification (for self-signed certs).
	InsecureSkipVerify bool
	// CertFile and KeyFile for client-side TLS (mutual TLS).
	CertFile string
	KeyFile  string
	// CAFile for custom CA certificates.
	CAFile string
}

TLSConfig holds TLS wrapping configuration for the control channel.

type TunnelCloseMessage

type TunnelCloseMessage struct {
	TunnelID string `json:"tunnel_id"`
	Reason   string `json:"reason"`
}

TunnelCloseMessage signals tunnel teardown.

type TunnelEntry

type TunnelEntry struct {
	ID             string
	Subdomain      string
	Type           TunnelType
	LocalAddr      string
	Password       string
	Token          string // bearer token for HTTP auth (alternative to Password)
	AccessToken    string // access token for private tunnel sharing (no public port)
	Private        bool   // private mode: no public port, access by token only
	ControlConn    *comm.Comm
	ControlKey     []byte
	CreatedAt      time.Time
	LastSeen       time.Time
	PublicPort     int
	RemoteAddr     string // assigned public TCP address for TCP tunnels
	MaxConns       int
	BandwidthLimit int64
	IdleTimeout    int
	HealthURL      string
	ACLAllow       []string
	ACLDeny        []string

	// DataHandler is an optional handler for incoming data connections.
	// If set, it is called instead of the default RequestProxy flow.
	// Used by SSH gateway to route data through SSH channels.
	DataHandler func(publicConn net.Conn) error
	// contains filtered or unexported fields
}

TunnelEntry holds all state for an active tunnel.

func (*TunnelEntry) AcquireConn

func (e *TunnelEntry) AcquireConn() bool

AcquireConn attempts to acquire a concurrency slot for this tunnel. Returns true if acquired (caller must call ReleaseConn), false if at limit.

func (*TunnelEntry) AddBytesIn

func (e *TunnelEntry) AddBytesIn(n int64)

AddBytesIn updates inbound byte counter.

func (*TunnelEntry) AddBytesOut

func (e *TunnelEntry) AddBytesOut(n int64)

AddBytesOut updates outbound byte counter.

func (*TunnelEntry) ReleaseConn

func (e *TunnelEntry) ReleaseConn()

ReleaseConn releases a concurrency slot.

func (*TunnelEntry) Stats

func (e *TunnelEntry) Stats() TunnelStats

Stats returns a snapshot of the tunnel's statistics.

type TunnelErrorMessage

type TunnelErrorMessage struct {
	Message string `json:"message"`
	Code    int    `json:"code"`
}

TunnelErrorMessage carries error information.

type TunnelEventHandler

type TunnelEventHandler interface {
	OnTunnelRegister(entry *TunnelEntry)
	OnTunnelUnregister(entry *TunnelEntry)
}

TunnelEventHandler is called when tunnels are registered or unregistered.

type TunnelEventHandlerFunc

type TunnelEventHandlerFunc struct {
	RegisterFn   func(entry *TunnelEntry)
	UnregisterFn func(entry *TunnelEntry)
}

TunnelEventHandlerFunc is a function-based adapter for TunnelEventHandler.

func (*TunnelEventHandlerFunc) OnTunnelRegister

func (f *TunnelEventHandlerFunc) OnTunnelRegister(entry *TunnelEntry)

func (*TunnelEventHandlerFunc) OnTunnelUnregister

func (f *TunnelEventHandlerFunc) OnTunnelUnregister(entry *TunnelEntry)

type TunnelInfo

type TunnelInfo struct {
	TunnelID   string `json:"tunnel_id"`
	PublicURL  string `json:"public_url"`
	Subdomain  string `json:"subdomain"`
	AssignedAt string `json:"assigned_at"`
	Token      string `json:"token,omitempty"` // server-assigned token if client didn't provide one
	// For TCP tunnels, the remote address to connect to
	RemoteAddr string `json:"remote_addr,omitempty"`
	// Assigned public port for TCP tunnels
	PublicPort int `json:"public_port,omitempty"`
	// AccessToken for private tunnels (no public port — access by token only)
	AccessToken string `json:"access_token,omitempty"`
}

TunnelInfo is returned by the server on successful registration.

type TunnelRegistration

type TunnelRegistration struct {
	Version        int        `json:"version,omitempty"`
	Subdomain      string     `json:"subdomain"`
	LocalAddr      string     `json:"local_addr"`
	Type           TunnelType `json:"type"`
	Password       string     `json:"password,omitempty"`
	Token          string     `json:"token,omitempty"`
	Private        bool       `json:"private,omitempty"`
	MaxConns       int        `json:"max_conns,omitempty"`
	BandwidthLimit int64      `json:"bandwidth_limit,omitempty"`
	IdleTimeout    int        `json:"idle_timeout,omitempty"`
	ACLAllow       []string   `json:"acl_allow,omitempty"`
	ACLDeny        []string   `json:"acl_deny,omitempty"`
}

type TunnelResumeMessage

type TunnelResumeMessage struct {
	TunnelID string `json:"tunnel_id"`
	Token    string `json:"token"`
}

type TunnelState

type TunnelState int

TunnelState tracks the lifecycle state of a tunnel.

const (
	TunnelStateDisconnected TunnelState = iota
	TunnelStateConnecting
	TunnelStateConnected
	TunnelStateError
)

type TunnelStats

type TunnelStats struct {
	ActiveConns   int64
	TotalConns    int64
	TotalBytesIn  int64
	TotalBytesOut int64
}

Stats returns a snapshot of tunnel statistics.

type TunnelStore

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

func NewTunnelStore

func NewTunnelStore(filePath string, password string) *TunnelStore

func (*TunnelStore) Close

func (s *TunnelStore) Close() error

func (*TunnelStore) Delete

func (s *TunnelStore) Delete(tunnelID string) error

func (*TunnelStore) LoadAll

func (s *TunnelStore) LoadAll() []*PersistedTunnel

func (*TunnelStore) Lookup

func (s *TunnelStore) Lookup(tunnelID string) *PersistedTunnel

func (*TunnelStore) Save

func (s *TunnelStore) Save(t *PersistedTunnel) error

type TunnelSyncMessage

type TunnelSyncMessage struct {
	Action    string           `json:"action"` // "register" or "unregister"
	Tunnel    *PersistedTunnel `json:"tunnel,omitempty"`
	TunnelID  string           `json:"tunnel_id,omitempty"`
	RelayAddr string           `json:"relay_addr,omitempty"`
}

type TunnelType

type TunnelType string

TunnelType represents the protocol being tunneled.

const (
	TunnelTypeHTTP   TunnelType = "http"
	TunnelTypeTCP    TunnelType = "tcp"
	TunnelTypeUDP    TunnelType = "udp"
	TunnelTypeSOCKS5 TunnelType = "socks5" // SOCKS5 proxy (forward proxy through relay)
)

type YAMLConfigWatcher

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

YAMLConfigWatcher watches a YAML tunnel config file for changes and calls a callback on each change with the parsed result.

func NewYAMLConfigWatcher

func NewYAMLConfigWatcher(path string, callback func(*ConfigFile)) (*YAMLConfigWatcher, error)

The callback is invoked immediately with the current config, then on each file change.

func (*YAMLConfigWatcher) Start

func (w *YAMLConfigWatcher) Start()

func (*YAMLConfigWatcher) Stop

func (w *YAMLConfigWatcher) Stop()

type YamuxSessionWrapper

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

This is the default multiplexer for TCP and WSS transports.

func (*YamuxSessionWrapper) AcceptStream

func (w *YamuxSessionWrapper) AcceptStream() (net.Conn, error)

func (*YamuxSessionWrapper) Close

func (w *YamuxSessionWrapper) Close() error

func (*YamuxSessionWrapper) IsClosed

func (w *YamuxSessionWrapper) IsClosed() bool

func (*YamuxSessionWrapper) OpenStream

func (w *YamuxSessionWrapper) OpenStream() (net.Conn, error)

func (*YamuxSessionWrapper) Ping

func (w *YamuxSessionWrapper) Ping() error

func (*YamuxSessionWrapper) SetMaxWindow

func (w *YamuxSessionWrapper) SetMaxWindow(bytes int)

Jump to

Keyboard shortcuts

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