types

package
v0.23.0 Latest Latest
Warning

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

Go to latest
Published: Sep 18, 2024 License: BSD-3-Clause Imports: 30 Imported by: 1

Documentation

Index

Constants

View Source
const (
	SelfUpdateIdentifier = "self-update"
	DatabasePostgres     = "postgres"
	DatabaseSqlite       = "sqlite3"
)
View Source
const (
	PolicyModeDB   = "database"
	PolicyModeFile = "file"
)
View Source
const (
	HTTPTimeout            = 30 * time.Second
	HTTPShutdownTimeout    = 3 * time.Second
	TLSALPN01ChallengeType = "TLS-ALPN-01"
	HTTP01ChallengeType    = "HTTP-01"

	JSONLogFormat = "json"
	TextLogFormat = "text"

	KeepAliveInterval = 60 * time.Second
	MaxHostnameLength = 255
)

Variables

View Source
var (
	NotifyOriginKey   = ctxkey.New("notify.origin", "")
	NotifyHostnameKey = ctxkey.New("notify.hostname", "")
)
View Source
var (
	ErrNodeAddressesInvalid = errors.New("failed to parse node addresses")
	ErrHostnameTooLong      = errors.New("hostname too long, cannot except 255 ASCII chars")
	ErrNodeHasNoGivenName   = errors.New("node has no given name")
	ErrNodeUserHasNoName    = errors.New("node user has no name")
)
View Source
var (
	ErrPolicyNotFound         = errors.New("acl policy not found")
	ErrPolicyUpdateIsDisabled = errors.New("update is disabled for modes other than 'database'")
)
View Source
var (
	ExitRouteV4 = netip.MustParsePrefix("0.0.0.0/0")
	ExitRouteV6 = netip.MustParsePrefix("::/0")
)
View Source
var ErrCannotParsePrefix = errors.New("cannot parse prefix")

Functions

func LoadConfig

func LoadConfig(path string, isFile bool) error

LoadConfig prepares and loads the Headscale configuration into Viper. This means it sets the default values, reads the configuration file and environment variables, and handles deprecated configuration options. It has to be called before LoadServerConfig and LoadCLIConfig. The configuration is not validated and the caller should check for errors using a validation function.

func NotifyCtx

func NotifyCtx(ctx context.Context, origin, hostname string) context.Context

Types

type APIKey

type APIKey struct {
	ID     uint64 `gorm:"primary_key"`
	Prefix string `gorm:"uniqueIndex"`
	Hash   []byte

	CreatedAt  *time.Time
	Expiration *time.Time
	LastSeen   *time.Time
}

APIKey describes the datamodel for API keys used to remotely authenticate with headscale.

func (*APIKey) Proto

func (key *APIKey) Proto() *v1.ApiKey

type CLIConfig

type CLIConfig struct {
	Address  string
	APIKey   string
	Timeout  time.Duration
	Insecure bool
}

type Config

type Config struct {
	ServerURL                      string
	Addr                           string
	MetricsAddr                    string
	GRPCAddr                       string
	GRPCAllowInsecure              bool
	EphemeralNodeInactivityTimeout time.Duration
	PrefixV4                       *netip.Prefix
	PrefixV6                       *netip.Prefix
	IPAllocation                   IPAllocationStrategy
	NoisePrivateKeyPath            string
	BaseDomain                     string
	Log                            LogConfig
	DisableUpdateCheck             bool

	Database DatabaseConfig

	DERP DERPConfig

	TLS TLSConfig

	ACMEURL   string
	ACMEEmail string

	DNSConfig             *tailcfg.DNSConfig
	DNSUserNameInMagicDNS bool

	UnixSocket           string
	UnixSocketPermission fs.FileMode

	OIDC OIDCConfig

	LogTail             LogTailConfig
	RandomizeClientPort bool

	CLI CLIConfig

	Policy PolicyConfig

	Tuning Tuning
}

Config contains the initial Headscale configuration.

func LoadCLIConfig

func LoadCLIConfig() (*Config, error)

LoadCLIConfig returns the needed configuration for the CLI client of Headscale to connect to a Headscale server.

func LoadServerConfig

func LoadServerConfig() (*Config, error)

LoadServerConfig returns the full Headscale configuration to host a Headscale server. This is called as part of `headscale serve`.

type DERPConfig

type DERPConfig struct {
	ServerEnabled                      bool
	AutomaticallyAddEmbeddedDerpRegion bool
	ServerRegionID                     int
	ServerRegionCode                   string
	ServerRegionName                   string
	ServerPrivateKeyPath               string
	STUNAddr                           string
	URLs                               []url.URL
	Paths                              []string
	AutoUpdate                         bool
	UpdateFrequency                    time.Duration
	IPv4                               string
	IPv6                               string
}

type DNSConfig

