Documentation
¶
Overview ¶
Package ipn implements the interactions between the Tailscale cloud control plane and the local network stack.
IPN is the abbreviated name for a Tailscale network. What's less clear is what it's an abbreviation for: Identified Private Network? IP Network? Internet Private Network? I Privately Network?
Index ¶
- Constants
- Variables
- func IsReadonlyContext(ctx context.Context) bool
- func ReadMsg(r io.Reader) ([]byte, error)
- func ReadonlyContextOf(ctx context.Context) context.Context
- func SavePrefs(filename string, p *Prefs)
- func WriteMsg(w io.Writer, b []byte) error
- type Backend
- type BackendClient
- func (bc *BackendClient) FakeExpireAfter(x time.Duration)
- func (bc *BackendClient) GotNotifyMsg(b []byte)
- func (bc *BackendClient) Login(token *oauth2.Token)
- func (bc *BackendClient) Logout()
- func (bc *BackendClient) Ping(ip string)
- func (bc *BackendClient) Quit() error
- func (bc *BackendClient) RequestEngineStatus()
- func (bc *BackendClient) RequestStatus()
- func (bc *BackendClient) SetNotifyCallback(fn func(Notify))
- func (bc *BackendClient) SetPrefs(new *Prefs)
- func (bc *BackendClient) SetWantRunning(v bool)
- func (bc *BackendClient) Start(opts Options) error
- func (bc *BackendClient) StartLoginInteractive()
- type BackendServer
- func (bs *BackendServer) GotCommand(ctx context.Context, cmd *Command) error
- func (bs *BackendServer) GotCommandMsg(ctx context.Context, b []byte) error
- func (bs *BackendServer) GotFakeCommand(ctx context.Context, cmd *Command) error
- func (bs *BackendServer) Reset(ctx context.Context) error
- func (bs *BackendServer) SendErrorMessage(msg string)
- func (bs *BackendServer) SendInUseOtherUserErrorMessage(msg string)
- type Command
- type EngineStatus
- type FakeExpireAfterArgs
- type FileStore
- type Handle
- func (h *Handle) AdminPageURL() string
- func (h *Handle) EngineStatus() EngineStatus
- func (h *Handle) Expiry() time.Time
- func (h *Handle) FakeExpireAfter(x time.Duration)
- func (h *Handle) LocalAddrs() []netaddr.IPPrefix
- func (h *Handle) Login(token *oauth2.Token)
- func (h *Handle) Logout()
- func (h *Handle) NetMap() *netmap.NetworkMap
- func (h *Handle) Prefs() *Prefs
- func (h *Handle) RequestEngineStatus()
- func (h *Handle) RequestStatus()
- func (h *Handle) Reset()
- func (h *Handle) Start(opts Options) error
- func (h *Handle) StartLoginInteractive()
- func (h *Handle) State() State
- func (h *Handle) UpdatePrefs(updateFn func(p *Prefs))
- type MemoryStore
- type NoArgs
- type Notify
- type Options
- type PingArgs
- type Prefs
- type SetPrefsArgs
- type StartArgs
- type State
- type StateKey
- type StateStore
Constants ¶
const ( NoState = State(iota) InUseOtherUser NeedsLogin NeedsMachineAuth Stopped Starting Running )
const ( // MachineKeyStateKey is the key under which we store the machine key, // in its wgkey.Private.MarshalText representation. MachineKeyStateKey = StateKey("_machinekey") // GlobalDaemonStateKey is the ipn.StateKey that tailscaled // loads on startup. // // We have to support multiple state keys for other OSes (Windows in // particular), but right now Unix daemons run with a single // node-global state. To keep open the option of having per-user state // later, the global state key doesn't look like a username. GlobalDaemonStateKey = StateKey("_daemon") // ServerModeStartKey's value, if non-empty, is the value of a // StateKey containing the prefs to start with which to start the // server. // // For example, the value might be "user-1234", meaning the // the server should start with the Prefs JSON loaded from // StateKey "user-1234". ServerModeStartKey = StateKey("server-mode-start-key") )
const ErrMsgPermissionDenied = "permission denied"
ErrMsgPermissionDenied is the Notify.ErrMessage value used an operation was done from a user/context that didn't have permission.
const GoogleIDTokenType = "ts_android_google_login"
GoogleIDToken Type is the oauth2.Token.TokenType for the Google ID tokens used by the Android client.
const MaxMessageSize = 10 << 20
MaxMessageSize is the maximum message size, in bytes.
Variables ¶
var ErrStateNotExist = errors.New("no state with given ID")
ErrStateNotExist is returned by StateStore.ReadState when the requested state ID doesn't exist.
Functions ¶
func IsReadonlyContext ¶ added in v1.4.0
IsReadonlyContext reports whether ctx is a read-only context, as currently used by Unix non-root users running the "tailscale" CLI command. They can run "status", but not much else.
func ReadMsg ¶
TODO(apenwarr): incremental json decode?
That would let us avoid storing the whole byte array uselessly in RAM.
func ReadonlyContextOf ¶ added in v1.4.0
ReadonlyContextOf returns ctx wrapped with a context value that will make IsReadonlyContext reports true.
Types ¶
type Backend ¶
type Backend interface {
// Start starts or restarts the backend, typically when a
// frontend client connects.
Start(Options) error
// StartLoginInteractive requests to start a new interactive login
// flow. This should trigger a new BrowseToURL notification
// eventually.
StartLoginInteractive()
// Login logs in with an OAuth2 token.
Login(token *oauth2.Token)
// Logout terminates the current login session and stops the
// wireguard engine.
Logout()
// SetPrefs installs a new set of user preferences, including
// WantRunning. This may cause the wireguard engine to
// reconfigure or stop.
SetPrefs(*Prefs)
// SetWantRunning is like SetPrefs but sets only the
// WantRunning field.
SetWantRunning(wantRunning bool)
// RequestEngineStatus polls for an update from the wireguard
// engine. Only needed if you want to display byte
// counts. Connection events are emitted automatically without
// polling.
RequestEngineStatus()
// RequestStatus requests that a full Status update
// notification is sent.
RequestStatus()
// FakeExpireAfter pretends that the current key is going to
// expire after duration x. This is useful for testing GUIs to
// make sure they react properly with keys that are going to
// expire.
FakeExpireAfter(x time.Duration)
// Ping attempts to start connecting to the given IP and sends a Notify
// with its PingResult. If the host is down, there might never
// be a PingResult sent. The cmd/tailscale CLI client adds a timeout.
Ping(ip string)
}
Backend is the interface between Tailscale frontends (e.g. cmd/tailscale, iOS/MacOS/Windows GUIs) and the tailscale backend (e.g. cmd/tailscaled) running on the same machine. (It has nothing to do with the interface between the backends and the cloud control plane.)
type BackendClient ¶
type BackendClient struct {
// AllowVersionSkew controls whether to allow mismatched
// frontend & backend versions.
AllowVersionSkew bool
// contains filtered or unexported fields
}
func NewBackendClient ¶
func NewBackendClient(logf logger.Logf, sendCommandMsg func(jsonb []byte)) *BackendClient
func (*BackendClient) FakeExpireAfter ¶
func (bc *BackendClient) FakeExpireAfter(x time.Duration)
func (*BackendClient) GotNotifyMsg ¶
func (bc *BackendClient) GotNotifyMsg(b []byte)
func (*BackendClient) Login ¶ added in v1.0.0
func (bc *BackendClient) Login(token *oauth2.Token)
func (*BackendClient) Logout ¶
func (bc *BackendClient) Logout()
func (*BackendClient) Ping ¶ added in v1.2.0
func (bc *BackendClient) Ping(ip string)
func (*BackendClient) Quit ¶
func (bc *BackendClient) Quit() error
func (*BackendClient) RequestEngineStatus ¶
func (bc *BackendClient) RequestEngineStatus()
func (*BackendClient) RequestStatus ¶ added in v0.98.0
func (bc *BackendClient) RequestStatus()
func (*BackendClient) SetNotifyCallback ¶ added in v0.98.0
func (bc *BackendClient) SetNotifyCallback(fn func(Notify))
func (*BackendClient) SetPrefs ¶
func (bc *BackendClient) SetPrefs(new *Prefs)
func (*BackendClient) SetWantRunning ¶ added in v1.2.0
func (bc *BackendClient) SetWantRunning(v bool)
func (*BackendClient) Start ¶
func (bc *BackendClient) Start(opts Options) error
func (*BackendClient) StartLoginInteractive ¶
func (bc *BackendClient) StartLoginInteractive()
type BackendServer ¶
type BackendServer struct {
GotQuit bool // a Quit command was received
// contains filtered or unexported fields
}
func NewBackendServer ¶
func NewBackendServer(logf logger.Logf, b Backend, sendNotifyMsg func(b []byte)) *BackendServer
func (*BackendServer) GotCommand ¶
func (bs *BackendServer) GotCommand(ctx context.Context, cmd *Command) error
func (*BackendServer) GotCommandMsg ¶
func (bs *BackendServer) GotCommandMsg(ctx context.Context, b []byte) error
GotCommandMsg parses the incoming message b as a JSON Command and calls GotCommand with it.
func (*BackendServer) GotFakeCommand ¶ added in v0.98.1
func (bs *BackendServer) GotFakeCommand(ctx context.Context, cmd *Command) error
func (*BackendServer) SendErrorMessage ¶ added in v1.0.0
func (bs *BackendServer) SendErrorMessage(msg string)
func (*BackendServer) SendInUseOtherUserErrorMessage ¶ added in v1.2.1
func (bs *BackendServer) SendInUseOtherUserErrorMessage(msg string)
SendInUseOtherUserErrorMessage sends a Notify message to the client that both sets the state to 'InUseOtherUser' and sets the associated reason to msg.
type Command ¶
type Command struct {
// Version is the binary version of the frontend (the client).
Version string
// AllowVersionSkew controls whether it's permitted for the
// client and server to have a different version. The default
// (false) means to be strict.
AllowVersionSkew bool
// Exactly one of the following must be non-nil.
Quit *NoArgs
Start *StartArgs
StartLoginInteractive *NoArgs
Login *oauth2.Token
Logout *NoArgs
SetPrefs *SetPrefsArgs
SetWantRunning *bool
RequestEngineStatus *NoArgs
RequestStatus *NoArgs
FakeExpireAfter *FakeExpireAfterArgs
Ping *PingArgs
// contains filtered or unexported fields
}
Command is a command message that is JSON encoded and sent by a frontend to a backend.
type EngineStatus ¶
type EngineStatus struct {
RBytes, WBytes int64
NumLive int
LiveDERPs int // number of active DERP connections
LivePeers map[tailcfg.NodeKey]ipnstate.PeerStatusLite
}
EngineStatus contains WireGuard engine stats.
type FakeExpireAfterArgs ¶
type FileStore ¶
type FileStore struct {
// contains filtered or unexported fields
}
FileStore is a StateStore that uses a JSON file for persistence.
func NewFileStore ¶
NewFileStore returns a new file store that persists to path.
type Handle ¶
type Handle struct {
// contains filtered or unexported fields
}
func (*Handle) AdminPageURL ¶
func (*Handle) EngineStatus ¶
func (h *Handle) EngineStatus() EngineStatus
func (*Handle) FakeExpireAfter ¶
func (*Handle) LocalAddrs ¶
func (*Handle) NetMap ¶
func (h *Handle) NetMap() *netmap.NetworkMap
func (*Handle) RequestEngineStatus ¶
func (h *Handle) RequestEngineStatus()
func (*Handle) RequestStatus ¶ added in v0.98.0
func (h *Handle) RequestStatus()
func (*Handle) StartLoginInteractive ¶
func (h *Handle) StartLoginInteractive()
func (*Handle) UpdatePrefs ¶
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is a store that keeps state in memory only.
func (*MemoryStore) ReadState ¶
func (s *MemoryStore) ReadState(id StateKey) ([]byte, error)
ReadState implements the StateStore interface.
func (*MemoryStore) String ¶ added in v1.2.0
func (s *MemoryStore) String() string
func (*MemoryStore) WriteState ¶
func (s *MemoryStore) WriteState(id StateKey, bs []byte) error
WriteState implements the StateStore interface.
type Notify ¶
type Notify struct {
Version string // version number of IPN backend
ErrMessage *string // critical error message, if any; for InUseOtherUser, the details
LoginFinished *empty.Message // event: non-nil when login process succeeded
State *State // current IPN state has changed
Prefs *Prefs // preferences were changed
NetMap *netmap.NetworkMap // new netmap received
Engine *EngineStatus // wireguard engine stats
Status *ipnstate.Status // full status
BrowseToURL *string // UI should open a browser right now
BackendLogID *string // public logtail id used by backend
PingResult *ipnstate.PingResult
// LocalTCPPort, if non-nil, informs the UI frontend which
// (non-zero) localhost TCP port it's listening on.
// This is currently only used by Tailscale when run in the
// macOS Network Extension.
LocalTCPPort *uint16 `json:",omitempty"`
// contains filtered or unexported fields
}
Notify is a communication from a backend (e.g. tailscaled) to a frontend (cmd/tailscale, iOS, macOS, Win Tasktray). In any given notification, any or all of these may be nil, meaning that they have not changed. They are JSON-encoded on the wire, despite the lack of struct tags.
type Options ¶
type Options struct {
// FrontendLogID is the public logtail id used by the frontend.
FrontendLogID string
// StateKey and Prefs together define the state the backend should
// use:
// - StateKey=="" && Prefs!=nil: use Prefs for internal state,
// don't persist changes in the backend, except for the machine key
// for migration purposes.
// - StateKey!="" && Prefs==nil: load the given backend-side
// state and use/update that.
// - StateKey!="" && Prefs!=nil: like the previous case, but do
// an initial overwrite of backend state with Prefs.
StateKey StateKey
Prefs *Prefs
// AuthKey is an optional node auth key used to authorize a
// new node key without user interaction.
AuthKey string
// LegacyConfigPath optionally specifies the old-style relaynode
// relay.conf location. If both LegacyConfigPath and StateKey are
// specified and the requested state doesn't exist in the backend
// store, the backend migrates the config from LegacyConfigPath.
//
// TODO(danderson): remove some time after the transition to
// tailscaled is done.
LegacyConfigPath string
// Notify is called when backend events happen.
Notify func(Notify) `json:"-"`
// HTTPTestClient is an optional HTTP client to pass to controlclient
// (for tests only).
HTTPTestClient *http.Client
}
type Prefs ¶
type Prefs struct {
// ControlURL is the URL of the control server to use.
ControlURL string
// RouteAll specifies whether to accept subnets advertised by
// other nodes on the Tailscale network. Note that this does not
// include default routes (0.0.0.0/0 and ::/0), those are
// controlled by ExitNodeID/IP below.
RouteAll bool
// AllowSingleHosts specifies whether to install routes for each
// node IP on the tailscale network, in addition to a route for
// the whole network.
// This corresponds to the "tailscale up --host-routes" value,
// which defaults to true.
//
// TODO(danderson): why do we have this? It dumps a lot of stuff
// into the routing table, and a single network route _should_ be
// all that we need. But when I turn this off in my tailscaled,
// packets stop flowing. What's up with that?
AllowSingleHosts bool
// ExitNodeID and ExitNodeIP specify the node that should be used
// as an exit node for internet traffic. At most one of these
// should be non-zero.
//
// The preferred way to express the chosen node is ExitNodeID, but
// in some cases it's not possible to use that ID (e.g. in the
// linux CLI, before tailscaled has a netmap). For those
// situations, we allow specifying the exit node by IP, and
// ipnlocal.LocalBackend will translate the IP into an ID when the
// node is found in the netmap.
//
// If the selected exit node doesn't exist (e.g. it's not part of
// the current tailnet), or it doesn't offer exit node services, a
// blackhole route will be installed on the local system to
// prevent any traffic escaping to the local network.
ExitNodeID tailcfg.StableNodeID
ExitNodeIP netaddr.IP
// CorpDNS specifies whether to install the Tailscale network's
// DNS configuration, if it exists.
CorpDNS bool
// WantRunning indicates whether networking should be active on
// this node.
WantRunning bool
// ShieldsUp indicates whether to block all incoming connections,
// regardless of the control-provided packet filter. If false, we
// use the packet filter as provided. If true, we block incoming
// connections. This overrides tailcfg.Hostinfo's ShieldsUp.
ShieldsUp bool
// AdvertiseTags specifies groups that this node wants to join, for
// purposes of ACL enforcement. These can be referenced from the ACL
// security policy. Note that advertising a tag doesn't guarantee that
// the control server will allow you to take on the rights for that
// tag.
AdvertiseTags []string
// Hostname is the hostname to use for identifying the node. If
// not set, os.Hostname is used.
Hostname string
// OSVersion overrides tailcfg.Hostinfo's OSVersion.
OSVersion string
// DeviceModel overrides tailcfg.Hostinfo's DeviceModel.
DeviceModel string
// NotepadURLs is a debugging setting that opens OAuth URLs in
// notepad.exe on Windows, rather than loading them in a browser.
//
// apenwarr 2020-04-29: Unfortunately this is still needed sometimes.
// Windows' default browser setting is sometimes screwy and this helps
// users narrow it down a bit.
NotepadURLs bool
// ForceDaemon specifies whether a platform that normally
// operates in "client mode" (that is, requires an active user
// logged in with the GUI app running) should keep running after the
// GUI ends and/or the user logs out.
//
// The only current applicable platform is Windows. This
// forced Windows to go into "server mode" where Tailscale is
// running even with no users logged in. This might also be
// used for macOS in the future. This setting has no effect
// for Linux/etc, which always operate in daemon mode.
ForceDaemon bool `json:"ForceDaemon,omitempty"`
// AdvertiseRoutes specifies CIDR prefixes to advertise into the
// Tailscale network as reachable through the current
// node.
AdvertiseRoutes []netaddr.IPPrefix
// NoSNAT specifies whether to source NAT traffic going to
// destinations in AdvertiseRoutes. The default is to apply source
// NAT, which makes the traffic appear to come from the router
// machine rather than the peer's Tailscale IP.
//
// Disabling SNAT requires additional manual configuration in your
// network to route Tailscale traffic back to the subnet relay
// machine.
//
// Linux-only.
NoSNAT bool
// NetfilterMode specifies how much to manage netfilter rules for
// Tailscale, if at all.
NetfilterMode preftype.NetfilterMode
// The Persist field is named 'Config' in the file for backward
// compatibility with earlier versions.
// TODO(apenwarr): We should move this out of here, it's not a pref.
// We can maybe do that once we're sure which module should persist
// it (backend or frontend?)
Persist *persist.Persist `json:"Config"`
}
Prefs are the user modifiable settings of the Tailscale node agent.
func LoadPrefs ¶
LoadPrefs loads a legacy relaynode config file into Prefs with sensible migration defaults set.
func PrefsFromBytes ¶
PrefsFromBytes deserializes Prefs from a JSON blob. If enforceDefaults is true, Prefs.RouteAll and Prefs.AllowSingleHosts are forced on.
func (*Prefs) Clone ¶
Clone makes a deep copy of Prefs. The result aliases no memory with the original.
type SetPrefsArgs ¶
type SetPrefsArgs struct {
New *Prefs
}
type StateKey ¶
type StateKey string
StateKey is an opaque identifier for a set of LocalBackend state (preferences, private keys, etc.).
The reason we need this is that the Tailscale agent may be running on a multi-user machine, in a context where a single daemon is shared by several consecutive users. Ideally we would just use the username of the connected frontend as the StateKey.
Various platforms currently set StateKey in different ways:
- the macOS/iOS GUI apps set it to "ipn-go-bridge"
- the Android app sets it to "ipn-android"
- on Windows, it's the empty string (in client mode) or, via LocalBackend.userID, a string like "user-$USER_ID" (used in server mode).
- on Linux/etc, it's always "_daemon" (ipn.GlobalDaemonStateKey)
type StateStore ¶
type StateStore interface {
// ReadState returns the bytes associated with ID. Returns (nil,
// ErrStateNotExist) if the ID doesn't have associated state.
ReadState(id StateKey) ([]byte, error)
// WriteState saves bs as the state associated with ID.
WriteState(id StateKey, bs []byte) error
}
StateStore persists state, and produces it back on request.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package ipnstate captures the entire state of the Tailscale network.
|
Package ipnstate captures the entire state of the Tailscale network. |
|
Package localapi contains the HTTP server handlers for tailscaled's API server.
|
Package localapi contains the HTTP server handlers for tailscaled's API server. |
|
Package policy contains various policy decisions that need to be shared between the node client & control server.
|
Package policy contains various policy decisions that need to be shared between the node client & control server. |