vnet

package
v1.77.0-pre Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2024 License: BSD-3-Clause Imports: 55 Imported by: 1

Documentation

Overview

Package vnet simulates a virtual Internet containing a set of networks with various NAT behaviors. You can then plug VMs into the virtual internet at different points to test Tailscale working end-to-end in various network conditions.

See https://github.com/tailscale/tailscale/issues/13038

Index

Constants

View Source
const (
	ProtocolQEMU      = Protocol(iota + 1)
	ProtocolUnixDGRAM // for macOS Virtualization.Framework and VZFileHandleNetworkDeviceAttachment
)

Variables

This section is empty.

Functions

func FakeDNSIPv4 added in v1.74.0

func FakeDNSIPv4() netip.Addr

FakeDNSIPv4 returns the fake DNS IPv4 address.

func FakeDNSIPv6 added in v1.74.0

func FakeDNSIPv6() netip.Addr

FakeDNSIPv6 returns the fake DNS IPv6 address.

func FakeSyslogIPv4 added in v1.74.0

func FakeSyslogIPv4() netip.Addr

FakeSyslogIPv4 returns the fake syslog IPv4 address.

func FakeSyslogIPv6 added in v1.74.0

func FakeSyslogIPv6() netip.Addr

FakeSyslogIPv6 returns the fake syslog IPv6 address.

Types

type Config

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

Config is the requested state of the natlab virtual network.

The zero value is a valid empty configuration. Call AddNode and AddNetwork to methods on the returned Node and Network values to modify the config before calling NewServer. Once the NewServer is called, Config is no longer used.

func (*Config) AddNetwork

func (c *Config) AddNetwork(opts ...any) *Network

AddNetwork add a new network.

The opts may be of the following types:

  • string IP address, for the network's WAN IP (if any)
  • string netip.Prefix, for the network's LAN IP (defaults to 192.168.0.0/24) if IPv4, or its WAN IPv6 + CIDR (e.g. "2000:52::1/64")
  • NAT, the type of NAT to use
  • NetworkService, a service to add to the network

On an error or unknown opt type, AddNetwork returns a network with a carried error that gets returned later.

func (*Config) AddNode

func (c *Config) AddNode(opts ...any) *Node

AddNode creates a new node in the world.

The opts may be of the following types:

  • *Network: zero, one, or more networks to add this node to
  • TODO: more

On an error or unknown opt type, AddNode returns a node with a carried error that gets returned later.

func (*Config) FirstNetwork

func (c *Config) FirstNetwork() *Network

FirstNetwork returns the first network in the config, or nil if none.

func (*Config) Nodes added in v1.74.0

func (c *Config) Nodes() iter.Seq2[int, *Node]

func (*Config) NumNodes

func (c *Config) NumNodes() int

NumNodes returns the number of nodes in the configuration.

func (*Config) SetBlendReality added in v1.74.0

func (c *Config) SetBlendReality(v bool)

SetBlendReality sets whether to blend the real controlplane.tailscale.com and DERP servers into the virtual network. This is mostly useful for interactive testing when working on natlab.

func (*Config) SetPCAPFile

func (c *Config) SetPCAPFile(file string)

SetPCAPFile sets the filename to write a pcap file to, or empty to disable pcap file writing.

type DialFunc

type DialFunc func(ctx context.Context, network, address string) (net.Conn, error)

type EthernetPacket

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

func (EthernetPacket) DstMAC

func (ep EthernetPacket) DstMAC() MAC

func (EthernetPacket) SrcMAC

func (ep EthernetPacket) SrcMAC() MAC

type IPPool

type IPPool interface {
	// WANIP returns the primary WAN IP address.
	//
	// TODO: add another method for networks with multiple WAN IP addresses.
	WANIP() netip.Addr

	// SoleLanIP reports whether this network has a sole LAN client
	// and if so, its IP address.
	SoleLANIP() (_ netip.Addr, ok bool)

	// IsPublicPortUsed reports whether the provided WAN IP+port is in use by
	// anything. (In particular, the NAT-PMP/etc port mappers might have taken
	// a port.) Implementations should check this before allocating a port,
	// and then they should report IsPublicPortUsed themselves for that port.
	IsPublicPortUsed(netip.AddrPort) bool
}

IPPool is the interface that a NAT implementation uses to get information about a network.

Outside of tests, this is typically a *network.

type MAC

type MAC [6]byte

func (MAC) HWAddr

func (m MAC) HWAddr() net.HardwareAddr

func (MAC) IsBroadcast

func (m MAC) IsBroadcast() bool

func (MAC) IsIPv6Multicast added in v1.74.0

func (m MAC) IsIPv6Multicast() bool

IsIPv6Multicast reports whether m is an IPv6 multicast MAC address, typically one containing a solicited-node multicast address.

func (MAC) String

func (m MAC) String() string

type NAT

type NAT string

NAT is a type of NAT that's known to natlab.

For example, "easy" for Linux-style NAT, "hard" for FreeBSD-style NAT, etc.

const (
	One2OneNAT NAT = "one2one"
	EasyNAT    NAT = "easy"   // address+port filtering
	EasyAFNAT  NAT = "easyaf" // address filtering (not port)
	HardNAT    NAT = "hard"
)

type NATTable

