mirror of
https://github.com/gravitl/netmaker.git
synced 2025-03-01 02:25:40 +08:00
Merge pull request #666 from gravitl/feature_v0.10.0_client_refactor1
Feature v0.10.0 client refactor1
This commit is contained in:
commit
959a688426
21 changed files with 390 additions and 242 deletions
|
@ -123,7 +123,7 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
|
||||||
newNetwork.DefaultPostUp = network.DefaultPostUp
|
newNetwork.DefaultPostUp = network.DefaultPostUp
|
||||||
}
|
}
|
||||||
|
|
||||||
rangeupdate, localrangeupdate, err := logic.UpdateNetwork(&network, &newNetwork)
|
rangeupdate, localrangeupdate, holepunchupdate, err := logic.UpdateNetwork(&network, &newNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
return
|
return
|
||||||
|
@ -148,6 +148,24 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if holepunchupdate {
|
||||||
|
err = logic.UpdateNetworkHolePunching(network.NetID, newNetwork.DefaultUDPHolePunch)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rangeupdate || localrangeupdate || holepunchupdate {
|
||||||
|
nodes, err := logic.GetNetworkNodes(network.NetID)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, node := range nodes {
|
||||||
|
runUpdates(&node, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.Log(1, r.Header.Get("user"), "updated network", netname)
|
logger.Log(1, r.Header.Get("user"), "updated network", netname)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(newNetwork)
|
json.NewEncoder(w).Encode(newNetwork)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
"github.com/gravitl/netmaker/logic"
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
|
"github.com/gravitl/netmaker/mq"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
"github.com/gravitl/netmaker/serverctl"
|
"github.com/gravitl/netmaker/serverctl"
|
||||||
)
|
)
|
||||||
|
@ -104,6 +105,27 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object)
|
||||||
|
|
||||||
runUpdates(&node, false)
|
runUpdates(&node, false)
|
||||||
|
|
||||||
|
go func(node *models.Node) {
|
||||||
|
if node.UDPHolePunch == "yes" {
|
||||||
|
var currentServerNode, getErr = logic.GetNetworkServerLeader(node.Network)
|
||||||
|
if getErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
if logic.HasPeerConnected(node) {
|
||||||
|
if logic.ShouldPublishPeerPorts(¤tServerNode) {
|
||||||
|
err = mq.PublishPeerUpdate(¤tServerNode)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(1, "error publishing port updates when node", node.Name, "joined")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second << 1) // allow time for client to startup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(&node)
|
||||||
|
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +186,6 @@ func getServerAddrs(node *models.Node) {
|
||||||
serverAddrs = append(serverAddrs, models.ServerAddr{
|
serverAddrs = append(serverAddrs, models.ServerAddr{
|
||||||
IsLeader: logic.IsLeader(&node),
|
IsLeader: logic.IsLeader(&node),
|
||||||
Address: node.Address,
|
Address: node.Address,
|
||||||
ID: node.ID,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,29 +282,7 @@ func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object)
|
||||||
}
|
}
|
||||||
|
|
||||||
// == private methods ==
|
// == private methods ==
|
||||||
/*
|
|
||||||
func getNewOrLegacyNode(data string) (models.Node, error) {
|
|
||||||
var reqNode, node models.Node
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if err = json.Unmarshal([]byte(data), &reqNode); err != nil {
|
|
||||||
oldID := strings.Split(data, "###") // handle legacy client IDs
|
|
||||||
if len(oldID) == 2 {
|
|
||||||
if node, err = logic.GetNodeByID(reqNode.ID); err != nil {
|
|
||||||
return models.Node{}, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return models.Node{}, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
node, err = logic.GetNodeByID(reqNode.ID)
|
|
||||||
if err != nil {
|
|
||||||
return models.Node{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node, nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func getNodeFromRequestData(data string) (models.Node, error) {
|
func getNodeFromRequestData(data string) (models.Node, error) {
|
||||||
var reqNode models.Node
|
var reqNode models.Node
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -23,14 +23,10 @@ func runServerPeerUpdate(node *models.Node, ifaceDelta bool) error {
|
||||||
if servercfg.IsClientMode() != "on" {
|
if servercfg.IsClientMode() != "on" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var currentServerNodeID, getErr = logic.GetNetworkServerNodeID(node.Network)
|
var currentServerNode, getErr = logic.GetNetworkServerLeader(node.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return getErr
|
return getErr
|
||||||
}
|
}
|
||||||
var currentServerNode, currErr = logic.GetNodeByID(currentServerNodeID)
|
|
||||||
if currErr != nil {
|
|
||||||
return currErr
|
|
||||||
}
|
|
||||||
if err = logic.ServerUpdate(¤tServerNode, ifaceDelta); err != nil {
|
if err = logic.ServerUpdate(¤tServerNode, ifaceDelta); err != nil {
|
||||||
logger.Log(1, "server node:", currentServerNode.ID, "failed update")
|
logger.Log(1, "server node:", currentServerNode.ID, "failed update")
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -389,7 +389,7 @@ func UpdateNetworkLocalAddresses(networkName string) error {
|
||||||
node.Address = ipaddr
|
node.Address = ipaddr
|
||||||
newNodeData, err := json.Marshal(&node)
|
newNodeData, err := json.Marshal(&node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("error in node address assignment!")
|
logger.Log(1, "error in node address assignment!")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
database.Insert(node.ID, string(newNodeData), database.NODES_TABLE_NAME)
|
database.Insert(node.ID, string(newNodeData), database.NODES_TABLE_NAME)
|
||||||
|
@ -399,6 +399,28 @@ func UpdateNetworkLocalAddresses(networkName string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateNetworkLocalAddresses - updates network localaddresses
|
||||||
|
func UpdateNetworkHolePunching(networkName string, holepunch string) error {
|
||||||
|
|
||||||
|
nodes, err := GetNetworkNodes(networkName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, node := range nodes {
|
||||||
|
if node.IsServer != "yes" {
|
||||||
|
node.UDPHolePunch = holepunch
|
||||||
|
newNodeData, err := json.Marshal(&node)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(1, "error in node hole punch assignment")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
database.Insert(node.ID, string(newNodeData), database.NODES_TABLE_NAME)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveNetworkNodeIPv6Addresses - removes network node IPv6 addresses
|
// RemoveNetworkNodeIPv6Addresses - removes network node IPv6 addresses
|
||||||
func RemoveNetworkNodeIPv6Addresses(networkName string) error {
|
func RemoveNetworkNodeIPv6Addresses(networkName string) error {
|
||||||
|
|
||||||
|
@ -509,23 +531,24 @@ func IsNetworkNameUnique(network *models.Network) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateNetwork - updates a network with another network's fields
|
// UpdateNetwork - updates a network with another network's fields
|
||||||
func UpdateNetwork(currentNetwork *models.Network, newNetwork *models.Network) (bool, bool, error) {
|
func UpdateNetwork(currentNetwork *models.Network, newNetwork *models.Network) (bool, bool, bool, error) {
|
||||||
if err := ValidateNetwork(newNetwork, true); err != nil {
|
if err := ValidateNetwork(newNetwork, true); err != nil {
|
||||||
return false, false, err
|
return false, false, false, err
|
||||||
}
|
}
|
||||||
if newNetwork.NetID == currentNetwork.NetID {
|
if newNetwork.NetID == currentNetwork.NetID {
|
||||||
hasrangeupdate := newNetwork.AddressRange != currentNetwork.AddressRange
|
hasrangeupdate := newNetwork.AddressRange != currentNetwork.AddressRange
|
||||||
localrangeupdate := newNetwork.LocalRange != currentNetwork.LocalRange
|
localrangeupdate := newNetwork.LocalRange != currentNetwork.LocalRange
|
||||||
|
hasholepunchupdate := newNetwork.DefaultUDPHolePunch != currentNetwork.DefaultUDPHolePunch
|
||||||
data, err := json.Marshal(newNetwork)
|
data, err := json.Marshal(newNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, false, err
|
return false, false, false, err
|
||||||
}
|
}
|
||||||
newNetwork.SetNetworkLastModified()
|
newNetwork.SetNetworkLastModified()
|
||||||
err = database.Insert(newNetwork.NetID, string(data), database.NETWORKS_TABLE_NAME)
|
err = database.Insert(newNetwork.NetID, string(data), database.NETWORKS_TABLE_NAME)
|
||||||
return hasrangeupdate, localrangeupdate, err
|
return hasrangeupdate, localrangeupdate, hasholepunchupdate, err
|
||||||
}
|
}
|
||||||
// copy values
|
// copy values
|
||||||
return false, false, errors.New("failed to update network " + newNetwork.NetID + ", cannot change netid.")
|
return false, false, false, errors.New("failed to update network " + newNetwork.NetID + ", cannot change netid.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inc - increments an IP
|
// Inc - increments an IP
|
||||||
|
|
104
logic/nodes.go
104
logic/nodes.go
|
@ -5,7 +5,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
|
@ -237,7 +236,6 @@ func CreateNode(node *models.Node) error {
|
||||||
return fmt.Errorf("invalid address: ipv6 " + node.Address6 + " is not unique")
|
return fmt.Errorf("invalid address: ipv6 " + node.Address6 + " is not unique")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This covers legacy nodes, eventually want to remove legacy check
|
|
||||||
node.ID = uuid.NewString()
|
node.ID = uuid.NewString()
|
||||||
|
|
||||||
//Create a JWT for the node
|
//Create a JWT for the node
|
||||||
|
@ -269,67 +267,6 @@ func CreateNode(node *models.Node) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IfaceDelta - is there interface changes
|
|
||||||
// func IfaceDelta(currentNode *models.Node, newNode *models.Node) bool {
|
|
||||||
// SetNodeDefaults(newNode)
|
|
||||||
// // single comparison statements
|
|
||||||
// if currentNode.IsServer != "yes" {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if newNode.Endpoint != currentNode.Endpoint ||
|
|
||||||
// newNode.LocalAddress != currentNode.LocalAddress ||
|
|
||||||
// newNode.PublicKey != currentNode.PublicKey ||
|
|
||||||
// newNode.Address != currentNode.Address ||
|
|
||||||
// newNode.IsEgressGateway != currentNode.IsEgressGateway ||
|
|
||||||
// newNode.IsIngressGateway != currentNode.IsIngressGateway ||
|
|
||||||
// newNode.IsRelay != currentNode.IsRelay ||
|
|
||||||
// newNode.UDPHolePunch != currentNode.UDPHolePunch ||
|
|
||||||
// newNode.IsPending != currentNode.IsPending ||
|
|
||||||
// newNode.PersistentKeepalive != currentNode.PersistentKeepalive ||
|
|
||||||
// len(newNode.ExcludedAddrs) != len(currentNode.ExcludedAddrs) ||
|
|
||||||
// len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // multi-comparison statements
|
|
||||||
// if newNode.IsDualStack == "yes" {
|
|
||||||
// if newNode.Address6 != currentNode.Address6 {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if newNode.IsEgressGateway == "yes" {
|
|
||||||
// if len(currentNode.EgressGatewayRanges) != len(newNode.EgressGatewayRanges) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// for _, address := range newNode.EgressGatewayRanges {
|
|
||||||
// if !StringSliceContains(currentNode.EgressGatewayRanges, address) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if newNode.IsRelay == "yes" {
|
|
||||||
// if len(currentNode.RelayAddrs) != len(newNode.RelayAddrs) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// for _, address := range newNode.RelayAddrs {
|
|
||||||
// if !StringSliceContains(currentNode.RelayAddrs, address) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for _, address := range newNode.AllowedIPs {
|
|
||||||
// if !StringSliceContains(currentNode.AllowedIPs, address) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
|
|
||||||
// GetAllNodes - returns all nodes in the DB
|
// GetAllNodes - returns all nodes in the DB
|
||||||
func GetAllNodes() ([]models.Node, error) {
|
func GetAllNodes() ([]models.Node, error) {
|
||||||
var nodes []models.Node
|
var nodes []models.Node
|
||||||
|
@ -602,28 +539,35 @@ func GetDeletedNodeByID(uuid string) (models.Node, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNetworkServerNodeID - get network server node ID if exists
|
// GetNetworkServerNodeID - get network server node ID if exists
|
||||||
func GetNetworkServerNodeID(network string) (string, error) {
|
func GetNetworkServerLeader(network string) (models.Node, error) {
|
||||||
var nodes, err = GetNetworkNodes(network)
|
nodes, err := GetSortedNetworkServerNodes(network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return models.Node{}, err
|
||||||
}
|
}
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
if node.IsServer == "yes" {
|
if IsLeader(&node) {
|
||||||
if servercfg.GetNodeID() != "" {
|
return node, nil
|
||||||
if servercfg.GetNodeID() == node.MacAddress {
|
|
||||||
if strings.Contains(node.ID, "###") {
|
|
||||||
DeleteNodeByMacAddress(&node, true)
|
|
||||||
logger.Log(1, "deleted legacy server node on network "+node.Network)
|
|
||||||
return "", errors.New("deleted legacy server node on network " + node.Network)
|
|
||||||
}
|
|
||||||
return node.ID, nil
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return node.ID, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", errors.New("could not find server node")
|
return models.Node{}, errors.New("could not find server leader")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetworkServerNodeID - get network server node ID if exists
|
||||||
|
func GetNetworkServerLocal(network string) (models.Node, error) {
|
||||||
|
nodes, err := GetSortedNetworkServerNodes(network)
|
||||||
|
if err != nil {
|
||||||
|
return models.Node{}, err
|
||||||
|
}
|
||||||
|
mac := servercfg.GetNodeID()
|
||||||
|
if mac == "" {
|
||||||
|
return models.Node{}, fmt.Errorf("error retrieving local server node: server node ID is unset")
|
||||||
|
}
|
||||||
|
for _, node := range nodes {
|
||||||
|
if mac == node.MacAddress {
|
||||||
|
return node, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return models.Node{}, errors.New("could not find node for local server")
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateServer - make sure servers dont change port or address
|
// validateServer - make sure servers dont change port or address
|
||||||
|
|
|
@ -73,7 +73,7 @@ func GetPeerUpdate(node *models.Node) (models.PeerUpdate, error) {
|
||||||
}
|
}
|
||||||
peers = append(peers, peerData)
|
peers = append(peers, peerData)
|
||||||
if peer.IsServer == "yes" {
|
if peer.IsServer == "yes" {
|
||||||
serverNodeAddresses = append(serverNodeAddresses, models.ServerAddr{ID: peer.ID, IsLeader: IsLeader(&peer), Address: peer.Address})
|
serverNodeAddresses = append(serverNodeAddresses, models.ServerAddr{IsLeader: IsLeader(&peer), Address: peer.Address})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if node.IsIngressGateway == "yes" {
|
if node.IsIngressGateway == "yes" {
|
||||||
|
|
|
@ -25,6 +25,27 @@ func RemoveConf(iface string, printlog bool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasPeerConnected - checks if a client node has connected over WG
|
||||||
|
func HasPeerConnected(node *models.Node) bool {
|
||||||
|
client, err := wgctrl.New()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
device, err := client.Device(node.Interface)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, peer := range device.Peers {
|
||||||
|
if peer.PublicKey.String() == node.PublicKey {
|
||||||
|
if peer.Endpoint != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// == Private Functions ==
|
// == Private Functions ==
|
||||||
|
|
||||||
// gets the server peers locally
|
// gets the server peers locally
|
||||||
|
|
|
@ -177,7 +177,6 @@ type Telemetry struct {
|
||||||
|
|
||||||
// ServerAddr - to pass to clients to tell server addresses and if it's the leader or not
|
// ServerAddr - to pass to clients to tell server addresses and if it's the leader or not
|
||||||
type ServerAddr struct {
|
type ServerAddr struct {
|
||||||
ID string `json:"id" bson:"id" yaml:"id"`
|
|
||||||
IsLeader bool `json:"isleader" bson:"isleader" yaml:"isleader"`
|
IsLeader bool `json:"isleader" bson:"isleader" yaml:"isleader"`
|
||||||
Address string `json:"address" bson:"address" yaml:"address"`
|
Address string `json:"address" bson:"address" yaml:"address"`
|
||||||
}
|
}
|
||||||
|
|
23
mq/mq.go
23
mq/mq.go
|
@ -195,13 +195,7 @@ func Keepalive(ctx context.Context) {
|
||||||
logger.Log(1, "error retrieving networks for keepalive", err.Error())
|
logger.Log(1, "error retrieving networks for keepalive", err.Error())
|
||||||
}
|
}
|
||||||
for _, network := range networks {
|
for _, network := range networks {
|
||||||
var id string
|
serverNode, errN := logic.GetNetworkServerLeader(network.NetID)
|
||||||
for _, servAddr := range network.DefaultServerAddrs {
|
|
||||||
if servAddr.IsLeader {
|
|
||||||
id = servAddr.ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
serverNode, errN := logic.GetNodeByID(id)
|
|
||||||
if errN == nil {
|
if errN == nil {
|
||||||
serverNode.SetLastCheckIn()
|
serverNode.SetLastCheckIn()
|
||||||
logic.UpdateNode(&serverNode, &serverNode)
|
logic.UpdateNode(&serverNode, &serverNode)
|
||||||
|
@ -210,14 +204,19 @@ func Keepalive(ctx context.Context) {
|
||||||
}
|
}
|
||||||
err = PublishPeerUpdate(&serverNode)
|
err = PublishPeerUpdate(&serverNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(1, "error publishing udp port updates", err.Error())
|
logger.Log(1, "error publishing udp port updates for network", network.NetID)
|
||||||
|
logger.Log(1, errN.Error())
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
if id == "" {
|
logger.Log(1, "unable to retrieve leader for network ", network.NetID)
|
||||||
logger.Log(0, "leader not defined for network", network.NetID)
|
logger.Log(1, errN.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if token := client.Publish("serverkeepalive/"+id, 0, false, servercfg.GetVersion()); token.Wait() && token.Error() != nil {
|
if serverNode.Address == "" {
|
||||||
|
logger.Log(1, "leader not defined for network ", network.NetID)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if token := client.Publish("serverkeepalive/"+network.NetID, 0, false, servercfg.GetVersion()); token.Wait() && token.Error() != nil {
|
||||||
logger.Log(1, "error publishing server keepalive for network", network.NetID, token.Error().Error())
|
logger.Log(1, "error publishing server keepalive for network", network.NetID, token.Error().Error())
|
||||||
} else {
|
} else {
|
||||||
logger.Log(2, "keepalive sent for network", network.NetID)
|
logger.Log(2, "keepalive sent for network", network.NetID)
|
||||||
|
|
|
@ -62,21 +62,21 @@ func GetCommands(cliFlags []cli.Flag) []*cli.Command {
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
Name: "push",
|
// Name: "push",
|
||||||
Usage: "Push configuration changes to server.",
|
// Usage: "Push configuration changes to server.",
|
||||||
Flags: cliFlags,
|
// Flags: cliFlags,
|
||||||
// the action, or code that will be executed when
|
// // the action, or code that will be executed when
|
||||||
// we execute our `ns` command
|
// // we execute our `ns` command
|
||||||
Action: func(c *cli.Context) error {
|
// Action: func(c *cli.Context) error {
|
||||||
cfg, _, err := config.GetCLIConfig(c)
|
// cfg, _, err := config.GetCLIConfig(c)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
err = command.Push(cfg)
|
// err = command.Push(cfg)
|
||||||
return err
|
// return err
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
Name: "pull",
|
Name: "pull",
|
||||||
Usage: "Pull latest configuration and peers from server.",
|
Usage: "Pull latest configuration and peers from server.",
|
||||||
|
|
|
@ -185,7 +185,7 @@ func LeaveNetwork(network string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//extra network route setting required for freebsd and windows
|
// extra network route setting required for freebsd and windows, TODO mac??
|
||||||
if ncutils.IsWindows() {
|
if ncutils.IsWindows() {
|
||||||
ip, mask, err := ncutils.GetNetworkIPMask(node.NetworkSettings.AddressRange)
|
ip, mask, err := ncutils.GetNetworkIPMask(node.NetworkSettings.AddressRange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -197,7 +197,12 @@ func LeaveNetwork(network string) error {
|
||||||
} else if ncutils.IsLinux() {
|
} else if ncutils.IsLinux() {
|
||||||
_, _ = ncutils.RunCmd("ip -4 route del "+node.NetworkSettings.AddressRange+" dev "+node.Interface, false)
|
_, _ = ncutils.RunCmd("ip -4 route del "+node.NetworkSettings.AddressRange+" dev "+node.Interface, false)
|
||||||
}
|
}
|
||||||
return RemoveLocalInstance(cfg, network)
|
|
||||||
|
currentNets, err := ncutils.GetSystemNetworks()
|
||||||
|
if err != nil || len(currentNets) <= 1 {
|
||||||
|
return RemoveLocalInstance(cfg, network)
|
||||||
|
}
|
||||||
|
return daemon.Restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveLocalInstance - remove all netclient files locally for a network
|
// RemoveLocalInstance - remove all netclient files locally for a network
|
||||||
|
|
|
@ -3,7 +3,6 @@ package functions
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -30,17 +29,31 @@ var messageCache = new(sync.Map)
|
||||||
const lastNodeUpdate = "lnu"
|
const lastNodeUpdate = "lnu"
|
||||||
const lastPeerUpdate = "lpu"
|
const lastPeerUpdate = "lpu"
|
||||||
|
|
||||||
|
type cachedMessage struct {
|
||||||
|
Message string
|
||||||
|
LastSeen time.Time
|
||||||
|
}
|
||||||
|
|
||||||
func insert(network, which, cache string) {
|
func insert(network, which, cache string) {
|
||||||
// var mu sync.Mutex
|
var newMessage = cachedMessage{
|
||||||
// mu.Lock()
|
Message: cache,
|
||||||
// defer mu.Unlock()
|
LastSeen: time.Now(),
|
||||||
messageCache.Store(fmt.Sprintf("%s%s", network, which), cache)
|
}
|
||||||
|
ncutils.Log("storing new message: " + cache)
|
||||||
|
messageCache.Store(fmt.Sprintf("%s%s", network, which), newMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func read(network, which string) string {
|
func read(network, which string) string {
|
||||||
val, isok := messageCache.Load(fmt.Sprintf("%s%s", network, which))
|
val, isok := messageCache.Load(fmt.Sprintf("%s%s", network, which))
|
||||||
if isok {
|
if isok {
|
||||||
return fmt.Sprintf("%v", val)
|
var readMessage = val.(cachedMessage) // fetch current cached message
|
||||||
|
if time.Now().After(readMessage.LastSeen.Add(time.Minute)) { // check if message has been there over a minute
|
||||||
|
messageCache.Delete(fmt.Sprintf("%s%s", network, which)) // remove old message if expired
|
||||||
|
ncutils.Log("cached message expired")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
ncutils.Log("cache hit, skipping probably " + readMessage.Message)
|
||||||
|
return readMessage.Message // return current message if not expired
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -108,19 +121,27 @@ func MessageQueue(ctx context.Context, network string) {
|
||||||
var cfg config.ClientConfig
|
var cfg config.ClientConfig
|
||||||
cfg.Network = network
|
cfg.Network = network
|
||||||
ncutils.Log("pulling latest config for " + cfg.Network)
|
ncutils.Log("pulling latest config for " + cfg.Network)
|
||||||
sleepTime := 2
|
var configPath = fmt.Sprintf("%sconfig/netconfig-%s", ncutils.GetNetclientPathSpecific(), network)
|
||||||
for {
|
fileInfo, err := os.Stat(configPath)
|
||||||
_, err := Pull(network, true)
|
if err != nil {
|
||||||
if err == nil {
|
ncutils.Log("could not stat config file: " + configPath)
|
||||||
break
|
}
|
||||||
|
// speed up UDP rest
|
||||||
|
if time.Now().After(fileInfo.ModTime().Add(time.Minute)) {
|
||||||
|
sleepTime := 2
|
||||||
|
for {
|
||||||
|
_, err := Pull(network, true)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if sleepTime > 3600 {
|
||||||
|
sleepTime = 3600
|
||||||
|
}
|
||||||
|
ncutils.Log("failed to pull for network " + network)
|
||||||
|
ncutils.Log(fmt.Sprintf("waiting %d seconds to retry...", sleepTime))
|
||||||
|
time.Sleep(time.Second * time.Duration(sleepTime))
|
||||||
|
sleepTime = sleepTime * 2
|
||||||
}
|
}
|
||||||
if sleepTime > 3600 {
|
|
||||||
sleepTime = 3600
|
|
||||||
}
|
|
||||||
ncutils.Log("failed to pull for network " + network)
|
|
||||||
ncutils.Log(fmt.Sprintf("waiting %d seconds to retry...", sleepTime))
|
|
||||||
time.Sleep(time.Second * time.Duration(sleepTime))
|
|
||||||
sleepTime = sleepTime * 2
|
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second << 1)
|
time.Sleep(time.Second << 1)
|
||||||
cfg.ReadConfig()
|
cfg.ReadConfig()
|
||||||
|
@ -147,25 +168,24 @@ func MessageQueue(ctx context.Context, network string) {
|
||||||
if cfg.DebugOn {
|
if cfg.DebugOn {
|
||||||
ncutils.Log(fmt.Sprintf("subscribed to peer updates for node %s peers/%s/%s", cfg.Node.Name, cfg.Node.Network, cfg.Node.ID))
|
ncutils.Log(fmt.Sprintf("subscribed to peer updates for node %s peers/%s/%s", cfg.Node.Name, cfg.Node.Network, cfg.Node.ID))
|
||||||
}
|
}
|
||||||
var id string
|
|
||||||
var found bool
|
var found bool
|
||||||
for _, server := range cfg.NetworkSettings.DefaultServerAddrs {
|
for _, server := range cfg.NetworkSettings.DefaultServerAddrs {
|
||||||
if server.IsLeader {
|
if !server.IsLeader {
|
||||||
id = server.ID
|
continue
|
||||||
}
|
}
|
||||||
if server.Address != "" {
|
if server.Address != "" {
|
||||||
if token := client.Subscribe("serverkeepalive/"+id, 0, mqtt.MessageHandler(ServerKeepAlive)); token.Wait() && token.Error() != nil {
|
if token := client.Subscribe("serverkeepalive/"+cfg.Node.Network, 0, mqtt.MessageHandler(ServerKeepAlive)); token.Wait() && token.Error() != nil {
|
||||||
ncutils.Log(token.Error().Error())
|
ncutils.Log(token.Error().Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
found = true
|
found = true
|
||||||
if cfg.DebugOn {
|
if cfg.DebugOn {
|
||||||
ncutils.Log("subscribed to server keepalives for server " + id)
|
ncutils.Log("subscribed to server keepalives for server " + cfg.Node.Network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
ncutils.Log("leader not defined for network " + cfg.Network)
|
ncutils.Log("leader not defined for network " + cfg.Node.Network)
|
||||||
}
|
}
|
||||||
defer client.Disconnect(250)
|
defer client.Disconnect(250)
|
||||||
go MonitorKeepalive(ctx, client, &cfg)
|
go MonitorKeepalive(ctx, client, &cfg)
|
||||||
|
@ -219,6 +239,7 @@ func NodeUpdate(client mqtt.Client, msg mqtt.Message) {
|
||||||
newNode.OS = runtime.GOOS
|
newNode.OS = runtime.GOOS
|
||||||
// check if interface needs to delta
|
// check if interface needs to delta
|
||||||
ifaceDelta := ncutils.IfaceDelta(&cfg.Node, &newNode)
|
ifaceDelta := ncutils.IfaceDelta(&cfg.Node, &newNode)
|
||||||
|
shouldDNSChange := cfg.Node.DNSOn != newNode.DNSOn
|
||||||
|
|
||||||
cfg.Node = newNode
|
cfg.Node = newNode
|
||||||
switch newNode.Action {
|
switch newNode.Action {
|
||||||
|
@ -265,24 +286,18 @@ func NodeUpdate(client mqtt.Client, msg mqtt.Message) {
|
||||||
ncutils.Log("error resubscribing after interface change " + err.Error())
|
ncutils.Log("error resubscribing after interface change " + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
if newNode.DNSOn == "yes" {
|
||||||
/*
|
ncutils.Log("setting up DNS")
|
||||||
else {
|
for _, server := range cfg.Node.NetworkSettings.DefaultServerAddrs {
|
||||||
ncutils.Log("syncing conf to " + file)
|
if server.IsLeader {
|
||||||
err = wireguard.SyncWGQuickConf(cfg.Node.Interface, file)
|
go setDNS(cfg.Node.Interface, cfg.Network, server.Address)
|
||||||
if err != nil {
|
break
|
||||||
ncutils.Log("error syncing wg after peer update " + err.Error())
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
//deal with DNS
|
//deal with DNS
|
||||||
if newNode.DNSOn == "yes" {
|
if newNode.DNSOn != "yes" && shouldDNSChange && cfg.Node.Interface != "" {
|
||||||
ncutils.Log("setting up DNS")
|
|
||||||
if err = local.UpdateDNS(cfg.Node.Interface, cfg.Network, cfg.Server.CoreDNSAddr); err != nil {
|
|
||||||
ncutils.Log("error applying dns" + err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ncutils.Log("settng DNS off")
|
ncutils.Log("settng DNS off")
|
||||||
_, err := ncutils.RunCmd("/usr/bin/resolvectl revert "+cfg.Node.Interface, true)
|
_, err := ncutils.RunCmd("/usr/bin/resolvectl revert "+cfg.Node.Interface, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -311,14 +326,12 @@ func UpdatePeers(client mqtt.Client, msg mqtt.Message) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// see if cache hit, if so skip
|
// see if cache hit, if so skip
|
||||||
/*
|
var currentMessage = read(peerUpdate.Network, lastPeerUpdate)
|
||||||
var currentMessage = read(peerUpdate.Network, lastPeerUpdate)
|
if currentMessage == string(data) {
|
||||||
if currentMessage == string(data) {
|
ncutils.Log("cache hit")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
insert(peerUpdate.Network, lastPeerUpdate, string(data))
|
insert(peerUpdate.Network, lastPeerUpdate, string(data))
|
||||||
ncutils.Log("update peer handler")
|
|
||||||
|
|
||||||
file := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf"
|
file := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf"
|
||||||
err = wireguard.UpdateWgPeers(file, peerUpdate.Peers)
|
err = wireguard.UpdateWgPeers(file, peerUpdate.Peers)
|
||||||
|
@ -326,31 +339,25 @@ func UpdatePeers(client mqtt.Client, msg mqtt.Message) {
|
||||||
ncutils.Log("error updating wireguard peers" + err.Error())
|
ncutils.Log("error updating wireguard peers" + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ncutils.Log("syncing conf to " + file)
|
|
||||||
//err = wireguard.SyncWGQuickConf(cfg.Node.Interface, file)
|
//err = wireguard.SyncWGQuickConf(cfg.Node.Interface, file)
|
||||||
err = wireguard.SetPeers(cfg.Node.Interface, cfg.Node.PersistentKeepalive, peerUpdate.Peers)
|
err = wireguard.SetPeers(cfg.Node.Interface, cfg.Node.PersistentKeepalive, peerUpdate.Peers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ncutils.Log("error syncing wg after peer update " + err.Error())
|
ncutils.Log("error syncing wg after peer update " + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
ncutils.Log(fmt.Sprintf("received peer update on network, %s", cfg.Network))
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonitorKeepalive - checks time last server keepalive received. If more than 3+ minutes, notify and resubscribe
|
// MonitorKeepalive - checks time last server keepalive received. If more than 3+ minutes, notify and resubscribe
|
||||||
func MonitorKeepalive(ctx context.Context, client mqtt.Client, cfg *config.ClientConfig) {
|
func MonitorKeepalive(ctx context.Context, client mqtt.Client, cfg *config.ClientConfig) {
|
||||||
var id string
|
|
||||||
for _, servAddr := range cfg.NetworkSettings.DefaultServerAddrs {
|
|
||||||
if servAddr.IsLeader {
|
|
||||||
id = servAddr.ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case <-time.After(time.Second * 150):
|
case <-time.After(time.Second * 150):
|
||||||
var keepalivetime time.Time
|
var keepalivetime time.Time
|
||||||
keepaliveval, ok := keepalive.Load(id)
|
keepaliveval, ok := keepalive.Load(cfg.Node.Network)
|
||||||
if ok {
|
if ok {
|
||||||
keepalivetime = keepaliveval.(time.Time)
|
keepalivetime = keepaliveval.(time.Time)
|
||||||
} else {
|
} else {
|
||||||
|
@ -370,15 +377,7 @@ func MonitorKeepalive(ctx context.Context, client mqtt.Client, cfg *config.Clien
|
||||||
|
|
||||||
// ServerKeepAlive -- handler to react to keepalive messages published by server
|
// ServerKeepAlive -- handler to react to keepalive messages published by server
|
||||||
func ServerKeepAlive(client mqtt.Client, msg mqtt.Message) {
|
func ServerKeepAlive(client mqtt.Client, msg mqtt.Message) {
|
||||||
// var mu sync.Mutex
|
keepalive.Store(parseNetworkFromTopic(msg.Topic()), time.Now())
|
||||||
// mu.Lock()
|
|
||||||
// defer mu.Unlock()
|
|
||||||
serverid, err := getID(msg.Topic())
|
|
||||||
if err != nil {
|
|
||||||
ncutils.Log("invalid ID in serverkeepalive topic")
|
|
||||||
}
|
|
||||||
keepalive.Store(serverid, time.Now())
|
|
||||||
// ncutils.Log("keepalive from server")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resubscribe --- handles resubscribing if needed
|
// Resubscribe --- handles resubscribing if needed
|
||||||
|
@ -398,25 +397,24 @@ func Resubscribe(client mqtt.Client, cfg *config.ClientConfig) error {
|
||||||
ncutils.Log("error resubscribing to peers for " + cfg.Node.Network)
|
ncutils.Log("error resubscribing to peers for " + cfg.Node.Network)
|
||||||
return token.Error()
|
return token.Error()
|
||||||
}
|
}
|
||||||
var id string
|
|
||||||
var found bool
|
var found bool
|
||||||
for _, server := range cfg.NetworkSettings.DefaultServerAddrs {
|
for _, server := range cfg.NetworkSettings.DefaultServerAddrs {
|
||||||
if server.IsLeader {
|
if !server.IsLeader {
|
||||||
id = server.ID
|
continue
|
||||||
}
|
}
|
||||||
if server.Address != "" {
|
if server.Address != "" {
|
||||||
if token := client.Subscribe("serverkeepalive/"+id, 0, mqtt.MessageHandler(ServerKeepAlive)); token.Wait() && token.Error() != nil {
|
if token := client.Subscribe("serverkeepalive/"+cfg.Node.Network, 0, mqtt.MessageHandler(ServerKeepAlive)); token.Wait() && token.Error() != nil {
|
||||||
ncutils.Log("error resubscribing to serverkeepalive for " + cfg.Node.Network)
|
ncutils.Log("error resubscribing to serverkeepalive for " + cfg.Node.Network)
|
||||||
return token.Error()
|
return token.Error()
|
||||||
}
|
}
|
||||||
found = true
|
found = true
|
||||||
if cfg.DebugOn {
|
if cfg.DebugOn {
|
||||||
ncutils.Log("subscribed to server keepalives for server " + id)
|
ncutils.Log("subscribed to server keepalives for server " + cfg.Node.Network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
ncutils.Log("leader not defined for network " + cfg.Network)
|
ncutils.Log("leader not defined for network " + cfg.Node.Network)
|
||||||
}
|
}
|
||||||
ncutils.Log("finished re subbing")
|
ncutils.Log("finished re subbing")
|
||||||
return nil
|
return nil
|
||||||
|
@ -568,24 +566,15 @@ func decryptMsg(cfg *config.ClientConfig, msg []byte) ([]byte, error) {
|
||||||
return ncutils.BoxDecrypt(msg, serverPubKey, diskKey)
|
return ncutils.BoxDecrypt(msg, serverPubKey, diskKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldResub(currentServers, newServers []models.ServerAddr) bool {
|
func setDNS(iface, network, address string) {
|
||||||
if len(currentServers) != len(newServers) {
|
var reachable bool
|
||||||
return true
|
for counter := 0; !reachable && counter < 5; counter++ {
|
||||||
|
reachable = local.IsDNSReachable(address)
|
||||||
|
time.Sleep(time.Second << 1)
|
||||||
}
|
}
|
||||||
for _, srv := range currentServers {
|
if !reachable {
|
||||||
if !ncutils.ServerAddrSliceContains(newServers, srv) {
|
ncutils.Log("not setting dns, server unreachable: " + address)
|
||||||
return true
|
} else if err := local.UpdateDNS(iface, network, address); err != nil {
|
||||||
}
|
ncutils.Log("error applying dns" + err.Error())
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func getID(topic string) (string, error) {
|
|
||||||
parts := strings.Split(topic, "/")
|
|
||||||
count := len(parts)
|
|
||||||
if count == 1 {
|
|
||||||
return "", errors.New("invalid topic")
|
|
||||||
}
|
|
||||||
//the last part of the topic will be the network.ID
|
|
||||||
return parts[count-1], nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,9 +109,9 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ncutils.IsLinux() {
|
if ncutils.IsLinux() {
|
||||||
_, err := exec.LookPath("resolvconf")
|
_, err := exec.LookPath("resolvectl")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ncutils.PrintLog("resolvconf not present", 2)
|
ncutils.PrintLog("resolvectl not present", 2)
|
||||||
ncutils.PrintLog("unable to configure DNS automatically, disabling automated DNS management", 2)
|
ncutils.PrintLog("unable to configure DNS automatically, disabling automated DNS management", 2)
|
||||||
cfg.Node.DNSOn = "no"
|
cfg.Node.DNSOn = "no"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package local
|
package local
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
//"github.com/davecgh/go-spew/spew"
|
//"github.com/davecgh/go-spew/spew"
|
||||||
"log"
|
"log"
|
||||||
|
@ -11,6 +14,8 @@ import (
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DNS_UNREACHABLE_ERROR = "nameserver unreachable"
|
||||||
|
|
||||||
// SetDNS - sets the DNS of a local machine
|
// SetDNS - sets the DNS of a local machine
|
||||||
func SetDNS(nameserver string) error {
|
func SetDNS(nameserver string) error {
|
||||||
bytes, err := os.ReadFile("/etc/resolv.conf")
|
bytes, err := os.ReadFile("/etc/resolv.conf")
|
||||||
|
@ -35,9 +40,21 @@ func SetDNS(nameserver string) error {
|
||||||
|
|
||||||
// UpdateDNS - updates local DNS of client
|
// UpdateDNS - updates local DNS of client
|
||||||
func UpdateDNS(ifacename string, network string, nameserver string) error {
|
func UpdateDNS(ifacename string, network string, nameserver string) error {
|
||||||
|
if ifacename == "" {
|
||||||
|
return fmt.Errorf("cannot set dns: interface name is blank")
|
||||||
|
}
|
||||||
|
if network == "" {
|
||||||
|
return fmt.Errorf("cannot set dns: network name is blank")
|
||||||
|
}
|
||||||
|
if nameserver == "" {
|
||||||
|
return fmt.Errorf("cannot set dns: nameserver is blank")
|
||||||
|
}
|
||||||
if ncutils.IsWindows() {
|
if ncutils.IsWindows() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if !IsDNSReachable(nameserver) {
|
||||||
|
return fmt.Errorf(DNS_UNREACHABLE_ERROR + " : " + nameserver + ":53")
|
||||||
|
}
|
||||||
_, err := exec.LookPath("resolvectl")
|
_, err := exec.LookPath("resolvectl")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
@ -60,3 +77,21 @@ func UpdateDNS(ifacename string, network string, nameserver string) error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsDNSReachable(nameserver string) bool {
|
||||||
|
port := "53"
|
||||||
|
protocols := [2]string{"tcp", "udp"}
|
||||||
|
for _, proto := range protocols {
|
||||||
|
timeout := time.Second
|
||||||
|
conn, err := net.DialTimeout(proto, net.JoinHostPort(nameserver, port), timeout)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if conn != nil {
|
||||||
|
defer conn.Close()
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
48
netclient/local/routes.go
Normal file
48
netclient/local/routes.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package local
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetPeerRoutes - sets/removes ip routes for each peer on a network
|
||||||
|
func SetPeerRoutes(iface string, oldPeers map[string][]net.IPNet, newPeers []wgtypes.PeerConfig) {
|
||||||
|
// traverse through all recieved peers
|
||||||
|
for _, peer := range newPeers {
|
||||||
|
// if pubkey found in existing peers, check against existing peer
|
||||||
|
currPeerAllowedIPs := oldPeers[peer.PublicKey.String()]
|
||||||
|
if currPeerAllowedIPs != nil {
|
||||||
|
// traverse IPs, check to see if old peer contains each IP
|
||||||
|
for _, allowedIP := range peer.AllowedIPs { // compare new ones (if any) to old ones
|
||||||
|
if !ncutils.IPNetSliceContains(currPeerAllowedIPs, allowedIP) {
|
||||||
|
if err := setRoute(iface, &allowedIP); err != nil {
|
||||||
|
ncutils.PrintLog(err.Error(), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, allowedIP := range currPeerAllowedIPs { // compare old ones (if any) to new ones
|
||||||
|
if !ncutils.IPNetSliceContains(peer.AllowedIPs, allowedIP) {
|
||||||
|
if err := deleteRoute(iface, &allowedIP); err != nil {
|
||||||
|
ncutils.PrintLog(err.Error(), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(oldPeers, peer.PublicKey.String()) // remove peer as it was found and processed
|
||||||
|
} else {
|
||||||
|
for _, allowedIP := range peer.AllowedIPs { // add all routes as peer doesn't exist
|
||||||
|
if err := setRoute(iface, &allowedIP); err != nil {
|
||||||
|
ncutils.PrintLog(err.Error(), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// traverse through all remaining existing peers
|
||||||
|
for _, allowedIPs := range oldPeers {
|
||||||
|
for _, allowedIP := range allowedIPs {
|
||||||
|
deleteRoute(iface, &allowedIP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
netclient/local/routes_linux.go
Normal file
25
netclient/local/routes_linux.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package local
|
||||||
|
|
||||||
|
import (
|
||||||
|
//"github.com/davecgh/go-spew/spew"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setRoute(iface string, addr *net.IPNet) error {
|
||||||
|
var err error
|
||||||
|
_, err = ncutils.RunCmd(fmt.Sprintf("ip route add %s dev %s", addr.String(), iface), true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteRoute(iface string, addr *net.IPNet) error {
|
||||||
|
var err error
|
||||||
|
_, err = ncutils.RunCmd(fmt.Sprintf("ip route del %s dev %s", addr.String(), iface), true)
|
||||||
|
return err
|
||||||
|
}
|
33
netclient/local/routes_other.go
Normal file
33
netclient/local/routes_other.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package local
|
||||||
|
|
||||||
|
import (
|
||||||
|
//"github.com/davecgh/go-spew/spew"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
//"github.com/davecgh/go-spew/spew"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
These functions are not used. These should only be called by Linux (see routes_linux.go). These routes return nothing if called.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func setRoute(iface string, addr *net.IPNet) error {
|
||||||
|
var err error
|
||||||
|
_, err = ncutils.RunCmd(fmt.Sprintf("ip route add %s dev %s", addr.String(), iface), true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteRoute(iface string, addr *net.IPNet) error {
|
||||||
|
var err error
|
||||||
|
_, err = ncutils.RunCmd(fmt.Sprintf("ip route del %s dev %s", addr.String(), iface), true)
|
||||||
|
return err
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ func IfaceDelta(currentNode *models.Node, newNode *models.Node) bool {
|
||||||
newNode.UDPHolePunch != currentNode.UDPHolePunch ||
|
newNode.UDPHolePunch != currentNode.UDPHolePunch ||
|
||||||
newNode.IsPending != currentNode.IsPending ||
|
newNode.IsPending != currentNode.IsPending ||
|
||||||
newNode.PersistentKeepalive != currentNode.PersistentKeepalive ||
|
newNode.PersistentKeepalive != currentNode.PersistentKeepalive ||
|
||||||
|
newNode.DNSOn != currentNode.DNSOn ||
|
||||||
len(newNode.ExcludedAddrs) != len(currentNode.ExcludedAddrs) ||
|
len(newNode.ExcludedAddrs) != len(currentNode.ExcludedAddrs) ||
|
||||||
len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) {
|
len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) {
|
||||||
return true
|
return true
|
||||||
|
@ -70,6 +71,16 @@ func StringSliceContains(slice []string, item string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPNetSliceContains - sees if a string slice contains a string element
|
||||||
|
func IPNetSliceContains(slice []net.IPNet, item net.IPNet) bool {
|
||||||
|
for _, s := range slice {
|
||||||
|
if s.String() == item.String() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// IfaceExists - return true if you can find the iface
|
// IfaceExists - return true if you can find the iface
|
||||||
func IfaceExists(ifacename string) bool {
|
func IfaceExists(ifacename string) bool {
|
||||||
localnets, err := net.Interfaces()
|
localnets, err := net.Interfaces()
|
||||||
|
|
|
@ -3,6 +3,7 @@ package wireguard
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -25,8 +26,8 @@ const (
|
||||||
|
|
||||||
// SetPeers - sets peers on a given WireGuard interface
|
// SetPeers - sets peers on a given WireGuard interface
|
||||||
func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error {
|
func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error {
|
||||||
|
|
||||||
var devicePeers []wgtypes.Peer
|
var devicePeers []wgtypes.Peer
|
||||||
|
var oldPeerAllowedIps = make(map[string][]net.IPNet, len(peers))
|
||||||
var err error
|
var err error
|
||||||
if ncutils.IsFreeBSD() {
|
if ncutils.IsFreeBSD() {
|
||||||
if devicePeers, err = ncutils.GetPeers(iface); err != nil {
|
if devicePeers, err = ncutils.GetPeers(iface); err != nil {
|
||||||
|
@ -100,10 +101,13 @@ func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error {
|
||||||
log.Println(output, "error removing peer", currentPeer.PublicKey.String())
|
log.Println(output, "error removing peer", currentPeer.PublicKey.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
oldPeerAllowedIps[currentPeer.PublicKey.String()] = currentPeer.AllowedIPs
|
||||||
}
|
}
|
||||||
if ncutils.IsMac() {
|
if ncutils.IsMac() {
|
||||||
err = SetMacPeerRoutes(iface)
|
err = SetMacPeerRoutes(iface)
|
||||||
return err
|
return err
|
||||||
|
} else if ncutils.IsLinux() {
|
||||||
|
local.SetPeerRoutes(iface, oldPeerAllowedIps, peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -65,6 +65,9 @@ func ApplyWGQuickConf(confPath string, ifacename string) error {
|
||||||
ncutils.RunCmd("wg-quick down "+confPath, true)
|
ncutils.RunCmd("wg-quick down "+confPath, true)
|
||||||
}
|
}
|
||||||
_, err = ncutils.RunCmd("wg-quick up "+confPath, true)
|
_, err = ncutils.RunCmd("wg-quick up "+confPath, true)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,12 +44,8 @@ func SyncServerNetwork(network string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serverNodeID, err := logic.GetNetworkServerNodeID(network)
|
serverNode, err := logic.GetNetworkServerLocal(network)
|
||||||
if !ifaceExists && (err == nil && serverNodeID != "") {
|
if !ifaceExists && (err == nil && serverNode.ID != "") {
|
||||||
serverNode, err := logic.GetNodeByID(serverNodeID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return logic.ServerUpdate(&serverNode, true)
|
return logic.ServerUpdate(&serverNode, true)
|
||||||
} else if !ifaceExists {
|
} else if !ifaceExists {
|
||||||
_, err := logic.ServerJoin(&serverNetworkSettings)
|
_, err := logic.ServerJoin(&serverNetworkSettings)
|
||||||
|
|
Loading…
Reference in a new issue