type DNSConfig struct {
	MagicDNS           bool   `mapstructure:"magic_dns"`
	BaseDomain         string `mapstructure:"base_domain"`
	Nameservers        Nameservers
	SearchDomains      []string            `mapstructure:"search_domains"`
	ExtraRecords       []tailcfg.DNSRecord `mapstructure:"extra_records"`
	UserNameInMagicDNS bool                `mapstructure:"use_username_in_magic_dns"`
}

type DatabaseConfig

type DatabaseConfig struct {
	// Type sets the database type, either "sqlite3" or "postgres"
	Type  string
	Debug bool

	// Type sets the gorm configuration
	Gorm GormConfig

	Sqlite   SqliteConfig
	Postgres PostgresConfig
}

type GormConfig

type GormConfig struct {
	Debug                 bool
	SlowThreshold         time.Duration
	SkipErrRecordNotFound bool
	ParameterizedQueries  bool
	PrepareStmt           bool
}

type IPAllocationStrategy

type IPAllocationStrategy string
const (
	IPAllocationStrategySequential IPAllocationStrategy = "sequential"
	IPAllocationStrategyRandom     IPAllocationStrategy = "random"
)

type IPPrefix

type IPPrefix netip.Prefix

func (*IPPrefix) Scan

func (i *IPPrefix) Scan(destination interface{}) error

func (IPPrefix) Value

func (i IPPrefix) Value() (driver.Value, error)

Value return json value, implement driver.Valuer interface.

type IPPrefixes

type IPPrefixes []netip.Prefix

func (*IPPrefixes) Scan

func (i *IPPrefixes) Scan(destination interface{}) error

func (IPPrefixes) Value

func (i IPPrefixes) Value() (driver.Value, error)

Value return json value, implement driver.Valuer interface.

type LetsEncryptConfig

type LetsEncryptConfig struct {
	Listen        string
	Hostname      string
	CacheDir      string
	ChallengeType string
}

type LogConfig

type LogConfig struct {
	Format string
	Level  zerolog.Level
}

type LogTailConfig

type LogTailConfig struct {
	Enabled bool
}

type Nameservers

type Nameservers struct {
	Global []string
	Split  map[string][]string
}

type Node

type Node struct {
	ID NodeID `gorm:"primary_key"`

	// MachineKeyDatabaseField is the string representation of MachineKey
	// it is _only_ used for reading and writing the key to the
	// database and should not be used.
	// Use MachineKey instead.
	MachineKeyDatabaseField string            `gorm:"column:machine_key;unique_index"`
	MachineKey              key.MachinePublic `gorm:"-"`

	// NodeKeyDatabaseField is the string representation of NodeKey
	// it is _only_ used for reading and writing the key to the
	// database and should not be used.
	// Use NodeKey instead.
	NodeKeyDatabaseField string         `gorm:"column:node_key"`
	NodeKey              key.NodePublic `gorm:"-"`

	// DiscoKeyDatabaseField is the string representation of DiscoKey
	// it is _only_ used for reading and writing the key to the
	// database and should not be used.
	// Use DiscoKey instead.
	DiscoKeyDatabaseField string          `gorm:"column:disco_key"`
	DiscoKey              key.DiscoPublic `gorm:"-"`

	// EndpointsDatabaseField is the string list representation of Endpoints
	// it is _only_ used for reading and writing the key to the
	// database and should not be used.
	// Use Endpoints instead.
	EndpointsDatabaseField StringList       `gorm:"column:endpoints"`
	Endpoints              []netip.AddrPort `gorm:"-"`

	// EndpointsDatabaseField is the string list representation of Endpoints
	// it is _only_ used for reading and writing the key to the
	// database and should not be used.
	// Use Endpoints instead.
	HostinfoDatabaseField string            `gorm:"column:host_info"`
	Hostinfo              *tailcfg.Hostinfo `gorm:"-"`

	// IPv4DatabaseField is the string representation of v4 address,
	// it is _only_ used for reading and writing the key to the
	// database and should not be used.
	// Use V4 instead.
	IPv4DatabaseField sql.NullString `gorm:"column:ipv4"`
	IPv4              *netip.Addr    `gorm:"-"`

	// IPv6DatabaseField is the string representation of v4 address,
	// it is _only_ used for reading and writing the key to the
	// database and should not be used.
	// Use V6 instead.
	IPv6DatabaseField sql.NullString `gorm:"column:ipv6"`
	IPv6              *netip.Addr    `gorm:"-"`

	// Hostname represents the name given by the Tailscale
	// client during registration
	Hostname string

	// Givenname represents either:
	// a DNS normalized version of Hostname
	// a valid name set by the User
	//
	// GivenName is the name used in all DNS related
	// parts of headscale.
	GivenName string `gorm:"type:varchar(63);unique_index"`
	UserID    uint
	User      User `gorm:"constraint:OnDelete:CASCADE;"`

	RegisterMethod string

	ForcedTags StringList

	// TODO(kradalby): This seems like irrelevant information?
	AuthKeyID *uint64     `sql:"DEFAULT:NULL"`
	AuthKey   *PreAuthKey `gorm:"constraint:OnDelete:SET NULL;"`

	LastSeen *time.Time
	Expiry   *time.Time

	Routes []Route `gorm:"constraint:OnDelete:CASCADE;"`

	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt *time.Time

	IsOnline *bool `gorm:"-"`
}

