From a7c0abe2fc7cbc652ab19b95d16a0a32129be618 Mon Sep 17 00:00:00 2001 From: Abhishek Kondur Date: Mon, 7 Nov 2022 01:25:04 +0530 Subject: [PATCH] refactor proxy updates --- controllers/node.go | 37 +--------------- controllers/relay.go | 38 +---------------- logic/peers.go | 69 +++++++++++++++++++++++------- logic/server.go | 34 ++------------- logic/wireguard.go | 24 +---------- models/mqtt.go | 18 ++++---- mq/handlers.go | 19 --------- mq/publishers.go | 38 +++++++++++++++-- netclient/functions/daemon.go | 8 ++-- netclient/functions/mqhandlers.go | 20 ++------- nm-proxy/common/common.go | 71 ------------------------------- nm-proxy/manager/manager.go | 24 +++++++---- nm-proxy/wg/wg.go | 68 ++++++++++++++++++++++++++--- serverctl/serverctl.go | 24 +---------- 14 files changed, 192 insertions(+), 300 deletions(-) diff --git a/controllers/node.go b/controllers/node.go index 781606d5..3d18d10b 100644 --- a/controllers/node.go +++ b/controllers/node.go @@ -3,7 +3,6 @@ package controller import ( "encoding/json" "fmt" - "net" "net/http" "strings" @@ -15,10 +14,8 @@ import ( "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models/promodels" "github.com/gravitl/netmaker/mq" - "github.com/gravitl/netmaker/nm-proxy/manager" "github.com/gravitl/netmaker/servercfg" "golang.org/x/crypto/bcrypt" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) func nodeHandlers(r *mux.Router) { @@ -1015,25 +1012,6 @@ func updateNode(w http.ResponseWriter, r *http.Request) { if servercfg.IsDNSMode() { logic.SetDNS() } - wgPubKey, wgErr := wgtypes.ParseKey(newNode.PublicKey) - nodeEndpoint, udpErr := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", newNode.Endpoint, newNode.LocalListenPort)) - if wgErr == nil && udpErr == nil { - logic.ProxyMgmChan <- &manager.ManagerAction{ - Action: manager.UpdatePeer, - Payload: manager.ManagerPayload{ - InterfaceName: newNode.Interface, - Peers: []wgtypes.PeerConfig{ - { - PublicKey: wgPubKey, - Endpoint: nodeEndpoint, - }, - }, - }, - } - } else { - logger.Log(1, fmt.Sprintf("failed to send node update to proxy, wgErr: %v, udpErr: %v", wgErr, udpErr)) - } - logger.Log(1, r.Header.Get("user"), "updated node", node.ID, "on network", node.Network) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(newNode) @@ -1121,20 +1099,6 @@ func deleteNode(w http.ResponseWriter, r *http.Request) { logger.Log(0, "failed to reset failover lists during node delete for node", node.Name, node.Network) } } - wgKey, _ := wgtypes.ParseKey(node.PublicKey) - endpoint, _ := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", node.Endpoint, node.LocalListenPort)) - logic.ProxyMgmChan <- &manager.ManagerAction{ - Action: manager.DeletePeer, - Payload: manager.ManagerPayload{ - InterfaceName: node.Interface, - Peers: []wgtypes.PeerConfig{ - { - PublicKey: wgKey, - Endpoint: endpoint, - }, - }, - }, - } logic.ReturnSuccessResponse(w, r, nodeid+" deleted.") logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"]) runUpdates(&node, false) @@ -1151,6 +1115,7 @@ func runUpdates(node *models.Node, ifaceDelta bool) { if err := runServerUpdate(node, ifaceDelta); err != nil { logger.Log(1, "error running server update", err.Error()) } + }() } diff --git a/controllers/relay.go b/controllers/relay.go index 1978c179..45d82653 100644 --- a/controllers/relay.go +++ b/controllers/relay.go @@ -10,8 +10,6 @@ import ( "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/mq" - "github.com/gravitl/netmaker/nm-proxy/manager" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // swagger:route POST /api/nodes/{network}/{nodeid}/createrelay nodes createRelay @@ -45,49 +43,15 @@ func createRelay(w http.ResponseWriter, r *http.Request) { return } - relayPeersMap := make(map[string][]wgtypes.PeerConfig) logger.Log(1, r.Header.Get("user"), "created relay on node", relay.NodeID, "on network", relay.NetID) for _, relayedNode := range updatenodes { - peers, err := logic.GetPeersForProxy(&relayedNode) - if err == nil { - relayPeersMap[relayedNode.PublicKey] = peers - } - - // relayEndpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", node.Endpoint, node.LocalListenPort)) - // if err != nil { - // logger.Log(1, "failed to resolve relay node endpoint: ", err.Error()) - // } - - // err = mq.ProxyUpdate(&manager.ManagerAction{ - // Action: manager.AddInterface, - // Payload: manager.ManagerPayload{ - // InterfaceName: relayedNode.Interface, - // IsRelayed: true, - // Peers: peers, - // RelayedTo: relayEndpoint, - // }, - // }, &node) - // if err != nil { - // logger.Log(1, "failed to send proxy update for relayed node: ", err.Error()) - // } err = mq.NodeUpdate(&relayedNode) if err != nil { logger.Log(1, "error sending update to relayed node ", relayedNode.Name, "on network", relay.NetID, ": ", err.Error()) } } - // send proxy update for node that is relaying traffic - logger.Log(0, "--------> sending relay update to proxy") - err = mq.ProxyUpdate(&manager.ManagerAction{ - Action: manager.RelayPeers, - Payload: manager.ManagerPayload{ - IsRelay: true, - RelayedPeers: relayPeersMap, - }, - }, &node) - if err != nil { - logger.Log(1, "failed to send proxy update: ", err.Error()) - } + w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(node) runUpdates(&node, true) diff --git a/logic/peers.go b/logic/peers.go index 7d94fd59..79d5e966 100644 --- a/logic/peers.go +++ b/logic/peers.go @@ -3,7 +3,6 @@ package logic import ( "errors" "fmt" - "log" "net" "strconv" "strings" @@ -14,24 +13,56 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic/acls/nodeacls" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/nm-proxy/manager" "github.com/gravitl/netmaker/servercfg" "golang.org/x/exp/slices" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) -func GetPeersForProxy(node *models.Node) ([]wgtypes.PeerConfig, error) { +func GetPeersForProxy(node *models.Node, onlyPeers bool) (manager.ManagerPayload, error) { + proxyPayload := manager.ManagerPayload{} var peers []wgtypes.PeerConfig + peerConfMap := make(map[string]manager.PeerConf) var err error currentPeers, err := GetNetworkNodes(node.Network) if err != nil { - return peers, err + return proxyPayload, err } + if !onlyPeers { + if node.IsRelayed == "yes" { + relayNode := FindRelay(node) + relayEndpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayNode.Endpoint, relayNode.LocalListenPort)) + if err != nil { + logger.Log(1, "failed to resolve relay node endpoint: ", err.Error()) + } + proxyPayload.IsRelayed = true + proxyPayload.RelayedTo = relayEndpoint + + } + if node.IsRelay == "yes" { + relayedNodes, err := GetRelayedNodes(node) + if err != nil { + logger.Log(1, "failed to relayed nodes: ", node.Name, err.Error()) + proxyPayload.IsRelay = false + } else { + relayPeersMap := make(map[string][]wgtypes.PeerConfig) + for _, relayedNode := range relayedNodes { + payload, err := GetPeersForProxy(&relayedNode, true) + if err == nil { + relayPeersMap[relayedNode.PublicKey] = payload.Peers + } + } + proxyPayload.IsRelay = true + proxyPayload.RelayedPeers = relayPeersMap + } + } + } + for _, peer := range currentPeers { if peer.ID == node.ID { //skip yourself continue } - log.Printf("----------> PEER: %s, Endpoint: %s, LocalPort: %d", peer.ID, peer.Endpoint, peer.LocalListenPort) pubkey, err := wgtypes.ParseKey(peer.PublicKey) if err != nil { logger.Log(1, "failed to parse node pub key: ", peer.ID) @@ -48,7 +79,6 @@ func GetPeersForProxy(node *models.Node) ([]wgtypes.PeerConfig, error) { // set_keepalive keepalive, _ = time.ParseDuration(strconv.FormatInt(int64(node.PersistentKeepalive), 10) + "s") } - log.Printf("---------->##### PEER: %s, Endpoint: %s, LocalPort: %d", peer.ID, endpoint, peer.LocalListenPort) peers = append(peers, wgtypes.PeerConfig{ PublicKey: pubkey, Endpoint: endpoint, @@ -56,8 +86,25 @@ func GetPeersForProxy(node *models.Node) ([]wgtypes.PeerConfig, error) { PersistentKeepaliveInterval: &keepalive, ReplaceAllowedIPs: true, }) + if !onlyPeers && peer.IsRelayed == "yes" { + relayNode := FindRelay(&peer) + if relayNode != nil { + relayTo, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", peer.Endpoint, peer.LocalListenPort)) + if err == nil { + peerConfMap[peer.PublicKey] = manager.PeerConf{ + IsRelayed: true, + RelayedTo: relayTo, + } + } + + } + + } } - return peers, nil + proxyPayload.Peers = peers + proxyPayload.PeerMap = peerConfMap + proxyPayload.InterfaceName = node.Interface + return proxyPayload, nil } // GetPeerUpdate - gets a wireguard peer config for each peer of a node @@ -237,16 +284,6 @@ func GetPeerUpdate(node *models.Node) (models.PeerUpdate, error) { peerUpdate.ServerAddrs = serverNodeAddresses peerUpdate.DNS = getPeerDNS(node.Network) peerUpdate.PeerIDs = peerMap - if node.IsRelayed == "yes" { - relayNode := FindRelay(node) - relayEndpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayNode.Endpoint, relayNode.LocalListenPort)) - if err != nil { - logger.Log(1, "failed to resolve relay node endpoint: ", err.Error()) - } - peerUpdate.IsRelayed = true - peerUpdate.RelayTo = relayEndpoint - - } return peerUpdate, nil } diff --git a/logic/server.go b/logic/server.go index bd61e480..e3da3a66 100644 --- a/logic/server.go +++ b/logic/server.go @@ -175,38 +175,12 @@ func ServerJoin(networkSettings *models.Network) (models.Node, error) { if err != nil { return returnNode, err } - logger.Log(0, "--------> Hereeeeeee23333") - proxyPayload := manager.ManagerPayload{ - IsRelay: node.IsRelay == "yes", - InterfaceName: node.Interface, - Peers: peers.Peers, + proxyPayload, err := GetPeersForProxy(node, false) + if err != nil && !ncutils.IsEmptyRecord(err) { + logger.Log(1, "failed to retrieve peers") + return returnNode, err } - // if proxyPayload.IsRelayed { - // relayNode := FindRelay(node) - // relayEndpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayNode.Endpoint, relayNode.LocalListenPort)) - // if err != nil { - // logger.Log(1, "failed to resolve relay node endpoint: ", err.Error()) - // proxyPayload.IsRelayed = false - // } - // proxyPayload.RelayedTo = relayEndpoint - // } - if proxyPayload.IsRelay { - relayedNodes, err := GetRelayedNodes(node) - if err != nil { - logger.Log(1, "failed to relayed nodes: ", node.Name, err.Error()) - proxyPayload.IsRelay = false - } else { - relayPeersMap := make(map[string][]wgtypes.PeerConfig) - for _, relayedNode := range relayedNodes { - peers, err := GetPeersForProxy(&relayedNode) - if err == nil { - relayPeersMap[relayedNode.PublicKey] = peers - } - } - proxyPayload.RelayedPeers = relayPeersMap - } - } ProxyMgmChan <- &manager.ManagerAction{ Action: manager.AddInterface, Payload: proxyPayload, diff --git a/logic/wireguard.go b/logic/wireguard.go index 017ea569..c05dd95e 100644 --- a/logic/wireguard.go +++ b/logic/wireguard.go @@ -161,31 +161,11 @@ func setWGConfig(node *models.Node, peerupdate bool) error { } logger.Log(0, "--------> ADD/Update INTERFACE TO PROXY.....") - peersP, err := GetPeersForProxy(node) + proxyPayload, err := GetPeersForProxy(node, false) if err != nil { logger.Log(0, "failed to get peers for proxy: ", err.Error()) } else { - proxyPayload := manager.ManagerPayload{ - IsRelay: node.IsRelay == "yes", - InterfaceName: node.Interface, - Peers: peersP, - } - if proxyPayload.IsRelay { - relayedNodes, err := GetRelayedNodes(node) - if err != nil { - logger.Log(1, "failed to relayed nodes: ", node.Name, err.Error()) - proxyPayload.IsRelay = false - } else { - relayPeersMap := make(map[string][]wgtypes.PeerConfig) - for _, relayedNode := range relayedNodes { - peers, err := GetPeersForProxy(&relayedNode) - if err == nil { - relayPeersMap[relayedNode.PublicKey] = peers - } - } - proxyPayload.RelayedPeers = relayPeersMap - } - } + ProxyMgmChan <- &manager.ManagerAction{ Action: manager.AddInterface, Payload: proxyPayload, diff --git a/models/mqtt.go b/models/mqtt.go index 67ad6f74..c3e610b3 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -1,21 +1,19 @@ package models import ( - "net" - + "github.com/gravitl/netmaker/nm-proxy/manager" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // PeerUpdate - struct type PeerUpdate struct { - Network string `json:"network" bson:"network" yaml:"network"` - ServerVersion string `json:"serverversion" bson:"serverversion" yaml:"serverversion"` - ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"` - Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"` - DNS string `json:"dns" bson:"dns" yaml:"dns"` - PeerIDs PeerMap `json:"peerids" bson:"peerids" yaml:"peerids"` - IsRelayed bool `json:"is_relayed" bson:"is_relayed" yaml:"is_relayed"` - RelayTo *net.UDPAddr `json:"relay_to" bson:"relay_to" yaml:"relay_to"` + Network string `json:"network" bson:"network" yaml:"network"` + ServerVersion string `json:"serverversion" bson:"serverversion" yaml:"serverversion"` + ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"` + Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"` + DNS string `json:"dns" bson:"dns" yaml:"dns"` + PeerIDs PeerMap `json:"peerids" bson:"peerids" yaml:"peerids"` + ProxyUpdate manager.ManagerAction `josn:"proxy_update"` } // KeyUpdate - key update struct diff --git a/mq/handlers.go b/mq/handlers.go index 40e141ac..8659b899 100644 --- a/mq/handlers.go +++ b/mq/handlers.go @@ -3,7 +3,6 @@ package mq import ( "encoding/json" "fmt" - "net" "time" mqtt "github.com/eclipse/paho.mqtt.golang" @@ -12,9 +11,7 @@ import ( "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/nm-proxy/manager" "github.com/gravitl/netmaker/servercfg" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // DefaultHandler default message queue handler -- NOT USED @@ -104,22 +101,6 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) { if err = PublishPeerUpdate(¤tNode, true); err != nil { logger.Log(0, "error updating peers when node", currentNode.Name, currentNode.ID, "informed the server of an interface change", err.Error()) } - pubKey, wgErr := wgtypes.ParseKey(newNode.PublicKey) - endpoint, udpErr := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", newNode.Endpoint, newNode.LocalListenPort)) - if wgErr == nil && udpErr == nil { - logic.ProxyMgmChan <- &manager.ManagerAction{ - Action: manager.UpdatePeer, - Payload: manager.ManagerPayload{ - InterfaceName: newNode.Interface, - Peers: []wgtypes.PeerConfig{ - { - PublicKey: pubKey, - Endpoint: endpoint, - }, - }, - }, - } - } } logger.Log(1, "updated node", id, newNode.Name) diff --git a/mq/publishers.go b/mq/publishers.go index 159ccdd7..7fe1dcae 100644 --- a/mq/publishers.go +++ b/mq/publishers.go @@ -26,7 +26,10 @@ func PublishPeerUpdate(newNode *models.Node, publishToSelf bool) error { return err } for _, node := range networkNodes { - + // err := PublishProxyUpdate(manager.AddInterface, &node) + // if err != nil { + // logger.Log(1, "failed to publish proxy update to node", node.Name, "on network", node.Network, ":", err.Error()) + // } if node.IsServer == "yes" { continue } @@ -38,16 +41,40 @@ func PublishPeerUpdate(newNode *models.Node, publishToSelf bool) error { if err != nil { logger.Log(1, "failed to publish peer update to node", node.Name, "on network", node.Network, ":", err.Error()) } + } return err } +func PublishProxyUpdate(action manager.ProxyAction, node *models.Node) error { + peerUpdates, err := logic.GetPeersForProxy(node, false) + if err != nil { + return err + } + err = ProxyUpdate(&manager.ManagerAction{ + Action: action, + Payload: peerUpdates}, node) + if err != nil { + logger.Log(1, "failed to send proxy update: ", err.Error()) + return err + } + return nil +} + // PublishSinglePeerUpdate --- determines and publishes a peer update to one node func PublishSinglePeerUpdate(node *models.Node) error { peerUpdate, err := logic.GetPeerUpdate(node) if err != nil { return err } + proxyUpdate, err := logic.GetPeersForProxy(node, false) + if err != nil { + return err + } + peerUpdate.ProxyUpdate = manager.ManagerAction{ + Action: manager.AddInterface, + Payload: proxyUpdate, + } data, err := json.Marshal(&peerUpdate) if err != nil { return err @@ -104,10 +131,14 @@ func NodeUpdate(node *models.Node) error { logger.Log(2, "error publishing node update to peer ", node.ID, err.Error()) return err } + err = PublishProxyUpdate(manager.AddInterface, node) + if err != nil { + logger.Log(1, "failed to publish proxy update to node", node.Name, "on network", node.Network, ":", err.Error()) + } return nil } -//ProxyUpdate -- publishes updates related to proxy +//ProxyUpdate -- publishes updates to peers related to proxy func ProxyUpdate(proxyPayload *manager.ManagerAction, node *models.Node) error { if !servercfg.IsMessageQueueBackend() { return nil @@ -122,7 +153,7 @@ func ProxyUpdate(proxyPayload *manager.ManagerAction, node *models.Node) error { logger.Log(2, "error marshalling node update ", err.Error()) return err } - if err = publish(node, fmt.Sprintf("update/proxy/%s/%s", node.Network, node.ID), data); err != nil { + if err = publish(node, fmt.Sprintf("proxy/%s/%s", node.Network, node.ID), data); err != nil { logger.Log(2, "error publishing node update to peer ", node.ID, err.Error()) return err } @@ -188,6 +219,7 @@ func sendPeers() { if errN != nil { logger.Log(1, errN.Error()) } + serverctl.SyncServerNetworkWithProxy() } } } diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 5f644832..7db09e31 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -25,8 +25,8 @@ import ( "github.com/gravitl/netmaker/netclient/local" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/wireguard" + nmproxy "github.com/gravitl/netmaker/nm-proxy" - "github.com/gravitl/netmaker/nm-proxy/common" "github.com/gravitl/netmaker/nm-proxy/manager" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -158,12 +158,12 @@ func startGoRoutines(wg *sync.WaitGroup) context.CancelFunc { } func GetNodeInfo(cfg *config.ClientConfig) (models.NodeGet, error) { var nodeGET models.NodeGet - token, err := common.Authenticate(cfg) + token, err := Authenticate(cfg) if err != nil { return nodeGET, err } url := fmt.Sprintf("https://%s/api/nodes/%s/%s", cfg.Server.API, cfg.Network, cfg.Node.ID) - response, err := common.API("", http.MethodGet, url, token) + response, err := API("", http.MethodGet, url, token) if err != nil { return nodeGET, err } @@ -217,7 +217,7 @@ func setSubscriptions(client mqtt.Client, nodeCfg *config.ClientConfig) { } return } - if token := client.Subscribe(fmt.Sprintf("update/proxy/%s/%s", nodeCfg.Node.Network, nodeCfg.Node.ID), 0, mqtt.MessageHandler(ProxyUpdate)); token.WaitTimeout(mq.MQ_TIMEOUT*time.Second) && token.Error() != nil { + if token := client.Subscribe(fmt.Sprintf("proxy/%s/%s", nodeCfg.Node.Network, nodeCfg.Node.ID), 0, mqtt.MessageHandler(ProxyUpdate)); token.WaitTimeout(mq.MQ_TIMEOUT*time.Second) && token.Error() != nil { if token.Error() == nil { logger.Log(0, "network:", nodeCfg.Node.Network, "connection timeout") } else { diff --git a/netclient/functions/mqhandlers.go b/netclient/functions/mqhandlers.go index f08fbe1b..38c6fd83 100644 --- a/netclient/functions/mqhandlers.go +++ b/netclient/functions/mqhandlers.go @@ -34,7 +34,7 @@ var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { func ProxyUpdate(client mqtt.Client, msg mqtt.Message) { var nodeCfg config.ClientConfig var proxyUpdate manager.ManagerAction - var network = strings.Split(msg.Topic(), "/")[2] + var network = parseNetworkFromTopic(msg.Topic()) nodeCfg.Network = network nodeCfg.ReadConfig() @@ -165,12 +165,7 @@ func NodeUpdate(client mqtt.Client, msg mqtt.Message) { // } // } // } - ProxyMgmChan <- &manager.ManagerAction{ - Action: manager.AddInterface, - Payload: manager.ManagerPayload{ - IsRelayed: newNode.IsRelay == "yes", - }, - } + if ifaceDelta { // if a change caused an ifacedelta we need to notify the server to update the peers doneErr := publishSignal(&nodeCfg, ncutils.DONE) if doneErr != nil { @@ -273,15 +268,7 @@ func UpdatePeers(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "error syncing wg after peer update: "+err.Error()) return } - ProxyMgmChan <- &manager.ManagerAction{ - Action: manager.AddInterface, - Payload: manager.ManagerPayload{ - InterfaceName: cfg.Node.Interface, - Peers: peerUpdate.Peers, - IsRelayed: peerUpdate.IsRelayed, - RelayedTo: peerUpdate.RelayTo, - }, - } + ProxyMgmChan <- &peerUpdate.ProxyUpdate logger.Log(0, "network:", cfg.Node.Network, "received peer update for node "+cfg.Node.Name+" "+cfg.Node.Network) if cfg.Node.DNSOn == "yes" { if err := setHostDNS(peerUpdate.DNS, cfg.Node.Interface, ncutils.IsWindows()); err != nil { @@ -294,6 +281,7 @@ func UpdatePeers(client mqtt.Client, msg mqtt.Message) { return } } + _ = UpdateLocalListenPort(&cfg) } diff --git a/nm-proxy/common/common.go b/nm-proxy/common/common.go index e69924c0..298e1b5a 100644 --- a/nm-proxy/common/common.go +++ b/nm-proxy/common/common.go @@ -1,22 +1,11 @@ package common import ( - "bytes" "context" - "encoding/json" - "fmt" - "io" "log" "net" - "net/http" - "os" "os/exec" "strings" - "time" - - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/nm-proxy/wg" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" @@ -94,63 +83,3 @@ func RunCmd(command string, printerr bool) (string, error) { } return string(out), err } - -// API function to interact with netmaker api endpoints. response from endpoint is returned -func API(data interface{}, method, url, authorization string) (*http.Response, error) { - var request *http.Request - var err error - if data != "" { - payload, err := json.Marshal(data) - if err != nil { - return nil, fmt.Errorf("error encoding data %w", err) - } - request, err = http.NewRequest(method, url, bytes.NewBuffer(payload)) - if err != nil { - return nil, fmt.Errorf("error creating http request %w", err) - } - request.Header.Set("Content-Type", "application/json") - } else { - request, err = http.NewRequest(method, url, nil) - if err != nil { - return nil, fmt.Errorf("error creating http request %w", err) - } - } - if authorization != "" { - request.Header.Set("authorization", "Bearer "+authorization) - } - request.Header.Set("requestfrom", "node") - var httpClient http.Client - httpClient.Timeout = time.Minute - return httpClient.Do(request) -} - -// Authenticate authenticates with api to permit subsequent interactions with the api -func Authenticate(cfg *config.ClientConfig) (string, error) { - - pass, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "secret-" + cfg.Network) - if err != nil { - return "", fmt.Errorf("could not read secrets file %w", err) - } - data := models.AuthParams{ - MacAddress: cfg.Node.MacAddress, - ID: cfg.Node.ID, - Password: string(pass), - } - url := "https://" + cfg.Server.API + "/api/nodes/adm/" + cfg.Network + "/authenticate" - response, err := API(data, http.MethodPost, url, "") - if err != nil { - return "", err - } - defer response.Body.Close() - if response.StatusCode != http.StatusOK { - bodybytes, _ := io.ReadAll(response.Body) - return "", fmt.Errorf("failed to authenticate %s %s", response.Status, string(bodybytes)) - } - resp := models.SuccessResponse{} - if err := json.NewDecoder(response.Body).Decode(&resp); err != nil { - return "", fmt.Errorf("error decoding respone %w", err) - } - tokenData := resp.Response.(map[string]interface{}) - token := tokenData["AuthToken"] - return token.(string), nil -} diff --git a/nm-proxy/manager/manager.go b/nm-proxy/manager/manager.go index 79747654..25e7464d 100644 --- a/nm-proxy/manager/manager.go +++ b/nm-proxy/manager/manager.go @@ -8,7 +8,6 @@ import ( "net" "runtime" - "github.com/gravitl/netmaker/netclient/wireguard" "github.com/gravitl/netmaker/nm-proxy/common" peerpkg "github.com/gravitl/netmaker/nm-proxy/peer" "github.com/gravitl/netmaker/nm-proxy/wg" @@ -18,12 +17,17 @@ import ( type ProxyAction string type ManagerPayload struct { - InterfaceName string - Peers []wgtypes.PeerConfig - IsRelayed bool - RelayedTo *net.UDPAddr - IsRelay bool - RelayedPeers map[string][]wgtypes.PeerConfig + InterfaceName string `json:"interface_name"` + Peers []wgtypes.PeerConfig `json:"peers"` + PeerMap map[string]PeerConf `json:"peer_map"` + IsRelayed bool `json:"is_relayed"` + RelayedTo *net.UDPAddr `json:"relayed_to"` + IsRelay bool `json:"is_relay"` + RelayedPeers map[string][]wgtypes.PeerConfig `json:"relayed_peers"` +} +type PeerConf struct { + IsRelayed bool `json:"is_relayed"` + RelayedTo *net.UDPAddr `json:"relayed_to"` } const ( @@ -48,6 +52,10 @@ func StartProxyManager(manageChan chan *ManagerAction) { log.Printf("-------> PROXY-MANAGER: %+v\n", mI) switch mI.Action { case AddInterface: + common.IsRelay = mI.Payload.IsRelay + if mI.Payload.IsRelay { + mI.RelayPeers() + } err := mI.AddInterfaceToProxy() if err != nil { log.Printf("failed to add interface: [%s] to proxy: %v\n ", mI.Payload.InterfaceName, err) @@ -161,7 +169,7 @@ func (m *ManagerAction) AddInterfaceToProxy() error { ifaceName := m.Payload.InterfaceName log.Println("--------> IFACE: ", ifaceName) if runtime.GOOS == "darwin" { - ifaceName, err = wireguard.GetRealIface(ifaceName) + ifaceName, err = wg.GetRealIface(ifaceName) if err != nil { log.Println("failed to get real iface: ", err) } diff --git a/nm-proxy/wg/wg.go b/nm-proxy/wg/wg.go index 72d3f52b..b7fff0db 100644 --- a/nm-proxy/wg/wg.go +++ b/nm-proxy/wg/wg.go @@ -1,9 +1,13 @@ package wg import ( + "errors" "fmt" "log" "net" + "os" + "os/exec" + "strings" "sync" "time" @@ -14,7 +18,7 @@ import ( const ( DefaultMTU = 1280 DefaultWgPort = 51820 - DefaultWgKeepAlive = 25 * time.Second + DefaultWgKeepAlive = 20 * time.Second ) // WGIface represents a interface instance @@ -103,7 +107,6 @@ func parseAddress(address string) (WGAddress, error) { } // UpdatePeer updates existing Wireguard Peer or creates a new one if doesn't exist -// Endpoint is optional func (w *WGIface) UpdatePeer(peerKey string, allowedIps []net.IPNet, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { w.mu.Lock() defer w.mu.Unlock() @@ -121,9 +124,9 @@ func (w *WGIface) UpdatePeer(peerKey string, allowedIps []net.IPNet, keepAlive t return err } peer := wgtypes.PeerConfig{ - PublicKey: peerKeyParsed, - ReplaceAllowedIPs: true, - AllowedIPs: allowedIps, + PublicKey: peerKeyParsed, + // ReplaceAllowedIPs: true, + // AllowedIPs: allowedIps, PersistentKeepaliveInterval: &keepAlive, PresharedKey: preSharedKey, Endpoint: endpoint, @@ -176,3 +179,58 @@ func (w *WGIface) GetListenPort() (*int, error) { return &d.ListenPort, nil } + +// GetRealIface - retrieves tun iface based on reference iface name from config file +func GetRealIface(iface string) (string, error) { + RunCmd("wg show interfaces", false) + ifacePath := "/var/run/wireguard/" + iface + ".name" + if !(FileExists(ifacePath)) { + return "", errors.New(ifacePath + " does not exist") + } + realIfaceName, err := GetFileAsString(ifacePath) + if err != nil { + return "", err + } + realIfaceName = strings.TrimSpace(realIfaceName) + if !(FileExists(fmt.Sprintf("/var/run/wireguard/%s.sock", realIfaceName))) { + return "", errors.New("interface file does not exist") + } + return realIfaceName, nil +} + +// FileExists - checks if file exists locally +func FileExists(f string) bool { + info, err := os.Stat(f) + if os.IsNotExist(err) { + return false + } + if err != nil && strings.Contains(err.Error(), "not a directory") { + return false + } + if err != nil { + log.Println(0, "error reading file: "+f+", "+err.Error()) + } + return !info.IsDir() +} + +// GetFileAsString - returns the string contents of a given file +func GetFileAsString(path string) (string, error) { + content, err := os.ReadFile(path) + if err != nil { + return "", err + } + return string(content), err +} + +// RunCmd - runs a local command +func RunCmd(command string, printerr bool) (string, error) { + args := strings.Fields(command) + cmd := exec.Command(args[0], args[1:]...) + cmd.Wait() + out, err := cmd.CombinedOutput() + if err != nil && printerr { + log.Println("error running command: ", command) + log.Println(strings.TrimSuffix(string(out), "\n")) + } + return string(out), err +} diff --git a/serverctl/serverctl.go b/serverctl/serverctl.go index 7dc4250d..81f94837 100644 --- a/serverctl/serverctl.go +++ b/serverctl/serverctl.go @@ -14,7 +14,6 @@ import ( "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/nm-proxy/manager" "github.com/gravitl/netmaker/servercfg" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) const ( @@ -83,33 +82,12 @@ func SyncServerNetworkWithProxy() error { logger.Log(1, "failed to retrieve local server node: ", serverNode.ID) continue } - peers, err := logic.GetPeersForProxy(&serverNode) + proxyPayload, err := logic.GetPeersForProxy(&serverNode, false) if err != nil && !ncutils.IsEmptyRecord(err) { logger.Log(1, "failed to retrieve peers for server node: ", serverNode.ID) continue } logger.Log(0, "----> HEREEEEEEEE1") - proxyPayload := manager.ManagerPayload{ - IsRelay: serverNode.IsRelay == "yes", - InterfaceName: serverNode.Interface, - Peers: peers, - } - if proxyPayload.IsRelay { - relayedNodes, err := logic.GetRelayedNodes(&serverNode) - if err != nil { - logger.Log(1, "failed to relayed nodes: ", serverNode.Name, err.Error()) - proxyPayload.IsRelay = false - } else { - relayPeersMap := make(map[string][]wgtypes.PeerConfig) - for _, relayedNode := range relayedNodes { - peers, err := logic.GetPeersForProxy(&relayedNode) - if err == nil { - relayPeersMap[relayedNode.PublicKey] = peers - } - } - proxyPayload.RelayedPeers = relayPeersMap - } - } logic.ProxyMgmChan <- &manager.ManagerAction{ Action: manager.AddInterface, Payload: proxyPayload,