tstun

package
v1.79.0-mod Latest Latest
Warning

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

Go to latest
Published: Dec 9, 2024 License: BSD-3-Clause Imports: 53 Imported by: 0

Documentation

Overview

Package tun creates a tuntap device, working around OS-specific quirks if necessary.

Index

Constants

View Source
const FakeTUNName = "FakeTUN"

FakeTUNName is the name of the fake TUN device.

View Source
const MaxPacketSize = device.MaxContentSize

MaxPacketSize is the maximum size (in bytes) of a packet that can be injected into a tstun.Wrapper.

View Source
const PacketStartOffset = device.MessageTransportHeaderSize

PacketStartOffset is the minimal amount of leading space that must exist before &packet[offset] in a packet passed to Read, Write, or InjectInboundDirect. This is necessary to avoid reallocation in wireguard-go internals.

Variables

View Source
var (
	// ErrClosed is returned when attempting an operation on a closed Wrapper.
	ErrClosed = errors.New("device closed")
	// ErrFiltered is returned when the acted-on packet is rejected by a filter.
	ErrFiltered = errors.New("packet dropped by filter")
)
View Source
var WireMTUsToProbe = []WireMTU{
	WireMTU(safeTUNMTU),
	TUNToWireMTU(safeTUNMTU),
	1400,
	1500,
	8000,
	9000,
}

WireMTUsToProbe is a list of the on-the-wire MTUs we want to probe. Each time magicsock discovery begins, it will send a set of pings, one of each size listed below.

Functions

func Diagnose

func Diagnose(logf logger.Logf, tunName string, err error)

Diagnose tries to explain a tuntap device creation failure. It pokes around the system and logs some diagnostic info that might help debug why tun creation failed. Because device creation has already failed and the program's about to end, log a lot.

The tunName is the name of the tun device that was requested but failed. The err error is how the tun creation failed.

func New

func New(logf logger.Logf, tunName string) (tun.Device, string, error)

New returns a tun.Device for the requested device name, along with the OS-dependent name that was allocated to the device.

func NewFake

func NewFake() tun.Device

NewFake returns a tun.Device that does nothing.

Types

type FilterFunc

type FilterFunc func(*packet.Parsed, *Wrapper) filter.Response

FilterFunc is a packet-filtering function with access to the Wrapper device. It must not hold onto the packet struct, as its backing storage will be reused.

type GROFilterFunc

type GROFilterFunc func(p *packet.Parsed, w *Wrapper, g *gro.GRO) (filter.Response, *gro.GRO)

GROFilterFunc is a FilterFunc extended with a *gro.GRO, enabling increased throughput where GRO is supported by a packet.Parsed interceptor, e.g. netstack/gVisor, and we are handling a vector of packets. Callers must pass a nil g for the first packet in a given vector, and continue passing the returned *gro.GRO for all remaining packets in said vector. If the returned *gro.GRO is non-nil after the last packet for a given vector is passed through the GROFilterFunc, the caller must also call Flush() on it to deliver any previously Enqueue()'d packets.

type TUNMTU

type TUNMTU uint32

TUNMTU is the MTU for the tailscale TUN.

func DefaultTUNMTU

func DefaultTUNMTU() TUNMTU

DefaultTUNMTU returns the MTU we use to set the Tailscale TUN MTU. It is also the path MTU that we default to if we have no information about the path to a peer.

1. If set, the value of TS_DEBUG_MTU clamped to a maximum of MaxTUNMTU 2. If TS_DEBUG_ENABLE_PMTUD is set, the maximum size MTU we probe, minus wg overhead 3. If TS_DEBUG_ENABLE_PMTUD is not set, the Safe MTU

func WireToTUNMTU

func WireToTUNMTU(w WireMTU) TUNMTU

WireToTUNMTU takes the MTU of an underlying network device and returns the largest possible MTU for a Tailscale TUN operating on top of that device, given that we have to add wireguard headers.

type WireMTU

type WireMTU uint32

WireMTU is the MTU for the underlying network devices.

func DefaultWireMTU

func DefaultWireMTU() WireMTU

DefaultWireMTU returns the default TUN MTU, adjusted for wireguard overhead.

func SafeWireMTU

func SafeWireMTU() WireMTU

SafeWireMTU returns the wire MTU that is safe to use if we have no information about the path MTU to this peer.

func TUNToWireMTU

func TUNToWireMTU(t TUNMTU) WireMTU

