controlclient

package
v1.14.3 Latest Latest
Warning

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

Go to latest
Published: Sep 16, 2021 License: BSD-3-Clause Imports: 50 Imported by: 26

Documentation

Overview

Package controlclient implements the client for the Tailscale control plane.

It handles authentication, port picking, and collects the local network configuration.

Index

Constants

View Source
const (
	LoginDefault     = LoginFlags(0)
	LoginInteractive = LoginFlags(1 << iota) // force user login and key refresh
)
View Source
const (
	StateNew = State(iota)
	StateNotAuthenticated
	StateAuthenticating
	StateURLVisitRequired
	StateAuthenticated
	StateSynchronized // connected and received map update
)

Variables

View Source
var Debug = initDebug()

Debug contains temporary internal-only debug knobs. They're unexported to not draw attention to them.

Functions

func DERPRouteFlag added in v1.2.0

func DERPRouteFlag() opt.Bool

DERPRouteFlag reports the last reported value from control for whether DERP route optimization (Issue 150) should be enabled.

func HashRegisterRequest added in v1.8.0

func HashRegisterRequest(ts time.Time, serverURL string, deviceCert []byte, serverPubKey, machinePubKey wgkey.Key) []byte

HashRegisterRequest generates the hash required sign or verify a tailcfg.RegisterRequest with tailcfg.SignatureV1.

func TrimWGConfig added in v1.2.0

func TrimWGConfig() opt.Bool

TrimWGConfig reports the last reported value from control for whether we should do lazy wireguard configuration.

Types

type Auto added in v1.8.0

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

Auto connects to a tailcontrol server for a node. It's a concrete implementation of the Client interface.

func New

func New(opts Options) (*Auto, error)

New creates and starts a new Auto.

func NewNoStart

func NewNoStart(opts Options) (*Auto, error)

NewNoStart creates a new Auto, but without calling Start on it.

func (*Auto) AuthCantContinue added in v1.8.0

func (c *Auto) AuthCantContinue() bool

func (*Auto) Direct added in v1.8.0

func (c *Auto) Direct() *Direct

Direct returns the underlying direct client object. Used in tests only.

func (*Auto) Expiry added in v1.8.0

func (c *Auto) Expiry() *time.Time

Expiry returns the credential expiration time, or the zero time if the expiration time isn't known. Used in tests only.

func (*Auto) Login added in v1.8.0

func (c *Auto) Login(t *tailcfg.Oauth2Token, flags LoginFlags)

func (*Auto) Logout added in v1.8.0

func (c *Auto) Logout(ctx context.Context) error

func (*Auto) SetDNS added in v1.10.0

func (c *Auto) SetDNS(ctx context.Context, req *tailcfg.SetDNSRequest) error

SetDNS sends the SetDNSRequest request to the control plane server, requesting a DNS record be created or updated.

func (*Auto) SetHostinfo added in v1.8.0

func (c *Auto) SetHostinfo(hi *tailcfg.Hostinfo)

func (*Auto) SetNetInfo added in v1.8.0

func (c *Auto) SetNetInfo(ni *tailcfg.NetInfo)

func (*Auto) SetPaused added in v1.8.0

func (c *Auto) SetPaused(paused bool)

SetPaused controls whether HTTP activity should be paused.

The client can be paused and unpaused repeatedly, unlike Start and Shutdown, which can only be used once.

func (*Auto) SetStatusFunc added in v1.8.0

func (c *Auto) SetStatusFunc(fn func(Status))

SetStatusFunc sets fn as the callback to run on any status change.

func (*Auto) Shutdown added in v1.8.0

func (c *Auto) Shutdown()

func (*Auto) Start added in v1.8.0

func (c *Auto) Start()

Start starts the client's goroutines.

It should only be called for clients created by NewNoStart.

func (*Auto) StartLogout added in v1.8.0

func (c *Auto) StartLogout()

func (*Auto) TestOnlyNodePublicKey added in v1.8.0

func (c *Auto) TestOnlyNodePublicKey() wgkey.Key

NodePublicKey returns the node public key currently in use. This is used exclusively in tests.

func (*Auto) TestOnlySetAuthKey added in v1.8.0

func (c *Auto) TestOnlySetAuthKey(authkey string)

func (*Auto) TestOnlyTimeNow added in v1.8.0

func (c *Auto) TestOnlyTimeNow() time.Time

func (*Auto) UpdateEndpoints added in v1.8.0

