backend.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Copyright 2019 the Kilo authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package mesh
  15. import (
  16. "context"
  17. "net"
  18. "time"
  19. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  20. "github.com/squat/kilo/pkg/wireguard"
  21. )
  22. const (
  23. // checkInPeriod is how often nodes should check-in.
  24. checkInPeriod = 30 * time.Second
  25. // DefaultKiloInterface is the default interface created and used by Kilo.
  26. DefaultKiloInterface = "kilo0"
  27. // DefaultKiloPort is the default UDP port Kilo uses.
  28. DefaultKiloPort = 51820
  29. // DefaultCNIPath is the default path to the CNI config file.
  30. DefaultCNIPath = "/etc/cni/net.d/10-kilo.conflist"
  31. )
  32. // DefaultKiloSubnet is the default CIDR for Kilo.
  33. var DefaultKiloSubnet = &net.IPNet{IP: []byte{10, 4, 0, 0}, Mask: []byte{255, 255, 0, 0}}
  34. // Granularity represents the abstraction level at which the network
  35. // should be meshed.
  36. type Granularity string
  37. const (
  38. // LogicalGranularity indicates that the network should create
  39. // a mesh between logical locations, e.g. data-centers, but not between
  40. // all nodes within a single location.
  41. LogicalGranularity Granularity = "location"
  42. // FullGranularity indicates that the network should create
  43. // a mesh between every node.
  44. FullGranularity Granularity = "full"
  45. // AutoGranularity can be used with kgctl to obtain
  46. // the granularity automatically.
  47. AutoGranularity Granularity = "auto"
  48. )
  49. // Node represents a node in the network.
  50. type Node struct {
  51. Endpoint *wireguard.Endpoint
  52. Key wgtypes.Key
  53. NoInternalIP bool
  54. InternalIP *net.IPNet
  55. CNICompatibilityIP *net.IPNet
  56. // LastSeen is a Unix time for the last time
  57. // the node confirmed it was live.
  58. LastSeen int64
  59. // Leader is a suggestion to Kilo that
  60. // the node wants to lead its segment.
  61. Leader bool
  62. Location string
  63. Name string
  64. PersistentKeepalive time.Duration
  65. Subnet *net.IPNet
  66. WireGuardIP *net.IPNet
  67. // DiscoveredEndpoints cannot be DNS endpoints, only net.UDPAddr.
  68. DiscoveredEndpoints map[string]*net.UDPAddr
  69. AllowedLocationIPs []net.IPNet
  70. Granularity Granularity
  71. }
  72. // Ready indicates whether or not the node is ready.
  73. func (n *Node) Ready() bool {
  74. // Nodes that are not leaders will not have WireGuardIPs, so it is not required.
  75. return n != nil &&
  76. n.Endpoint.Ready() &&
  77. n.Key != wgtypes.Key{} &&
  78. n.Subnet != nil &&
  79. time.Now().Unix()-n.LastSeen < int64(checkInPeriod)*2/int64(time.Second)
  80. }
  81. // Peer represents a peer in the network.
  82. type Peer struct {
  83. wireguard.Peer
  84. Name string
  85. }
  86. // Ready indicates whether or not the peer is ready.
  87. // Peers can have empty endpoints because they may not have an
  88. // IP, for example if they are behind a NAT, and thus
  89. // will not declare their endpoint and instead allow it to be
  90. // discovered.
  91. func (p *Peer) Ready() bool {
  92. return p != nil &&
  93. p.AllowedIPs != nil &&
  94. len(p.AllowedIPs) != 0 &&
  95. p.PublicKey != wgtypes.Key{} // If Key was not set, it will be wgtypes.Key{}.
  96. }
  97. // EventType describes what kind of an action an event represents.
  98. type EventType string
  99. const (
  100. // AddEvent represents an action where an item was added.
  101. AddEvent EventType = "add"
  102. // DeleteEvent represents an action where an item was removed.
  103. DeleteEvent EventType = "delete"
  104. // UpdateEvent represents an action where an item was updated.
  105. UpdateEvent EventType = "update"
  106. )
  107. // NodeEvent represents an event concerning a node in the cluster.
  108. type NodeEvent struct {
  109. Type EventType
  110. Node *Node
  111. Old *Node
  112. }
  113. // PeerEvent represents an event concerning a peer in the cluster.
  114. type PeerEvent struct {
  115. Type EventType
  116. Peer *Peer
  117. Old *Peer
  118. }
  119. // Backend can create clients for all of the
  120. // primitive types that Kilo deals with, namely:
  121. // * nodes; and
  122. // * peers.
  123. type Backend interface {
  124. Nodes() NodeBackend
  125. Peers() PeerBackend
  126. }
  127. // NodeBackend can get nodes by name, init itself,
  128. // list the nodes that should be meshed,
  129. // set Kilo properties for a node,
  130. // clean up any changes applied to the backend,
  131. // and watch for changes to nodes.
  132. type NodeBackend interface {
  133. CleanUp(context.Context, string) error
  134. Get(string) (*Node, error)
  135. Init(context.Context) error
  136. List() ([]*Node, error)
  137. Set(context.Context, string, *Node) error
  138. Watch() <-chan *NodeEvent
  139. }
  140. // PeerBackend can get peers by name, init itself,
  141. // list the peers that should be in the mesh,
  142. // set fields for a peer,
  143. // clean up any changes applied to the backend,
  144. // and watch for changes to peers.
  145. type PeerBackend interface {
  146. CleanUp(context.Context, string) error
  147. Get(string) (*Peer, error)
  148. Init(context.Context) error
  149. List() ([]*Peer, error)
  150. Set(context.Context, string, *Peer) error
  151. Watch() <-chan *PeerEvent
  152. }