TUNToWireMTU takes the MTU that the Tailscale TUN presents to the user and returns the on-the-wire MTU necessary to transmit the largest packet that will fit through the TUN, given that we have to add wireguard headers.

type Wrapper

type Wrapper struct {

	// PreFilterPacketInboundFromWireGuard is the inbound filter function that runs before the main filter
	// and therefore sees the packets that may be later dropped by it.
	PreFilterPacketInboundFromWireGuard FilterFunc
	// PostFilterPacketInboundFromWireGuard is the inbound filter function that runs after the main filter.
	PostFilterPacketInboundFromWireGuard GROFilterFunc
	// PreFilterPacketOutboundToWireGuardNetstackIntercept is a filter function that runs before the main filter
	// for packets from the local system. This filter is populated by netstack to hook
	// packets that should be handled by netstack. If set, this filter runs before
	// PreFilterFromTunToEngine.
	PreFilterPacketOutboundToWireGuardNetstackIntercept GROFilterFunc
	// PreFilterPacketOutboundToWireGuardEngineIntercept is a filter function that runs before the main filter
	// for packets from the local system. This filter is populated by wgengine to hook
	// packets which it handles internally. If both this and PreFilterFromTunToNetstack
	// filter functions are non-nil, this filter runs second.
	PreFilterPacketOutboundToWireGuardEngineIntercept FilterFunc
	// PostFilterPacketOutboundToWireGuard is the outbound filter function that runs after the main filter.
	PostFilterPacketOutboundToWireGuard FilterFunc

	// OnTSMPPongReceived, if non-nil, is called whenever a TSMP pong arrives.
	OnTSMPPongReceived func(packet.TSMPPongReply)

	// OnICMPEchoResponseReceived, if non-nil, is called whenever a ICMP echo response
	// arrives. If the packet is to be handled internally this returns true,
	// false otherwise.
	OnICMPEchoResponseReceived func(*packet.Parsed) bool

	// PeerAPIPort, if non-nil, returns the peerapi port that's
	// running for the given IP address.
	PeerAPIPort func(netip.Addr) (port uint16, ok bool)
	// contains filtered or unexported fields
}

Wrapper augments a tun.Device with packet filtering and injection.

A Wrapper starts in a "corked" mode where Read calls are blocked until the Wrapper's Start method is called.

func Wrap

func Wrap(logf logger.Logf, tdev tun.Device, m *usermetric.Registry) *Wrapper

func WrapTAP

func WrapTAP(logf logger.Logf, tdev tun.Device, m *usermetric.Registry) *Wrapper

func (*Wrapper) BatchSize

func (t *Wrapper) BatchSize() int

func (*Wrapper) Close

func (t *Wrapper) Close() error

func (*Wrapper) Events

func (t *Wrapper) Events() <-chan tun.Event

Events returns a TUN event channel that contains all non-Up, non-Down events. It is named Events because it is the set of events that we want to expose to wireguard-go, and Events is the name specified by the wireguard-go tun.Device interface.

func (*Wrapper) EventsUpDown

func (t *Wrapper) EventsUpDown() chan tun.Event

EventsUpDown returns a TUN event channel that contains all Up and Down events.

func (*Wrapper) File

func (t *Wrapper) File() *os.File

func (*Wrapper) GetFilter

func (t *Wrapper) GetFilter() *filter.Filter

func (*Wrapper) GetJailedFilter

func (t *Wrapper) GetJailedFilter() *filter.Filter

func (*Wrapper) IdleDuration

func (t *Wrapper) IdleDuration() time.Duration

IdleDuration reports how long it's been since the last read or write to this device.

Its value should only be presumed accurate to roughly 10ms granularity. If there's never been activity, the duration is since the wrapper was created.

func (*Wrapper) InjectInboundCopy

func (t *Wrapper) InjectInboundCopy(packet []byte) error

InjectInboundCopy takes a packet without leading space, reallocates it to conform to the InjectInboundDirect interface and calls InjectInboundDirect on it. Injecting a nil packet is a no-op.

func (*Wrapper) InjectInboundDirect

func (t *Wrapper) InjectInboundDirect(buf []byte, offset int) error

InjectInboundDirect makes the Wrapper device behave as if a packet with the given contents was received from the network. It blocks and does not take ownership of the packet. The injected packet will not pass through inbound filters.

