| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- // Copyright 2019 the Kilo authors
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package mesh
- import (
- "context"
- "net"
- "time"
- "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
- "github.com/squat/kilo/pkg/wireguard"
- )
- const (
- // checkInPeriod is how often nodes should check-in.
- checkInPeriod = 30 * time.Second
- // DefaultKiloInterface is the default interface created and used by Kilo.
- DefaultKiloInterface = "kilo0"
- // DefaultKiloPort is the default UDP port Kilo uses.
- DefaultKiloPort = 51820
- // DefaultCNIPath is the default path to the CNI config file.
- DefaultCNIPath = "/etc/cni/net.d/10-kilo.conflist"
- )
- // DefaultKiloSubnet is the default CIDR for Kilo.
- var DefaultKiloSubnet = &net.IPNet{IP: []byte{10, 4, 0, 0}, Mask: []byte{255, 255, 0, 0}}
- // Granularity represents the abstraction level at which the network
- // should be meshed.
- type Granularity string
- const (
- // LogicalGranularity indicates that the network should create
- // a mesh between logical locations, e.g. data-centers, but not between
- // all nodes within a single location.
- LogicalGranularity Granularity = "location"
- // FullGranularity indicates that the network should create
- // a mesh between every node.
- FullGranularity Granularity = "full"
- // AutoGranularity can be used with kgctl to obtain
- // the granularity automatically.
- AutoGranularity Granularity = "auto"
- )
- // Node represents a node in the network.
- type Node struct {
- Endpoint *wireguard.Endpoint
- Key wgtypes.Key
- NoInternalIP bool
- InternalIP *net.IPNet
- CNICompatibilityIP *net.IPNet
- // LastSeen is a Unix time for the last time
- // the node confirmed it was live.
- LastSeen int64
- // Leader is a suggestion to Kilo that
- // the node wants to lead its segment.
- Leader bool
- Location string
- Name string
- PersistentKeepalive time.Duration
- Subnet *net.IPNet
- WireGuardIP *net.IPNet
- // DiscoveredEndpoints cannot be DNS endpoints, only net.UDPAddr.
- DiscoveredEndpoints map[string]*net.UDPAddr
- AllowedLocationIPs []net.IPNet
- Granularity Granularity
- }
- // Ready indicates whether or not the node is ready.
- func (n *Node) Ready() bool {
- // Nodes that are not leaders will not have WireGuardIPs, so it is not required.
- return n != nil &&
- n.Endpoint.Ready() &&
- n.Key != wgtypes.Key{} &&
- n.Subnet != nil &&
- time.Now().Unix()-n.LastSeen < int64(checkInPeriod)*2/int64(time.Second)
- }
- // Peer represents a peer in the network.
- type Peer struct {
- wireguard.Peer
- Name string
- }
- // Ready indicates whether or not the peer is ready.
- // Peers can have empty endpoints because they may not have an
- // IP, for example if they are behind a NAT, and thus
- // will not declare their endpoint and instead allow it to be
- // discovered.
- func (p *Peer) Ready() bool {
- return p != nil &&
- p.AllowedIPs != nil &&
- len(p.AllowedIPs) != 0 &&
- p.PublicKey != wgtypes.Key{} // If Key was not set, it will be wgtypes.Key{}.
- }
- // EventType describes what kind of an action an event represents.
- type EventType string
- const (
- // AddEvent represents an action where an item was added.
- AddEvent EventType = "add"
- // DeleteEvent represents an action where an item was removed.
- DeleteEvent EventType = "delete"
- // UpdateEvent represents an action where an item was updated.
- UpdateEvent EventType = "update"
- )
- // NodeEvent represents an event concerning a node in the cluster.
- type NodeEvent struct {
- Type EventType
- Node *Node
- Old *Node
- }
- // PeerEvent represents an event concerning a peer in the cluster.
- type PeerEvent struct {
- Type EventType
- Peer *Peer
- Old *Peer
- }
- // Backend can create clients for all of the
- // primitive types that Kilo deals with, namely:
- // * nodes; and
- // * peers.
- type Backend interface {
- Nodes() NodeBackend
- Peers() PeerBackend
- }
- // NodeBackend can get nodes by name, init itself,
- // list the nodes that should be meshed,
- // set Kilo properties for a node,
- // clean up any changes applied to the backend,
- // and watch for changes to nodes.
- type NodeBackend interface {
- CleanUp(context.Context, string) error
- Get(string) (*Node, error)
- Init(context.Context) error
- List() ([]*Node, error)
- Set(context.Context, string, *Node) error
- Watch() <-chan *NodeEvent
- }
- // PeerBackend can get peers by name, init itself,
- // list the peers that should be in the mesh,
- // set fields for a peer,
- // clean up any changes applied to the backend,
- // and watch for changes to peers.
- type PeerBackend interface {
- CleanUp(context.Context, string) error
- Get(string) (*Peer, error)
- Init(context.Context) error
- List() ([]*Peer, error)
- Set(context.Context, string, *Peer) error
- Watch() <-chan *PeerEvent
- }
|