func (c *Auto) UpdateEndpoints(localPort uint16, endpoints []tailcfg.Endpoint)

UpdateEndpoints sets the client's discovered endpoints and sends them to the control server if they've changed.

It does not retain the provided slice.

The localPort field is unused except for integration tests in another repo.

type Client

type Client interface {
	// SetStatusFunc provides a callback to call when control sends us
	// a message.
	SetStatusFunc(func(Status))
	// Shutdown closes this session, which should not be used any further
	// afterwards.
	Shutdown()
	// Login begins an interactive or non-interactive login process.
	// Client will eventually call the Status callback with either a
	// LoginFinished flag (on success) or an auth URL (if further
	// interaction is needed).
	Login(*tailcfg.Oauth2Token, LoginFlags)
	// StartLogout starts an asynchronous logout process.
	// When it finishes, the Status callback will be called while
	// AuthCantContinue()==true.
	StartLogout()
	// Logout starts a synchronous logout process. It doesn't return
	// until the logout operation has been completed.
	Logout(context.Context) error
	// SetPaused pauses or unpauses the controlclient activity as much
	// as possible, without losing its internal state, to minimize
	// unnecessary network activity.
	// TODO: It might be better to simply shutdown the controlclient and
	// make a new one when it's time to unpause.
	SetPaused(bool)
	// AuthCantContinue returns whether authentication is blocked. If it
	// is, you either need to visit the auth URL (previously sent in a
	// Status callback) or call the Login function appropriately.
	// TODO: this probably belongs in the Status itself instead.
	AuthCantContinue() bool
	// SetHostinfo changes the Hostinfo structure that will be sent in
	// subsequent node registration requests.
	// TODO: a server-side change would let us simply upload this
	// in a separate http request. It has nothing to do with the rest of
	// the state machine.
	SetHostinfo(*tailcfg.Hostinfo)
	// SetNetinfo changes the NetIinfo structure that will be sent in
	// subsequent node registration requests.
	// TODO: a server-side change would let us simply upload this
	// in a separate http request. It has nothing to do with the rest of
	// the state machine.
	SetNetInfo(*tailcfg.NetInfo)
	// UpdateEndpoints changes the Endpoint structure that will be sent
	// in subsequent node registration requests.
	// TODO: localPort seems to be obsolete, remove it.
	// TODO: a server-side change would let us simply upload this
	// in a separate http request. It has nothing to do with the rest of
	// the state machine.
	UpdateEndpoints(localPort uint16, endpoints []tailcfg.Endpoint)
	// SetDNS sends the SetDNSRequest request to the control plane server,
	// requesting a DNS record be created or updated.
	SetDNS(context.Context, *tailcfg.SetDNSRequest) error
}

Client represents a client connection to the control server. Currently this is done through a pair of polling https requests in the Auto client, but that might change eventually.

type Decompressor

type Decompressor interface {
	DecodeAll(input, dst []byte) ([]byte, error)
	Close()
}

type Direct

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

Direct is the client that connects to a tailcontrol server for a node.

func NewDirect

func NewDirect(opts Options) (*Direct, error)

NewDirect returns a new Direct client.

func (*Direct) GetPersist

func (c *Direct) GetPersist() persist.Persist

func (*Direct) PollNetMap

func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*netmap.NetworkMap)) error

PollNetMap makes a /map request to download the network map, calling cb with each new netmap.

maxPolls is how many network maps to download; common values are 1 or -1 (to keep a long-poll query open to the server).

func (*Direct) SendLiteMapUpdate added in v1.4.0

func (c *Direct) SendLiteMapUpdate(ctx context.Context) error

SendLiteMapUpdate makes a /map request to update the server of our latest state, but does not fetch anything. It returns an error if the server did not return a successful 200 OK response.

func (*Direct) SetDNS added in v1.10.0

func (c *Direct) SetDNS(ctx context.Context, req *tailcfg.SetDNSRequest) error

SetDNS sends the SetDNSRequest request to the control plane server, requesting a DNS record be created or updated.

func (*Direct) SetEndpoints

func (c *Direct) SetEndpoints(localPort uint16, endpoints []tailcfg.Endpoint) (changed bool)

SetEndpoints updates the list of locally advertised endpoints. It won't be replicated to the server until a *fresh* call to PollNetMap(). You don't need to restart PollNetMap if we return changed==false.

func (*Direct) SetHostinfo