The packet contents are to start at &buf[offset]. offset must be greater or equal to PacketStartOffset. The space before &buf[offset] will be used by WireGuard.

func (*Wrapper) InjectInboundPacketBuffer

func (t *Wrapper) InjectInboundPacketBuffer(pkt *stack.PacketBuffer, buffs [][]byte, sizes []int) error

InjectInboundPacketBuffer makes the Wrapper device behave as if a packet (pkt) with the given contents was received from the network. It takes ownership of one reference count on pkt. The injected packet will not pass through inbound filters.

pkt will be copied into buffs before writing to the underlying tun.Device. Therefore, callers must allocate and pass a buffs slice that is sized appropriately for holding pkt.Size() + PacketStartOffset as a single element (buffs[0]) and split across multiple elements if the originating stack supports GSO. sizes must be sized with similar consideration, len(buffs) should be equal to len(sizes). If any len(buffs[<index>]) was mutated by InjectInboundPacketBuffer it will be reset to cap(buffs[<index>]) before returning.

This path is typically used to deliver synthesized packets to the host networking stack.

func (*Wrapper) InjectOutbound

func (t *Wrapper) InjectOutbound(pkt []byte) error

InjectOutbound makes the Wrapper device behave as if a packet with the given contents was sent to the network. It does not block, but takes ownership of the packet. The injected packet will not pass through outbound filters. Injecting an empty packet is a no-op.

func (*Wrapper) InjectOutboundPacketBuffer

func (t *Wrapper) InjectOutboundPacketBuffer(pkt *stack.PacketBuffer) error

InjectOutboundPacketBuffer logically behaves as InjectOutbound. It takes ownership of one reference count on the packet, and the packet may be mutated. The packet refcount will be decremented after the injected buffer has been read.

func (*Wrapper) InstallCaptureHook

func (t *Wrapper) InstallCaptureHook(cb capture.Callback)

func (*Wrapper) MTU

func (t *Wrapper) MTU() (int, error)

func (*Wrapper) Name

func (t *Wrapper) Name() (string, error)

func (*Wrapper) Read

func (t *Wrapper) Read(buffs [][]byte, sizes []int, offset int) (int, error)

func (*Wrapper) SetDestIPActivityFuncs

func (t *Wrapper) SetDestIPActivityFuncs(m map[netip.Addr]func())

SetDestIPActivityFuncs sets a map of funcs to run per packet destination (the map keys).

The map ownership passes to the Wrapper. It must be non-nil.

func (*Wrapper) SetDiscoKey

func (t *Wrapper) SetDiscoKey(k key.DiscoPublic)

SetDiscoKey sets the current discovery key.

It is only used for filtering out bogus traffic when network stack(s) get confused; see Issue 1526.

func (*Wrapper) SetFilter

func (t *Wrapper) SetFilter(filt *filter.Filter)

func (*Wrapper) SetJailedFilter

func (t *Wrapper) SetJailedFilter(filt *filter.Filter)

func (*Wrapper) SetLinkFeaturesPostUp

func (t *Wrapper) SetLinkFeaturesPostUp()

SetLinkFeaturesPostUp configures link features on t based on select TS_TUN_ environment variables and OS feature tests. Callers should ensure t is up prior to calling, otherwise OS feature tests may be inconclusive.

func (*Wrapper) SetStatistics

func (t *Wrapper) SetStatistics(stats *connstats.Statistics)

SetStatistics specifies a per-connection statistics aggregator. Nil may be specified to disable statistics gathering.

func (*Wrapper) SetWGConfig

func (t *Wrapper) SetWGConfig(wcfg *wgcfg.Config)

SetWGConfig is called when a new NetworkMap is received.

func (*Wrapper) Start

func (w *Wrapper) Start()

Start unblocks any Wrapper.Read calls that have already started and makes the Wrapper functional.

Start must be called exactly once after the various Tailscale subsystems have been wired up to each other.

func (*Wrapper) Unwrap

func (t *Wrapper) Unwrap() tun.Device

Unwrap returns the underlying tun.Device.

func (*Wrapper) Write

func (t *Wrapper) Write(buffs [][]byte, offset int) (int, error)

Write accepts incoming packets. The packets begin at buffs[:][offset:], like wireguard-go/tun.Device.Write. Write is called per-peer via wireguard-go/device.Peer.RoutineSequentialReceiver, so it MUST be thread-safe.

Jump to

Keyboard shortcuts

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