type NATTable interface {
	// PickOutgoingSrc returns the source address to use for an outgoing packet.
	//
	// The result should either be invalid (to drop the packet) or a WAN (not
	// private) IP address.
	//
	// Typically, the src is a LAN source IP address, but it might also be a WAN
	// IP address if the packet is being forwarded for a source machine that has
	// a public IP address.
	PickOutgoingSrc(src, dst netip.AddrPort, at time.Time) (wanSrc netip.AddrPort)

	// PickIncomingDst returns the destination address to use for an incoming
	// packet. The incoming src address is always a public WAN IP.
	//
	// The result should either be invalid (to drop the packet) or the IP
	// address of a machine on the local network address, usually a private
	// LAN IP.
	PickIncomingDst(src, dst netip.AddrPort, at time.Time) (lanDst netip.AddrPort)

	// IsPublicPortUsed reports whether the provided WAN IP+port is in use by
	// anything. The port mapper uses this to avoid grabbing an in-use port.
	IsPublicPortUsed(netip.AddrPort) bool
}

NATTable is what a NAT implementation is expected to do.

This project tests Tailscale as it faces various combinations various NAT implementations (e.g. Linux easy style NAT vs FreeBSD hard/endpoint dependent NAT vs Cloud 1:1 NAT, etc)

Implementations of NATTable need not handle concurrency; the natlab serializes all calls into a NATTable.

The provided `at` value will typically be time.Now, except for tests. Implementations should not use real time and should only compare previously provided time values.

type Network

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

Network is the configuration of a network in the virtual network.

func (*Network) AddService

func (n *Network) AddService(s NetworkService)

AddService adds a network service (such as port mapping protocols) to a network.

func (*Network) CanTakeMoreNodes

func (n *Network) CanTakeMoreNodes() bool

func (*Network) CanV4 added in v1.74.0

func (n *Network) CanV4() bool

func (*Network) CanV6 added in v1.74.0

func (n *Network) CanV6() bool

func (*Network) SetBlackholedIPv4 added in v1.74.0

func (n *Network) SetBlackholedIPv4(v bool)

SetBlackholedIPv4 sets whether the network should blackhole all IPv4 traffic out to the Internet. (DHCP etc continues to work on the LAN.)

type NetworkService

type NetworkService string

NetworkService is a service that can be added to a network.

const (
	NATPMP NetworkService = "NAT-PMP"
	PCP    NetworkService = "PCP"
	UPnP   NetworkService = "UPnP"
)

type Node

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

Node is the configuration of a node in the virtual network.

func (*Node) Env

func (n *Node) Env() []TailscaledEnv

func (*Node) HostFirewall

func (n *Node) HostFirewall() bool

func (*Node) IsV6Only added in v1.74.0

func (n *Node) IsV6Only() bool

IsV6Only reports whether this node is only connected to IPv6 networks.

func (*Node) MAC

func (n *Node) MAC() MAC

MAC returns the MAC address of the node.

func (*Node) Network

func (n *Node) Network() *Network

Network returns the first network this node is connected to, or nil if none.

func (*Node) Num

func (n *Node) Num() int

Num returns the 1-based node number.

func (*Node) SetVerboseSyslog

func (n *Node) SetVerboseSyslog(v bool)

func (*Node) String

func (n *Node) String() string

String returns the string "nodeN" where N is the 1-based node number.

func (*Node) VerboseSyslog

func (n *Node) VerboseSyslog() bool

type NodeAgentClient

type NodeAgentClient struct {
	*tailscale.LocalClient
	HTTPClient *http.Client
}

func (*NodeAgentClient) EnableHostFirewall

func (c *NodeAgentClient) EnableHostFirewall(ctx context.Context) error

EnableHostFirewall enables the host's stateful firewall.

type NodeOption

type NodeOption string

NodeOption is an option that can be passed to Config.AddNode.

const (
	HostFirewall  NodeOption = "HostFirewall"
	VerboseSyslog NodeOption = "VerboseSyslog"
)

type Protocol

type Protocol int

type Server

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

func New

func New(c *Config) (*Server, error)

func (*Server) Close

func (s *Server) Close()

func (*Server) HWAddr

func (s *Server) HWAddr(mac MAC) net.HardwareAddr

func (*Server) MACs added in v1.74.0

func (s *Server) MACs() iter.Seq[MAC]

MACs returns the MAC addresses of the configured nodes.

func (*Server) NodeAgentClient

func (s *Server) NodeAgentClient(n *Node) *NodeAgentClient

func (*Server) NodeAgentDialer

func (s *Server) NodeAgentDialer(n *Node) DialFunc

func (*Server) PopulateDERPMapIPs

func (s *Server) PopulateDERPMapIPs() error

func (*Server) RegisterSinkForTest added in v1.74.0

func (s *Server) RegisterSinkForTest(mac MAC, fn func(eth []byte))

func (*Server) RegisteredWritersForTest added in v1.74.0

func (s *Server) RegisteredWritersForTest() int

RegisteredWritersForTest returns the number of registered connections (VM guests with a known MAC to whom a packet can be sent) there are to the server. It exists for testing.

func (*Server) ServeUnixConn

func (s *Server) ServeUnixConn(uc *net.UnixConn, proto Protocol)

Handles a single connection from a QEMU-style client or muxd connections for dgram mode

func (*Server) SetLoggerForTest added in v1.74.0

func (s *Server) SetLoggerForTest(logf func(format string, args ...any))

func (*Server) WriteStartingBanner

func (s *Server) WriteStartingBanner(w io.Writer)

type TailscaledEnv

type TailscaledEnv struct {
	Key, Value string
}

TailscaledEnv is а option that can be passed to Config.AddNode to set an environment variable for tailscaled.

type UDPPacket

type UDPPacket struct {
	Src     netip.AddrPort
	Dst     netip.AddrPort
	Payload []byte // everything after UDP header
}

UDPPacket is a UDP packet.

For the purposes of this project, a UDP packet (not a general IP packet) is the unit to be NAT'ed, as that's all that Tailscale uses.

Jump to

Keyboard shortcuts

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