forward

package
v0.0.59 Latest Latest
Warning

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

Go to latest
Published: May 23, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package forward implements host-to-VM port forwarding for Slicer.

Each accepted local TCP/Unix connection opens a per-connection WebSocket to the daemon at /vm/{hostname}/forward with an X-Inlets-Upstream header that tells the daemon what host:port (or unix:/path) to dial inside the guest. The WebSocket carries raw bytes both directions as binary frames. No subprotocol framing, no multiplexing — one local connection per WebSocket.

Usage:

fwd, err := forward.Start(ctx, forward.Options{
    BaseURL: "http://127.0.0.1:8080",
    Token:   os.Getenv("SLICER_TOKEN"),
    VMName:  "sbox-1",
    Specs:   []string{"127.0.0.1:8080:127.0.0.1:80"},
})
if err != nil { log.Fatal(err) }
defer fwd.Close()

// listeners are bound and serving; issue your host-side requests now.
resp, _ := http.Get("http://127.0.0.1:8080/")

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AddressMapping

type AddressMapping struct {
	// RawSpec is the original string supplied by the caller.
	RawSpec string

	// ListenAddr is the TCP bind address (e.g. "127.0.0.1" or "0.0.0.0").
	// Empty when listening on a Unix socket.
	ListenAddr string
	// ListenPort is the TCP listen port. Zero for random; ignored for Unix.
	ListenPort int
	// ListenUnixPath is set when listening on a Unix socket instead of TCP.
	ListenUnixPath string

	// RemoteHost is the guest-side TCP host to dial. Empty when targeting
	// a guest Unix socket.
	RemoteHost string
	// RemotePort is the guest-side TCP port.
	RemotePort int
	// RemoteUnixPath is set when dialing a Unix socket inside the guest.
	RemoteUnixPath string
}

AddressMapping describes one -L-style forward: a local listener on the host plus the upstream target to dial inside the VM.

func ParseAddressMapping

func ParseAddressMapping(spec string) (*AddressMapping, error)

ParseAddressMapping parses a -L-style spec. Supported formats:

127.0.0.1:9000                               TCP, listen and forward same host:port
9001:127.0.0.1:9000                          TCP, listen 0.0.0.0:9001 → 127.0.0.1:9000
0:127.0.0.1:9000                             TCP, random listen port → 127.0.0.1:9000
0.0.0.0:9000:127.0.0.1:9000                  TCP, fully explicit
127.0.0.1:9000:/var/run/docker.sock          TCP listen, Unix socket forward
9000:/var/run/docker.sock                    TCP listen 0.0.0.0:9000, Unix socket forward
/tmp/docker.sock:/var/run/docker.sock        Unix-to-Unix
./docker.sock:/var/run/docker.sock           Unix-to-Unix with relative local path

func (*AddressMapping) ListenAddress

func (m *AddressMapping) ListenAddress() string

ListenAddress renders a human-readable form of the local side.

func (*AddressMapping) ListenUnix

func (m *AddressMapping) ListenUnix() bool

ListenUnix reports whether the local listener is a Unix socket.

func (*AddressMapping) RemoteTarget

func (m *AddressMapping) RemoteTarget() string

RemoteTarget renders the X-Inlets-Upstream header value.

TCP:  "host:port"
Unix: "unix:/path/to/socket"

func (*AddressMapping) RemoteUnix

func (m *AddressMapping) RemoteUnix() bool

RemoteUnix reports whether the upstream target is a Unix socket.

type Forwarder

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

Forwarder holds bound listeners and the per-connection tunnel machinery. A Forwarder is safe to close from any goroutine; Close is idempotent.

func Start

func Start(ctx context.Context, opts Options) (*Forwarder, error)

Start parses specs, binds all local listeners, begins accepting, and returns a Forwarder. If binding any listener fails the partial state is cleaned up before returning the error.

ctx governs the lifetime of accept loops. Cancelling it is equivalent to calling Close.

func (*Forwarder) Close

func (f *Forwarder) Close() error

Close tears down all listeners and in-flight tunnel sockets. Safe to call multiple times.

func (*Forwarder) Listeners

func (f *Forwarder) Listeners() []Listener

Listeners returns the bound local listeners in the order they were supplied.

func (*Forwarder) Wait

func (f *Forwarder) Wait() error

Wait blocks until all accept loops have exited. Intended for callers who want to treat Start+Wait as a foreground operation, equivalent to the `slicer vm forward` CLI.

type Listener

type Listener struct {
	// Spec is the original -L string that created this listener.
	Spec string
	// Local is a human-readable form of the local address (e.g.
	// "127.0.0.1:50306" or "/tmp/docker.sock").
	Local string
	// Remote is the upstream target inside the VM as sent in X-Inlets-Upstream.
	Remote string
	// Port is the resolved local TCP port. Useful when the caller asked for 0.
	// Zero for Unix-socket listeners.
	Port int
}

Listener describes one bound local listener.

type Options

type Options struct {
	// BaseURL is the Slicer API URL: `http(s)://host[:port]` or an absolute
	// Unix socket path (`/path/to/slicer.sock` or `unix:///path`).
	BaseURL string

	// Token is the bearer token for the Slicer API. Optional for unix sockets
	// with no auth configured.
	Token string

	// VMName is the hostname of the VM to forward into.
	VMName string

	// Specs are -L-style mappings. See ParseAddressMapping for the accepted
	// formats.
	Specs []string

	// ClientID identifies this client to the daemon via the
	// X-Inlets-Client-ID header. Defaults to os.Hostname().
	ClientID string

	// UserAgent overrides the HTTP User-Agent header on the upgrade request.
	UserAgent string

	// DialTimeout bounds the initial WebSocket handshake. Default 10s.
	DialTimeout time.Duration

	// Logger receives short progress strings. If nil, events are discarded.
	Logger *log.Logger
}

Options configures a Forwarder.

Jump to

Keyboard shortcuts

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