Documentation
¶
Overview ¶
Package magicsock implements a socket that can change its communication path while in use, actively searching for the best way to communicate.
Index ¶
- Variables
- type Conn
- func (c *Conn) Bind() conn.Bind
- func (c *Conn) Close() error
- func (c *Conn) DERPs() int
- func (c *Conn) DebugBreakDERPConns() error
- func (c *Conn) DebugForcePreferDERP(n int)
- func (c *Conn) DebugPickNewDERP() error
- func (c *Conn) DiscoPublicKey() key.DiscoPublic
- func (c *Conn) DontFragSetting() (bool, error)
- func (c *Conn) GetEndpointChanges(peer tailcfg.NodeView) ([]EndpointChange, error)
- func (c *Conn) GetLastNetcheckReport(ctx context.Context) *netcheck.Report
- func (c *Conn) HandleDiscoKeyAdvertisement(node tailcfg.NodeView, update packet.TSMPDiscoKeyAdvertisement)
- func (c *Conn) InstallCaptureHook(cb packet.CaptureCallback)
- func (c *Conn) LastRecvActivityOfNodeKey(nk key.NodePublic) string
- func (c *Conn) LocalPort() uint16
- func (c *Conn) ParseEndpoint(nodeKeyStr string) (conn.Endpoint, error)
- func (c *Conn) PeerMTUEnabled() bool
- func (c *Conn) PeerRelays() set.Set[netip.Addr]
- func (c *Conn) Ping(peer tailcfg.NodeView, res *ipnstate.PingResult, size int, ...)
- func (c *Conn) ReSTUN(why string)
- func (c *Conn) Rebind()
- func (c *Conn) RotateDiscoKey()
- func (c *Conn) Send(buffs [][]byte, ep conn.Endpoint, offset int) (err error)
- func (c *Conn) ServeHTTPDebug(w http.ResponseWriter, r *http.Request)
- func (c *Conn) SetConnectionCounter(fn netlogfunc.ConnectionCounter)
- func (c *Conn) SetDERPMap(dm *tailcfg.DERPMap)
- func (c *Conn) SetDebugLoggingEnabled(v bool)
- func (c *Conn) SetHomeless(v bool)
- func (c *Conn) SetLastNetcheckReportForTest(ctx context.Context, report *netcheck.Report)
- func (c *Conn) SetNetInfoCallback(fn func(*tailcfg.NetInfo))
- func (c *Conn) SetNetworkUp(up bool)
- func (c *Conn) SetOnlyTCP443(v bool)
- func (c *Conn) SetPreferredPort(port uint16)
- func (c *Conn) SetPrivateKey(privateKey key.NodePrivate) error
- func (c *Conn) SetProbeUDPLifetime(v bool)
- func (c *Conn) SetSilentDisco(v bool)
- func (c *Conn) SetStaticEndpoints(ep views.Slice[netip.AddrPort])
- func (c *Conn) ShouldPMTUD() bool
- func (c *Conn) SilentDisco() bool
- func (c *Conn) Synchronize()
- func (c *Conn) UpdatePMTUD()
- func (c *Conn) UpdatePeers(newPeers set.Set[key.NodePublic])
- func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder)
- type EndpointChange
- type FilterUpdate
- type NewDiscoKeyAvailable
- type NodeMutationsUpdate
- type NodeViewsUpdate
- type Options
- type Path
- type ProbeUDPLifetimeConfig
- type RebindingUDPConn
- func (c *RebindingUDPConn) Close() error
- func (c *RebindingUDPConn) LocalAddr() *net.UDPAddr
- func (c *RebindingUDPConn) Port() uint16
- func (c *RebindingUDPConn) ReadBatch(msgs []ipv6.Message, flags int) (int, error)
- func (c *RebindingUDPConn) ReadFromUDPAddrPort(b []byte) (int, netip.AddrPort, error)
- func (c *RebindingUDPConn) SyscallConn() (syscall.RawConn, error)
- func (c *RebindingUDPConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error)
- func (c *RebindingUDPConn) WriteWireGuardBatchTo(buffs [][]byte, addr epAddr, offset int) error
- type UDPRelayAllocReq
- type UDPRelayAllocResp
Constants ¶
This section is empty.
Variables ¶
var MaxDiscoPingSize = tstun.MaxPacketSize - 20 - 8
MaxDiscoPingSize is the largest useful ping message size that we can send - the maximum packet size minus the IPv4 and UDP headers.
Functions ¶
This section is empty.
Types ¶
type Conn ¶
type Conn struct {
// contains filtered or unexported fields
}
A Conn routes UDP packets and actively manages a list of its endpoints.
func NewConn ¶
NewConn creates a magic Conn listening on opts.Port. As the set of possible endpoints for a Conn changes, the callback opts.EndpointsFunc is called.
func (*Conn) Close ¶
Close closes the connection.
Only the first close does anything. Any later closes return nil.
func (*Conn) DebugBreakDERPConns ¶
DebugBreakDERPConns breaks all DERP connections for debug/testing reasons.
func (*Conn) DebugForcePreferDERP ¶
func (*Conn) DebugPickNewDERP ¶
DebugPickNewDERP picks a new DERP random home temporarily (even if just for seconds) and reports it to control. It exists to test DERP home changes and netmap deltas, etc. It serves no useful user purpose.
func (*Conn) DiscoPublicKey ¶
func (c *Conn) DiscoPublicKey() key.DiscoPublic
DiscoPublicKey returns the discovery public key.
func (*Conn) DontFragSetting ¶
DontFragSetting returns true if at least one of the underlying sockets of this connection is a UDP socket with the don't fragment bit set, otherwise it returns false. It also returns an error if either connection returned an error other than errUnsupportedConnType.
func (*Conn) GetEndpointChanges ¶
func (c *Conn) GetEndpointChanges(peer tailcfg.NodeView) ([]EndpointChange, error)
GetEndpointChanges returns the most recent changes for a particular endpoint. The returned EndpointChange structs are for debug use only and there are no guarantees about order, size, or content.
func (*Conn) GetLastNetcheckReport ¶
GetLastNetcheckReport returns the last netcheck report, returning nil if a recent one does not exist.
func (*Conn) HandleDiscoKeyAdvertisement ¶
func (c *Conn) HandleDiscoKeyAdvertisement(node tailcfg.NodeView, update packet.TSMPDiscoKeyAdvertisement)
HandleDiscoKeyAdvertisement processes a TSMP disco key update. The update may be solicited (in response to a request) or unsolicited. node is the Tailscale tailcfg.NodeView of the peer that sent the update.
func (*Conn) InstallCaptureHook ¶
func (c *Conn) InstallCaptureHook(cb packet.CaptureCallback)
InstallCaptureHook installs a callback which is called to log debug information into the pcap stream. This function can be called with a nil argument to uninstall the capture hook.
func (*Conn) LastRecvActivityOfNodeKey ¶
func (c *Conn) LastRecvActivityOfNodeKey(nk key.NodePublic) string
LastRecvActivityOfNodeKey describes the time we last got traffic from this endpoint (updated every ~10 seconds).
func (*Conn) ParseEndpoint ¶
ParseEndpoint implements conn.Bind; it's called by WireGuard to connect to an endpoint.
See https://pkg.go.dev/golang.zx2c4.com/wireguard/conn#Bind.ParseEndpoint
func (*Conn) PeerMTUEnabled ¶
PeerMTUEnabled reports whether peer path MTU discovery is enabled.
func (*Conn) PeerRelays ¶
PeerRelays returns the current set of candidate peer relays.
func (*Conn) Ping ¶
func (c *Conn) Ping(peer tailcfg.NodeView, res *ipnstate.PingResult, size int, cb func(*ipnstate.PingResult))
Ping handles a "tailscale ping" CLI query.
func (*Conn) ReSTUN ¶
ReSTUN triggers an address discovery. The provided why string is for debug logging only. If Conn.staticEndpoints have been updated, calling ReSTUN will also result in the new endpoints being advertised.
func (*Conn) Rebind ¶
func (c *Conn) Rebind()
Rebind closes and re-binds the UDP sockets and resets the DERP connection. It should be followed by a call to ReSTUN.
func (*Conn) RotateDiscoKey ¶
func (c *Conn) RotateDiscoKey()
RotateDiscoKey generates a new discovery key pair and updates the connection to use it. This invalidates all existing disco sessions and will cause peers to re-establish discovery sessions with the new key. Addtionally, the lastTSMPDiscoAdvertisement on all endpoints is reset to 0.
This is primarily for debugging and testing purposes, a future enhancement should provide a mechanism for seamless rotation by supporting short term use of the old key.
func (*Conn) Send ¶
Send implements conn.Bind.
See https://pkg.go.dev/github.com/tailscale/wireguard-go/conn#Bind.Send
func (*Conn) ServeHTTPDebug ¶
func (c *Conn) ServeHTTPDebug(w http.ResponseWriter, r *http.Request)
ServeHTTPDebug serves an HTML representation of the innards of c for debugging.
It's accessible either from tailscaled's debug port (at /debug/magicsock) or via peerapi to a peer that's owned by the same user (so they can e.g. inspect their phones).
func (*Conn) SetConnectionCounter ¶
func (c *Conn) SetConnectionCounter(fn netlogfunc.ConnectionCounter)
SetConnectionCounter specifies a per-connection statistics aggregator. Nil may be specified to disable statistics gathering.
func (*Conn) SetDERPMap ¶
SetDERPMap controls which (if any) DERP servers are used. A nil value means to disable DERP; it's disabled by default.
func (*Conn) SetDebugLoggingEnabled ¶
SetDebugLoggingEnabled controls whether spammy debug logging is enabled.
Note that this is currently independent from the log levels, even though they're pretty correlated: debugging logs should be [v1] (or higher), but some non-debug logs may also still have a [vN] annotation. The [vN] level controls which gets shown in stderr. The dlogf method, on the other hand, controls which gets even printed or uploaded at any level.
func (*Conn) SetHomeless ¶
SetHomeless sets whether magicsock should idle harder and not have a DERP home connection active and not search for its nearest DERP home. In this homeless mode, the node is unreachable by others.
func (*Conn) SetLastNetcheckReportForTest ¶
SetLastNetcheckReportForTest sets the magicsock conn's last netcheck report. Used for testing purposes.
func (*Conn) SetNetInfoCallback ¶
SetNetInfoCallback sets the func to be called whenever the network conditions change.
At most one func can be registered; the most recent one replaces any previous registration.
This is called by LocalBackend.
func (*Conn) SetNetworkUp ¶
func (*Conn) SetOnlyTCP443 ¶
SetOnlyTCP443 set whether the magicsock connection is restricted to only using TCP port 443 outbound. If true, no UDP is allowed, no STUN checks are performend, etc.
func (*Conn) SetPreferredPort ¶
SetPreferredPort sets the connection's preferred local port.
func (*Conn) SetPrivateKey ¶
func (c *Conn) SetPrivateKey(privateKey key.NodePrivate) error
SetPrivateKey sets the connection's private key.
This is only used to be able prove our identity when connecting to DERP servers.
If the private key changes, any DERP connections are torn down & recreated when needed.
func (*Conn) SetProbeUDPLifetime ¶
SetProbeUDPLifetime toggles probing of UDP lifetime based on v.
func (*Conn) SetSilentDisco ¶
SetSilentDisco toggles silent disco based on v.
func (*Conn) SetStaticEndpoints ¶
SetStaticEndpoints sets static endpoints to the provided value and triggers an asynchronous update of the endpoints that this node advertises. Static endpoints are endpoints explicitly configured by user.
func (*Conn) ShouldPMTUD ¶
ShouldPMTUD returns true if this client should try to enable peer MTU discovery, false otherwise.
func (*Conn) SilentDisco ¶
SilentDisco returns true if silent disco is enabled, otherwise false.
func (*Conn) Synchronize ¶
func (c *Conn) Synchronize()
Synchronize waits for all eventbus events published prior to this call to be processed by the receiver.
func (*Conn) UpdatePMTUD ¶
func (c *Conn) UpdatePMTUD()
UpdatePMTUD configures the underlying sockets of this Conn to enable or disable peer path MTU discovery according to the current configuration.
Enabling or disabling peer path MTU discovery requires setting the don't fragment bit on its two underlying pconns. There are three distinct results for this operation on each pconn:
1. Success 2. Failure (not supported on this platform, or supported but failed) 3. Not a UDP socket (most likely one of IPv4 or IPv6 couldn't be used)
To simplify the fast path for the most common case, we set the PMTUD status of the overall Conn according to the results of setting the sockopt on pconn as follows:
1. Both setsockopts succeed: PMTUD status update succeeds 2. One succeeds, one returns not a UDP socket: PMTUD status update succeeds 4. Neither setsockopt succeeds: PMTUD disabled 3. Either setsockopt fails: PMTUD disabled
If the PMTUD settings changed, it resets the endpoint state so that it will re-probe path MTUs to this peer.
func (*Conn) UpdatePeers ¶
func (c *Conn) UpdatePeers(newPeers set.Set[key.NodePublic])
UpdatePeers is called when the set of WireGuard peers changes. It then removes any state for old peers.
The caller passes ownership of newPeers map to UpdatePeers.
func (*Conn) UpdateStatus ¶
func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder)
UpdateStatus implements the interface needed by ipnstate.StatusBuilder.
This method adds in the magicsock-specific information only. Most of the status is otherwise populated by LocalBackend.
type EndpointChange ¶
type EndpointChange struct {
When time.Time // when the change occurred
What string // what this change is
From any `json:",omitempty"` // information about the previous state
To any `json:",omitempty"` // information about the new state
}
EndpointChange is a structure containing information about changes made to a particular endpoint. This is not a stable interface and could change at any time.
type FilterUpdate ¶
FilterUpdate represents an update event for a *filter.Filter. This event is signaled over an eventbus.Bus. magicsock.Conn is the sole subscriber as of 2025-06. If you are adding more subscribers consider moving this type out of magicsock.
type NewDiscoKeyAvailable ¶
NewDiscoKeyAvailable is an eventbus topic that is emitted when we're sending a packet to a node and observe we haven't told it our current DiscoKey before.
The publisher is magicsock, when we're sending a packet. The subscriber is userspaceEngine, which sends a TSMP packet, also via magicsock. This doesn't recurse infinitely because we only publish it once per DiscoKey. In the common case, a DiscoKey is not rotated within a process generation (as of 2026-01-21), except with debug commands to simulate process restarts.
The address is the first node address (tailscale address) of the node. It does not matter if the address is v4/v6, the receiver should handle either.
Since we have not yet communicated with the node at the time we are sending this event, the resulting TSMPDiscoKeyAdvertisement will with all likelihood be transmitted via DERP.
type NodeMutationsUpdate ¶
type NodeMutationsUpdate struct {
Mutations []netmap.NodeMutation
}
NodeMutationsUpdate represents an update event of one or more netmap.NodeMutation. This event is published over an eventbus.Bus. magicsock.Conn is the sole subscriber as of 2025-06. If you are adding more subscribers consider moving this type out of magicsock.
type NodeViewsUpdate ¶
type NodeViewsUpdate struct {
SelfNode tailcfg.NodeView
Peers []tailcfg.NodeView // sorted by Node.ID
}
NodeViewsUpdate represents an update event of tailcfg.NodeView for all nodes. This event is published over an eventbus.Bus. It may be published with an invalid SelfNode, and/or zero/nil Peers. magicsock.Conn is the sole subscriber as of 2025-06. If you are adding more subscribers consider moving this type out of magicsock.
type Options ¶
type Options struct {
// EventBus, if non-nil, is used for event publication and subscription by
// each Conn created from these Options. It must not be nil outside of
// tests.
EventBus *eventbus.Bus
// Logf provides a log function to use. It must not be nil.
// Use [logger.Discard] to disrcard logs.
Logf logger.Logf
// Port is the port to listen on.
// Zero means to pick one automatically.
Port uint16
// EndpointsFunc optionally provides a func to be called when
// endpoints change. The called func does not own the slice.
EndpointsFunc func([]tailcfg.Endpoint)
// DERPActiveFunc optionally provides a func to be called when
// a connection is made to a DERP server.
DERPActiveFunc func()
// IdleFunc optionally provides a func to return how long
// it's been since a TUN packet was sent or received.
IdleFunc func() time.Duration
// TestOnlyPacketListener optionally specifies how to create PacketConns.
// Only used by tests.
TestOnlyPacketListener nettype.PacketListener
// NoteRecvActivity, if provided, is a func for magicsock to call
// whenever it receives a packet from a a peer if it's been more
// than ~10 seconds since the last one. (10 seconds is somewhat
// arbitrary; the sole user, lazy WireGuard configuration,
// just doesn't need or want it called on
// every packet, just every minute or two for WireGuard timeouts,
// and 10 seconds seems like a good trade-off between often enough
// and not too often.)
// The provided func is likely to call back into
// Conn.ParseEndpoint, which acquires Conn.mu. As such, you should
// not hold Conn.mu while calling it.
NoteRecvActivity func(key.NodePublic)
// NetMon is the network monitor to use.
// It must be non-nil.
NetMon *netmon.Monitor
// HealthTracker optionally specifies the health tracker to
// report errors and warnings to.
HealthTracker *health.Tracker
// Metrics specifies the metrics registry to record metrics to.
Metrics *usermetric.Registry
// ControlKnobs are the set of control knobs to use.
// If nil, they're ignored and not updated.
ControlKnobs *controlknobs.Knobs
// PeerByKeyFunc optionally specifies a function to look up a peer's
// WireGuard state by its public key. If nil, it's not used.
// In regular use, this will be wgengine.(*userspaceEngine).PeerByKey.
PeerByKeyFunc func(key.NodePublic) (_ wgint.Peer, ok bool)
// DisablePortMapper, if true, disables the portmapper.
// This is primarily useful in tests.
DisablePortMapper bool
}
Options contains options for Listen.
type ProbeUDPLifetimeConfig ¶
type ProbeUDPLifetimeConfig struct {
// The timeout cliffs to probe. Values are in ascending order. Ascending
// order is chosen over descending because we have limited opportunities to
// probe. With a descending order we are stuck waiting for a new UDP
// path/session if the first value times out. When that new path is
// established is anyone's guess.
Cliffs []time.Duration
// CycleCanStartEvery represents the min duration between cycles starting
// up.
CycleCanStartEvery time.Duration
}
ProbeUDPLifetimeConfig represents the configuration for probing UDP path lifetime.
func (*ProbeUDPLifetimeConfig) Equals ¶
func (p *ProbeUDPLifetimeConfig) Equals(b *ProbeUDPLifetimeConfig) bool
Equals returns true if b equals p, otherwise false. If both sides are nil, Equals returns true. If only one side is nil, Equals returns false.
func (*ProbeUDPLifetimeConfig) Valid ¶
func (p *ProbeUDPLifetimeConfig) Valid() bool
Valid returns true if p is valid, otherwise false. p must be non-nil.
type RebindingUDPConn ¶
type RebindingUDPConn struct {
// contains filtered or unexported fields
}
RebindingUDPConn is a UDP socket that can be re-bound. Unix has no notion of re-binding a socket, so we swap it out for a new one.
func (*RebindingUDPConn) Close ¶
func (c *RebindingUDPConn) Close() error
func (*RebindingUDPConn) LocalAddr ¶
func (c *RebindingUDPConn) LocalAddr() *net.UDPAddr
func (*RebindingUDPConn) Port ¶
func (c *RebindingUDPConn) Port() uint16
func (*RebindingUDPConn) ReadBatch ¶
ReadBatch is an alias for batching.Conn.ReadBatch with fallback to single packet operations if c.pconn is not a batching.Conn.
func (*RebindingUDPConn) ReadFromUDPAddrPort ¶
ReadFromUDPAddrPort reads a packet from c into b. It returns the number of bytes copied and the source address.
func (*RebindingUDPConn) SyscallConn ¶
func (c *RebindingUDPConn) SyscallConn() (syscall.RawConn, error)
func (*RebindingUDPConn) WriteToUDPAddrPort ¶
func (*RebindingUDPConn) WriteWireGuardBatchTo ¶
func (c *RebindingUDPConn) WriteWireGuardBatchTo(buffs [][]byte, addr epAddr, offset int) error
WriteWireGuardBatchTo writes buffs to addr. It serves primarily as an alias for batching.Conn.WriteBatchTo, with fallback to single packet operations if c.pconn is not a batching.Conn.
WriteWireGuardBatchTo assumes buffs are WireGuard packets, which is notable for Geneve encapsulation: Geneve protocol is set to packet.GeneveProtocolWireGuard, and the control bit is left unset.
type UDPRelayAllocReq ¶
type UDPRelayAllocReq struct {
// RxFromNodeKey is the unauthenticated (DERP server claimed src) node key
// of the transmitting party, noted at disco message reception time over
// DERP. This node key is unambiguously-aligned with RxFromDiscoKey being
// that the disco message is received over DERP.
RxFromNodeKey key.NodePublic
// RxFromDiscoKey is the disco key of the transmitting party, noted and
// authenticated at reception time.
RxFromDiscoKey key.DiscoPublic
// Message is the disco message.
Message *disco.AllocateUDPRelayEndpointRequest
}
UDPRelayAllocReq represents a *disco.AllocateUDPRelayEndpointRequest reception event. This is signaled over an eventbus.Bus from magicsock.Conn towards [relayserver.extension].
type UDPRelayAllocResp ¶
type UDPRelayAllocResp struct {
// ReqRxFromNodeKey is copied from [UDPRelayAllocReq.RxFromNodeKey]. It
// enables peer lookup leading up to transmission over DERP.
ReqRxFromNodeKey key.NodePublic
// ReqRxFromDiscoKey is copied from [UDPRelayAllocReq.RxFromDiscoKey].
ReqRxFromDiscoKey key.DiscoPublic
// Message is the disco message.
Message *disco.AllocateUDPRelayEndpointResponse
}
UDPRelayAllocResp represents a *disco.AllocateUDPRelayEndpointResponse that is yet to be transmitted over DERP (or delivered locally if ReqRxFromNodeKey is self). This is signaled over an eventbus.Bus from [relayserver.extension] towards magicsock.Conn.