func (c *Direct) SetHostinfo(hi *tailcfg.Hostinfo) bool

SetHostinfo clones the provided Hostinfo and remembers it for the next update. It reports whether the Hostinfo has changed.

func (*Direct) SetNetInfo

func (c *Direct) SetNetInfo(ni *tailcfg.NetInfo) bool

SetNetInfo clones the provided NetInfo and remembers it for the next update. It reports whether the NetInfo has changed.

func (*Direct) TryLogin

func (c *Direct) TryLogin(ctx context.Context, t *tailcfg.Oauth2Token, flags LoginFlags) (url string, err error)

func (*Direct) TryLogout

func (c *Direct) TryLogout(ctx context.Context) error

func (*Direct) WaitLoginURL

func (c *Direct) WaitLoginURL(ctx context.Context, url string) (newURL string, err error)

WaitLoginURL sits in a long poll waiting for the user to authenticate at url.

On success, newURL and err will both be nil.

type LoginFlags

type LoginFlags int

type LoginGoal

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

type Options

type Options struct {
	Persist              persist.Persist               // initial persistent data
	GetMachinePrivateKey func() (wgkey.Private, error) // returns the machine key to use
	ServerURL            string                        // URL of the tailcontrol server
	AuthKey              string                        // optional node auth key for auto registration
	TimeNow              func() time.Time              // time.Now implementation used by Client
	Hostinfo             *tailcfg.Hostinfo             // non-nil passes ownership, nil means to use default using os.Hostname, etc
	DiscoPublicKey       tailcfg.DiscoKey
	NewDecompressor      func() (Decompressor, error)
	KeepAlive            bool
	Logf                 logger.Logf
	HTTPTestClient       *http.Client // optional HTTP client to use (for tests only)
	DebugFlags           []string     // debug settings to send to control
	LinkMonitor          *monitor.Mon // optional link monitor

	// KeepSharerAndUserSplit controls whether the client
	// understands Node.Sharer. If false, the Sharer is mapped to the User.
	KeepSharerAndUserSplit bool

	// SkipIPForwardingCheck declares that the host's IP
	// forwarding works and should not be double-checked by the
	// controlclient package.
	SkipIPForwardingCheck bool

	// Pinger optionally specifies the Pinger to use to satisfy
	// MapResponse.PingRequest queries from the control plane.
	// If nil, PingRequest queries are not answered.
	Pinger Pinger
}

type Pinger added in v1.10.0

type Pinger interface {
	// Ping is a request to start a discovery or TSMP ping with the peer handling
	// the given IP and then call cb with its ping latency & method.
	Ping(ip netaddr.IP, useTSMP bool, cb func(*ipnstate.PingResult))
}

Pinger is a subset of the wgengine.Engine interface, containing just the Ping method.

type State added in v0.98.1

type State int

State is the high-level state of the client. It is used only in unit tests for proper sequencing, don't depend on it anywhere else.

TODO(apenwarr): eliminate the state, as it's now obsolete.

apenwarr: Historical note: controlclient.Auto was originally intended to be the state machine for the whole tailscale client, but that turned out to not be the right abstraction layer, and it moved to ipn.Backend. Since ipn.Backend now has a state machine, it would be much better if controlclient could be a simple stateless API. But the current server-side API (two interlocking polling https calls) makes that very hard to implement. A server side API change could untangle this and remove all the statefulness.

func (State) MarshalText added in v0.98.1

func (s State) MarshalText() ([]byte, error)

func (State) String added in v0.98.1

func (s State) String() string

type Status

type Status struct {
	LoginFinished  *empty.Message // nonempty when login finishes
	LogoutFinished *empty.Message // nonempty when logout finishes
	Err            string
	URL            string             // interactive URL to visit to finish logging in
	NetMap         *netmap.NetworkMap // server-pushed configuration

	// The internal state should not be exposed outside this
	// package, but we have some automated tests elsewhere that need to
	// use them. Please don't use these fields.
	// TODO(apenwarr): Unexport or remove these.
	State    State
	Persist  *persist.Persist  // locally persisted configuration
	Hostinfo *tailcfg.Hostinfo // current Hostinfo data
	// contains filtered or unexported fields
}

func (*Status) Equal

func (s *Status) Equal(s2 *Status) bool

Equal reports whether s and s2 are equal.

func (Status) String

func (s Status) String() string

Jump to

Keyboard shortcuts

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