Node is a Headscale client.

func (*Node) AfterFind

func (node *Node) AfterFind(tx *gorm.DB) error

AfterFind is a hook that ensures that Node objects fields that has a different type in the database is unwrapped and populated correctly. This currently unmarshals all the keys, stored as strings, into the proper types.

func (*Node) AppendToIPSet

func (node *Node) AppendToIPSet(build *netipx.IPSetBuilder)

AppendToIPSet adds the individual ips in NodeAddresses to a given netipx.IPSetBuilder.

func (*Node) ApplyPeerChange

func (node *Node) ApplyPeerChange(change *tailcfg.PeerChange)

ApplyPeerChange takes a PeerChange struct and updates the node.

func (*Node) BeforeSave

func (node *Node) BeforeSave(tx *gorm.DB) error

BeforeSave is a hook that ensures that some values that cannot be directly marshalled into database values are stored correctly in the database. This currently means storing the keys as strings.

func (*Node) CanAccess

func (node *Node) CanAccess(filter []tailcfg.FilterRule, node2 *Node) bool

func (*Node) GetFQDN

func (node *Node) GetFQDN(cfg *Config, baseDomain string) (string, error)

func (*Node) IPs

func (node *Node) IPs() []netip.Addr

func (*Node) IPsAsString

func (node *Node) IPsAsString() []string

func (*Node) InIPSet

func (node *Node) InIPSet(set *netipx.IPSet) bool

func (*Node) IsEphemeral

func (node *Node) IsEphemeral() bool

IsEphemeral returns if the node is registered as an Ephemeral node. https://tailscale.com/kb/1111/ephemeral-nodes/

func (Node) IsExpired

func (node Node) IsExpired() bool

IsExpired returns whether the node registration has expired.

func (*Node) PeerChangeFromMapRequest

func (node *Node) PeerChangeFromMapRequest(req tailcfg.MapRequest) tailcfg.PeerChange

PeerChangeFromMapRequest takes a MapRequest and compares it to the node to produce a PeerChange struct that can be used to updated the node and inform peers about smaller changes to the node. When a field is added to this function, remember to also add it to: - node.ApplyPeerChange - logTracePeerChange in poll.go.

func (*Node) Prefixes

func (node *Node) Prefixes() []netip.Prefix

func (*Node) Proto

func (node *Node) Proto() *v1.Node

func (*Node) RegisterMethodToV1Enum

func (node *Node) RegisterMethodToV1Enum() v1.RegisterMethod

type NodeID

type NodeID uint64

func (NodeID) NodeID

func (id NodeID) NodeID() tailcfg.NodeID

func (NodeID) StableID

func (id NodeID) StableID() tailcfg.StableNodeID

func (NodeID) String

func (id NodeID) String() string

func (NodeID) Uint64

func (id NodeID) Uint64() uint64

type Nodes

type Nodes []*Node

func (Nodes) FilterByIP

func (nodes Nodes) FilterByIP(ip netip.Addr) Nodes

func (Nodes) IDMap

func (nodes Nodes) IDMap() map[NodeID]*Node

func (Nodes) String

func (nodes Nodes) String() string

type OIDCConfig

type OIDCConfig struct {
	OnlyStartIfOIDCIsAvailable bool
	Issuer                     string
	ClientID                   string
	ClientSecret               string
	Scope                      []string
	ExtraParams                map[string]string
	AllowedDomains             []string
	AllowedUsers               []string
	AllowedGroups              []string
	StripEmaildomain           bool
	Expiry                     time.Duration
	UseExpiryFromToken         bool
}

type Policy

type Policy struct {
	gorm.Model

	// Data contains the policy in HuJSON format.
	Data string
}

Policy represents a policy in the database.

type PolicyConfig

type PolicyConfig struct {
	Path string
	Mode PolicyMode
}

type PolicyMode

type PolicyMode string

type PostgresConfig

type PostgresConfig struct {
	Host                string
	Port                int
	Name                string
	User                string
	Pass                string
	Ssl                 string
	MaxOpenConnections  int
	MaxIdleConnections  int
	ConnMaxIdleTimeSecs int
}

type PreAuthKey

