| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- package logic
- import (
- "context"
- "errors"
- "net"
- "sync"
- "github.com/google/uuid"
- "github.com/gravitl/netmaker/db"
- "github.com/gravitl/netmaker/logger"
- "github.com/gravitl/netmaker/logic"
- "github.com/gravitl/netmaker/models"
- "github.com/gravitl/netmaker/schema"
- "github.com/gravitl/netmaker/servercfg"
- "golang.org/x/exp/slog"
- )
- var autoRelayCtxMutex = &sync.RWMutex{}
- var autoRelayCacheMutex = &sync.RWMutex{}
- var autoRelayCache = make(map[models.NetworkID][]string)
- func InitAutoRelayCache() {
- autoRelayCacheMutex.Lock()
- defer autoRelayCacheMutex.Unlock()
- allNodes, err := logic.GetAllNodes()
- if err != nil {
- return
- }
- for _, node := range allNodes {
- if node.IsAutoRelay {
- autoRelayCache[models.NetworkID(node.Network)] = append(autoRelayCache[models.NetworkID(node.Network)], node.ID.String())
- }
- }
- }
- func SetAutoRelay(node *models.Node) {
- node.IsAutoRelay = true
- }
- func CheckAutoRelayCtx(autoRelayNode, victimNode, peerNode models.Node) error {
- autoRelayCtxMutex.RLock()
- defer autoRelayCtxMutex.RUnlock()
- if peerNode.AutoRelayedPeers == nil {
- return nil
- }
- if victimNode.AutoRelayedPeers == nil {
- return nil
- }
- if peerNode.Mutex != nil {
- peerNode.Mutex.Lock()
- }
- _, peerHasAutoRelayed := peerNode.AutoRelayedPeers[victimNode.ID.String()]
- if peerNode.Mutex != nil {
- peerNode.Mutex.Unlock()
- }
- if victimNode.Mutex != nil {
- victimNode.Mutex.Lock()
- }
- _, victimHasAutoRelayed := victimNode.AutoRelayedPeers[peerNode.ID.String()]
- if victimNode.Mutex != nil {
- victimNode.Mutex.Unlock()
- }
- if peerHasAutoRelayed && victimHasAutoRelayed &&
- victimNode.AutoRelayedBy == autoRelayNode.ID && peerNode.AutoRelayedBy == autoRelayNode.ID {
- return errors.New("auto relay ctx is already set")
- }
- return nil
- }
- func SetAutoRelayCtx(autoRelayNode, victimNode, peerNode models.Node) error {
- autoRelayCtxMutex.Lock()
- defer autoRelayCtxMutex.Unlock()
- if peerNode.AutoRelayedPeers == nil {
- peerNode.AutoRelayedPeers = make(map[string]struct{})
- }
- if victimNode.AutoRelayedPeers == nil {
- victimNode.AutoRelayedPeers = make(map[string]struct{})
- }
- if peerNode.Mutex != nil {
- peerNode.Mutex.Lock()
- }
- _, peerHasAutoRelayed := peerNode.AutoRelayedPeers[victimNode.ID.String()]
- if peerNode.Mutex != nil {
- peerNode.Mutex.Unlock()
- }
- if victimNode.Mutex != nil {
- victimNode.Mutex.Lock()
- }
- _, victimHasAutoRelayed := victimNode.AutoRelayedPeers[peerNode.ID.String()]
- if victimNode.Mutex != nil {
- victimNode.Mutex.Unlock()
- }
- if peerHasAutoRelayed && victimHasAutoRelayed &&
- victimNode.AutoRelayedBy == autoRelayNode.ID && peerNode.AutoRelayedBy == autoRelayNode.ID {
- return errors.New("auto relay ctx is already set")
- }
- if peerNode.Mutex != nil {
- peerNode.Mutex.Lock()
- }
- peerNode.AutoRelayedPeers[victimNode.ID.String()] = struct{}{}
- if peerNode.Mutex != nil {
- peerNode.Mutex.Unlock()
- }
- if victimNode.Mutex != nil {
- victimNode.Mutex.Lock()
- }
- victimNode.AutoRelayedPeers[peerNode.ID.String()] = struct{}{}
- if victimNode.Mutex != nil {
- victimNode.Mutex.Unlock()
- }
- victimNode.AutoRelayedBy = autoRelayNode.ID
- // peerNode.AutoRelayedBy = autoRelayNode.ID
- if err := logic.UpsertNode(&victimNode); err != nil {
- return err
- }
- if err := logic.UpsertNode(&peerNode); err != nil {
- return err
- }
- return nil
- }
- // GetAutoRelayNode - gets the host acting as autoRelay
- func GetAutoRelayNode(network string, allNodes []models.Node) (models.Node, error) {
- nodes := logic.GetNetworkNodesMemory(allNodes, network)
- for _, node := range nodes {
- if node.IsAutoRelay {
- return node, nil
- }
- }
- return models.Node{}, errors.New("auto relay not found")
- }
- func RemoveAutoRelayFromCache(network string) {
- autoRelayCacheMutex.Lock()
- defer autoRelayCacheMutex.Unlock()
- delete(autoRelayCache, models.NetworkID(network))
- }
- func SetAutoRelayInCache(node models.Node) {
- autoRelayCacheMutex.Lock()
- defer autoRelayCacheMutex.Unlock()
- autoRelayCache[models.NetworkID(node.Network)] = append(autoRelayCache[models.NetworkID(node.Network)], node.ID.String())
- }
- // DoesAutoRelayExist - checks if autorelay exists already in the network
- func DoesAutoRelayExist(network string) (autoRelayNodes []models.Node) {
- autoRelayCacheMutex.RLock()
- defer autoRelayCacheMutex.RUnlock()
- if !servercfg.CacheEnabled() {
- nodes, _ := logic.GetNetworkNodes(network)
- for _, node := range nodes {
- if node.IsAutoRelay {
- autoRelayNodes = append(autoRelayNodes, node)
- }
- }
- }
- if nodeIDs, ok := autoRelayCache[models.NetworkID(network)]; ok {
- for _, nodeID := range nodeIDs {
- autoRelayNode, err := logic.GetNodeByID(nodeID)
- if err == nil {
- autoRelayNodes = append(autoRelayNodes, autoRelayNode)
- }
- }
- }
- return
- }
- // ResetAutoRelayedPeer - removes auto relayed over node from network peers
- func ResetAutoRelayedPeer(autoRelayedNode *models.Node) error {
- nodes, err := logic.GetNetworkNodes(autoRelayedNode.Network)
- if err != nil {
- return err
- }
- autoRelayedNode.AutoRelayedBy = uuid.Nil
- autoRelayedNode.AutoRelayedPeers = make(map[string]struct{})
- err = logic.UpsertNode(autoRelayedNode)
- if err != nil {
- return err
- }
- for _, node := range nodes {
- if node.AutoRelayedPeers == nil || node.ID == autoRelayedNode.ID {
- continue
- }
- delete(node.AutoRelayedPeers, autoRelayedNode.ID.String())
- logic.UpsertNode(&node)
- }
- return nil
- }
- // ResetAutoRelay - reset autorelayed peers
- func ResetAutoRelay(autoRelayNode *models.Node) error {
- // Unset autorelayed peers
- nodes, err := logic.GetNetworkNodes(autoRelayNode.Network)
- if err != nil {
- return err
- }
- for _, node := range nodes {
- if node.AutoRelayedBy == autoRelayNode.ID {
- node.AutoRelayedBy = uuid.Nil
- node.AutoRelayedPeers = make(map[string]struct{})
- logic.UpsertNode(&node)
- for _, peer := range nodes {
- if peer.ID == node.ID {
- continue
- }
- if _, ok := peer.AutoRelayedPeers[node.ID.String()]; ok {
- delete(peer.AutoRelayedPeers, node.ID.String())
- logic.UpsertNode(&peer)
- }
- }
- }
- }
- return nil
- }
- // GetAutoRelayPeerIps - adds the autorelayed peerIps by the peer
- func GetAutoRelayPeerIps(peer, node *models.Node) []net.IPNet {
- allowedips := []net.IPNet{}
- eli, _ := (&schema.Egress{Network: node.Network}).ListByNetwork(db.WithContext(context.TODO()))
- acls, _ := logic.ListAclsByNetwork(models.NetworkID(node.Network))
- for autoRelayedpeerID := range node.AutoRelayedPeers {
- autoRelayedpeer, err := logic.GetNodeByID(autoRelayedpeerID)
- if err == nil && (autoRelayedpeer.AutoRelayedBy == peer.ID || node.AutoRelayedBy == peer.ID) {
- logic.GetNodeEgressInfo(&autoRelayedpeer, eli, acls)
- if autoRelayedpeer.Address.IP != nil {
- allowed := net.IPNet{
- IP: autoRelayedpeer.Address.IP,
- Mask: net.CIDRMask(32, 32),
- }
- allowedips = append(allowedips, allowed)
- }
- if autoRelayedpeer.Address6.IP != nil {
- allowed := net.IPNet{
- IP: autoRelayedpeer.Address6.IP,
- Mask: net.CIDRMask(128, 128),
- }
- allowedips = append(allowedips, allowed)
- }
- if autoRelayedpeer.EgressDetails.IsEgressGateway {
- allowedips = append(allowedips, logic.GetEgressIPs(&autoRelayedpeer)...)
- }
- if autoRelayedpeer.IsRelay {
- for _, id := range autoRelayedpeer.RelayedNodes {
- rNode, _ := logic.GetNodeByID(id)
- logic.GetNodeEgressInfo(&rNode, eli, acls)
- if rNode.Address.IP != nil {
- allowed := net.IPNet{
- IP: rNode.Address.IP,
- Mask: net.CIDRMask(32, 32),
- }
- allowedips = append(allowedips, allowed)
- }
- if rNode.Address6.IP != nil {
- allowed := net.IPNet{
- IP: rNode.Address6.IP,
- Mask: net.CIDRMask(128, 128),
- }
- allowedips = append(allowedips, allowed)
- }
- if rNode.EgressDetails.IsEgressGateway {
- allowedips = append(allowedips, logic.GetEgressIPs(&rNode)...)
- }
- }
- }
- // handle ingress gateway peers
- if autoRelayedpeer.IsIngressGateway {
- extPeers, _, _, err := logic.GetExtPeers(&autoRelayedpeer, node)
- if err != nil {
- logger.Log(2, "could not retrieve ext peers for ", peer.ID.String(), err.Error())
- }
- for _, extPeer := range extPeers {
- allowedips = append(allowedips, extPeer.AllowedIPs...)
- }
- }
- }
- }
- return allowedips
- }
- func CreateAutoRelay(node models.Node) error {
- host, err := logic.GetHost(node.HostID.String())
- if err != nil {
- return err
- }
- if host.OS != models.OS_Types.Linux {
- return errors.New("only linux nodes are allowed to be set as autoRelay")
- }
- if node.IsRelayed {
- return errors.New("relayed node cannot be set as autoRelay")
- }
- node.IsAutoRelay = true
- err = logic.UpsertNode(&node)
- if err != nil {
- slog.Error("failed to upsert node", "node", node.ID.String(), "error", err)
- return err
- }
- if servercfg.CacheEnabled() {
- SetAutoRelayInCache(node)
- }
- return nil
- }
|