type PreAuthKey struct {
	ID        uint64 `gorm:"primary_key"`
	Key       string
	UserID    uint
	User      User `gorm:"constraint:OnDelete:CASCADE;"`
	Reusable  bool
	Ephemeral bool               `gorm:"default:false"`
	Used      bool               `gorm:"default:false"`
	ACLTags   []PreAuthKeyACLTag `gorm:"constraint:OnDelete:CASCADE;"`

	CreatedAt  *time.Time
	Expiration *time.Time
}

PreAuthKey describes a pre-authorization key usable in a particular user.

func (*PreAuthKey) Proto

func (key *PreAuthKey) Proto() *v1.PreAuthKey

type PreAuthKeyACLTag

type PreAuthKeyACLTag struct {
	ID           uint64 `gorm:"primary_key"`
	PreAuthKeyID uint64
	Tag          string
}

PreAuthKeyACLTag describes an autmatic tag applied to a node when registered with the associated PreAuthKey.

type Route

type Route struct {
	gorm.Model

	NodeID uint64
	Node   Node

	// TODO(kradalby): change this custom type to netip.Prefix
	Prefix IPPrefix

	Advertised bool
	Enabled    bool
	IsPrimary  bool
}

func (*Route) IsAnnouncable

func (r *Route) IsAnnouncable() bool

func (*Route) IsExitRoute

func (r *Route) IsExitRoute() bool

func (*Route) String

func (r *Route) String() string

type Routes

type Routes []Route

func (Routes) PrefixMap

func (rs Routes) PrefixMap() map[IPPrefix][]Route

func (Routes) Prefixes

func (rs Routes) Prefixes() []netip.Prefix

func (Routes) Primaries

func (rs Routes) Primaries() Routes

Primaries returns Primary routes from a list of routes.

func (Routes) Proto

func (rs Routes) Proto() []*v1.Route

type SqliteConfig

type SqliteConfig struct {
	Path          string
	WriteAheadLog bool
}

type StateUpdate

type StateUpdate struct {
	// The type of update
	Type StateUpdateType

	// ChangeNodes must be set when Type is StatePeerAdded
	// and StatePeerChanged and contains the full node
	// object for added nodes.
	ChangeNodes []NodeID

	// ChangePatches must be set when Type is StatePeerChangedPatch
	// and contains a populated PeerChange object.
	ChangePatches []*tailcfg.PeerChange

	// Removed must be set when Type is StatePeerRemoved and
	// contain a list of the nodes that has been removed from
	// the network.
	Removed []NodeID

	// DERPMap must be set when Type is StateDERPUpdated and
	// contain the new DERP Map.
	DERPMap *tailcfg.DERPMap

	// Additional message for tracking origin or what being
	// updated, useful for ambiguous updates like StatePeerChanged.
	Message string
}

StateUpdate is an internal message containing information about a state change that has happened to the network. If type is StateFullUpdate, all fields are ignored.

func StateUpdateExpire

func StateUpdateExpire(nodeID NodeID, expiry time.Time) StateUpdate

func (*StateUpdate) Empty

func (su *StateUpdate) Empty() bool

Empty reports if there are any updates in the StateUpdate.

type StateUpdateType

type StateUpdateType int
const (
	StateFullUpdate StateUpdateType = iota
	// StatePeerChanged is used for updates that needs
	// to be calculated with all peers and all policy rules.
	// This would typically be things that include tags, routes
	// and similar.
	StatePeerChanged
	StatePeerChangedPatch
	StatePeerRemoved
	// StateSelfUpdate is used to indicate that the node
	// has changed in control, and the client needs to be
	// informed.
	// The updated node is inside the ChangeNodes field
	// which should have a length of one.
	StateSelfUpdate
	StateDERPUpdated
)

func (StateUpdateType) String

func (su StateUpdateType) String() string

type StringList

type StringList []string

func (*StringList) Scan

func (i *StringList) Scan(destination interface{}) error

func (StringList) Value

func (i StringList) Value() (driver.Value, error)

Value return json value, implement driver.Valuer interface.

type TLSConfig

type TLSConfig struct {
	CertPath string
	KeyPath  string

	LetsEncrypt LetsEncryptConfig
}

type Tuning

type Tuning struct {
	NotifierSendTimeout            time.Duration
	BatchChangeDelay               time.Duration
	NodeMapSessionBufferedChanSize int
}

type User

type User struct {
	gorm.Model
	Name string `gorm:"unique"`
}

User is the way Headscale implements the concept of users in Tailscale

At the end of the day, users in Tailscale are some kind of 'bubbles' or users that contain our machines.

func (*User) Proto

func (n *User) Proto() *v1.User

func (*User) TailscaleLogin

func (u *User) TailscaleLogin() *tailcfg.Login

func (*User) TailscaleUser

func (u *User) TailscaleUser() *tailcfg.User

func (*User) TailscaleUserProfile

func (u *User) TailscaleUserProfile() tailcfg.UserProfile

Jump to

Keyboard shortcuts

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