Browse Source

transplanted setwgconfig and pull

0xdcarns 3 years ago
parent
commit
340f50c535
6 changed files with 249 additions and 55 deletions
  1. 50 0
      logic/network.go
  2. 72 9
      logic/server.go
  3. 22 1
      logic/util.go
  4. 97 8
      logic/wireguard.go
  5. 0 6
      netclient/functions/checkin.go
  6. 8 31
      serverctl/serverctl.go

+ 50 - 0
logic/network.go

@@ -2,8 +2,11 @@ package logic
 
 
 import (
 import (
 	"net"
 	"net"
+	"os/exec"
+	"strings"
 
 
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/ncutils"
 )
 )
 
 
 // GetLocalIP - gets the local ip
 // GetLocalIP - gets the local ip
@@ -61,3 +64,50 @@ func GetLocalIP(node models.Node) string {
 	}
 	}
 	return local
 	return local
 }
 }
+
+// == Private ==
+
+func deleteInterface(ifacename string, postdown string) error {
+	var err error
+	if !ncutils.IsKernel() {
+		err = RemoveConf(ifacename, true)
+	} else {
+		ipExec, errN := exec.LookPath("ip")
+		err = errN
+		if err != nil {
+			ncutils.PrintLog(err.Error(), 1)
+		}
+		_, err = ncutils.RunCmd(ipExec+" link del "+ifacename, false)
+		if postdown != "" {
+			runcmds := strings.Split(postdown, "; ")
+			err = ncutils.RunCmds(runcmds, true)
+		}
+	}
+	return err
+}
+
+func isInterfacePresent(iface string, address string) (string, bool) {
+	var interfaces []net.Interface
+	var err error
+	interfaces, err = net.Interfaces()
+	if err != nil {
+		Log("ERROR: could not read interfaces", 0)
+		return "", true
+	}
+	for _, currIface := range interfaces {
+		var currAddrs []net.Addr
+		currAddrs, err = currIface.Addrs()
+		if err != nil || len(currAddrs) == 0 {
+			continue
+		}
+		for _, addr := range currAddrs {
+			Log("looking at addresses "+addr.String()+" compared to "+address, 0)
+			if addr.String() == address && currIface.Name != iface {
+				Log("found it", 0)
+				// return old iface and false
+				return currIface.Name, false
+			}
+		}
+	}
+	return "", true
+}

+ 72 - 9
logic/server.go

@@ -4,6 +4,7 @@ import (
 	"errors"
 	"errors"
 	"log"
 	"log"
 	"net"
 	"net"
+	"os"
 	"runtime"
 	"runtime"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
@@ -35,7 +36,7 @@ func ServerJoin(cfg config.ClientConfig, privateKey string) error {
 			cfg.Node.Endpoint, err = ncutils.GetPublicIP()
 			cfg.Node.Endpoint, err = ncutils.GetPublicIP()
 		}
 		}
 		if err != nil || cfg.Node.Endpoint == "" {
 		if err != nil || cfg.Node.Endpoint == "" {
-			ncutils.Log("Error setting cfg.Node.Endpoint.")
+			Log("Error setting cfg.Node.Endpoint.", 0)
 			return err
 			return err
 		}
 		}
 	}
 	}
@@ -117,9 +118,9 @@ func ServerJoin(cfg config.ClientConfig, privateKey string) error {
 		return err
 		return err
 	}
 	}
 
 
-	peers, hasGateway, gateways, err := GetServerPeers(node.MacAddress, cfg.Network, cfg.Server.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes", node.IsServer == "yes")
+	peers, hasGateway, gateways, err := GetServerPeers(node.MacAddress, cfg.Network, node.IsDualStack == "yes", node.IsIngressGateway == "yes")
 	if err != nil && !ncutils.IsEmptyRecord(err) {
 	if err != nil && !ncutils.IsEmptyRecord(err) {
-		ncutils.Log("failed to retrieve peers")
+		Log("failed to retrieve peers", 1)
 		return err
 		return err
 	}
 	}
 
 
@@ -131,22 +132,84 @@ func ServerJoin(cfg config.ClientConfig, privateKey string) error {
 	return nil
 	return nil
 }
 }
 
 
+// ServerPull - pulls current config/peers for server
+func ServerPull(mac string, network string) error {
+
+	var serverNode models.Node
+	var err error
+	serverNode, err = GetNode(mac, network)
+	if err != nil {
+		return err
+	}
+
+	if serverNode.IPForwarding == "yes" {
+		if err = setIPForwardingLinux(); err != nil {
+			return err
+		}
+	}
+	serverNode.OS = runtime.GOOS
+
+	if serverNode.PullChanges == "yes" {
+		// check for interface change
+		var isIfacePresent bool
+		var oldIfaceName string
+		// checks if address is in use by another interface
+		oldIfaceName, isIfacePresent = isInterfacePresent(serverNode.Interface, serverNode.Address)
+		if !isIfacePresent {
+			if err = deleteInterface(oldIfaceName, serverNode.PostDown); err != nil {
+				Log("could not delete old interface "+oldIfaceName, 1)
+			}
+		}
+		serverNode.PullChanges = "no"
+		if err = setWGConfig(serverNode, network, false); err != nil {
+			return err
+		}
+		// handle server side update
+		if err = serverNode.Update(&serverNode); err != nil {
+			return err
+		}
+	} else {
+		if err = setWGConfig(serverNode, network, true); err != nil {
+			if errors.Is(err, os.ErrNotExist) {
+				return ServerPull(serverNode.MacAddress, serverNode.Network)
+			} else {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
 // ServerPush - pushes config changes for server checkins/join
 // ServerPush - pushes config changes for server checkins/join
 func ServerPush(mac string, network string) error {
 func ServerPush(mac string, network string) error {
 
 
 	var serverNode models.Node
 	var serverNode models.Node
 	var err error
 	var err error
 	serverNode, err = GetNode(mac, network)
 	serverNode, err = GetNode(mac, network)
-	if err != nil && !ncutils.IsEmptyRecord(err) {
+	if err != nil /* && !ncutils.IsEmptyRecord(err) May not be necessary */ {
 		return err
 		return err
 	}
 	}
 	serverNode.OS = runtime.GOOS
 	serverNode.OS = runtime.GOOS
 	serverNode.SetLastCheckIn()
 	serverNode.SetLastCheckIn()
-	err = serverNode.Update(&serverNode)
-	return err
+	return serverNode.Update(&serverNode)
+}
+
+// ServerLeave - removes a server node
+func ServerLeave(mac string, network string) error {
+
+	var serverNode models.Node
+	var err error
+	serverNode, err = GetNode(mac, network)
+	if err != nil {
+		return err
+	}
+	serverNode.SetID()
+	return DeleteNode(serverNode.ID, true)
 }
 }
 
 
-func GetServerPeers(macaddress string, network string, server string, dualstack bool, isIngressGateway bool, isServer bool) ([]wgtypes.PeerConfig, bool, []string, error) {
+// GetServerPeers - gets peers of server
+func GetServerPeers(macaddress string, network string, dualstack bool, isIngressGateway bool) ([]wgtypes.PeerConfig, bool, []string, error) {
 	hasGateway := false
 	hasGateway := false
 	var err error
 	var err error
 	var gateways []string
 	var gateways []string
@@ -277,7 +340,7 @@ func GetServerPeers(macaddress string, network string, server string, dualstack
 		peers = append(peers, peer)
 		peers = append(peers, peer)
 	}
 	}
 	if isIngressGateway {
 	if isIngressGateway {
-		extPeers, err := GetServerExtPeers(macaddress, network, server, dualstack)
+		extPeers, err := GetServerExtPeers(macaddress, network, dualstack)
 		if err == nil {
 		if err == nil {
 			peers = append(peers, extPeers...)
 			peers = append(peers, extPeers...)
 		} else {
 		} else {
@@ -288,7 +351,7 @@ func GetServerPeers(macaddress string, network string, server string, dualstack
 }
 }
 
 
 // GetServerExtPeers - gets the extpeers for a client
 // GetServerExtPeers - gets the extpeers for a client
-func GetServerExtPeers(macaddress string, network string, server string, dualstack bool) ([]wgtypes.PeerConfig, error) {
+func GetServerExtPeers(macaddress string, network string, dualstack bool) ([]wgtypes.PeerConfig, error) {
 	var peers []wgtypes.PeerConfig
 	var peers []wgtypes.PeerConfig
 	var nodecfg models.Node
 	var nodecfg models.Node
 	var extPeers []models.Node
 	var extPeers []models.Node

+ 22 - 1
logic/util.go

@@ -13,6 +13,7 @@ import (
 	"github.com/gravitl/netmaker/dnslogic"
 	"github.com/gravitl/netmaker/dnslogic"
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/relay"
 	"github.com/gravitl/netmaker/relay"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
 	"golang.org/x/crypto/bcrypt"
 	"golang.org/x/crypto/bcrypt"
@@ -296,6 +297,26 @@ func setPeerInfo(node models.Node) models.Node {
 func Log(message string, loglevel int) {
 func Log(message string, loglevel int) {
 	log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
 	log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
 	if int32(loglevel) <= servercfg.GetVerbose() && servercfg.GetVerbose() != 0 {
 	if int32(loglevel) <= servercfg.GetVerbose() && servercfg.GetVerbose() != 0 {
-		log.Println(message)
+		log.Println("[netmaker] " + message)
 	}
 	}
 }
 }
+
+// == Private Methods ==
+
+func setIPForwardingLinux() error {
+	out, err := ncutils.RunCmd("sysctl net.ipv4.ip_forward", true)
+	if err != nil {
+		log.Println("WARNING: Error encountered setting ip forwarding. This can break functionality.")
+		return err
+	} else {
+		s := strings.Fields(string(out))
+		if s[2] != "1" {
+			_, err = ncutils.RunCmd("sysctl -w net.ipv4.ip_forward=1", true)
+			if err != nil {
+				log.Println("WARNING: Error encountered setting ip forwarding. You may want to investigate this.")
+				return err
+			}
+		}
+	}
+	return nil
+}

+ 97 - 8
logic/wireguard.go

@@ -12,7 +12,6 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
-	"github.com/gravitl/netmaker/netclient/local"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"golang.zx2c4.com/wireguard/wgctrl"
 	"golang.zx2c4.com/wireguard/wgctrl"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
@@ -38,6 +37,27 @@ func GetSystemPeers(node *models.Node) (map[string]string, error) {
 	return peers, nil
 	return peers, nil
 }
 }
 
 
+func setWGConfig(node models.Node, network string, peerupdate bool) error {
+
+	node.SetID()
+	peers, hasGateway, gateways, err := GetServerPeers(node.MacAddress, node.Network, node.IsDualStack == "yes", node.IsIngressGateway == "yes")
+	if err != nil {
+		return err
+	}
+	privkey, err := FetchPrivKey(node.ID)
+	if err != nil {
+		return err
+	}
+	if peerupdate {
+		var iface string
+		iface = node.Interface
+		err = setServerPeers(iface, node.PersistentKeepalive, peers)
+	} else {
+		err = initWireguard(&node, privkey, peers, hasGateway, gateways)
+	}
+	return err
+}
+
 func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error {
 func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error {
 
 
 	key, err := wgtypes.ParseKey(privkey)
 	key, err := wgtypes.ParseKey(privkey)
@@ -90,12 +110,7 @@ func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 		}
 		}
 		// spin up userspace + apply the conf file
 		// spin up userspace + apply the conf file
 		var deviceiface string
 		var deviceiface string
-		if ncutils.IsMac() {
-			deviceiface, err = local.GetMacIface(node.Address)
-			if err != nil || deviceiface == "" {
-				deviceiface = ifacename
-			}
-		}
+		deviceiface = ifacename
 		d, _ := wgclient.Device(deviceiface)
 		d, _ := wgclient.Device(deviceiface)
 		for d != nil && d.Name == deviceiface {
 		for d != nil && d.Name == deviceiface {
 			_ = RemoveConf(ifacename, false) // remove interface first
 			_ = RemoveConf(ifacename, false) // remove interface first
@@ -104,7 +119,7 @@ func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 		}
 		}
 		err = applyWGQuickConf(confPath)
 		err = applyWGQuickConf(confPath)
 		if err != nil {
 		if err != nil {
-			ncutils.PrintLog("failed to create wireguard interface", 1)
+			Log("failed to create wireguard interface", 1)
 			return err
 			return err
 		}
 		}
 	} else {
 	} else {
@@ -202,3 +217,77 @@ func removeWGQuickConf(confPath string, printlog bool) error {
 	}
 	}
 	return nil
 	return nil
 }
 }
+
+func setServerPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error {
+
+	client, err := wgctrl.New()
+	if err != nil {
+		ncutils.PrintLog("failed to start wgctrl", 0)
+		return err
+	}
+
+	device, err := client.Device(iface)
+	if err != nil {
+		ncutils.PrintLog("failed to parse interface", 0)
+		return err
+	}
+	devicePeers := device.Peers
+	if len(devicePeers) > 1 && len(peers) == 0 {
+		ncutils.PrintLog("no peers pulled", 1)
+		return err
+	}
+
+	for _, peer := range peers {
+
+		for _, currentPeer := range devicePeers {
+			if currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() &&
+				currentPeer.PublicKey.String() != peer.PublicKey.String() {
+				_, err := ncutils.RunCmd("wg set "+iface+" peer "+currentPeer.PublicKey.String()+" remove", true)
+				if err != nil {
+					log.Println("error removing peer", peer.Endpoint.String())
+				}
+			}
+		}
+		udpendpoint := peer.Endpoint.String()
+		var allowedips string
+		var iparr []string
+		for _, ipaddr := range peer.AllowedIPs {
+			iparr = append(iparr, ipaddr.String())
+		}
+		allowedips = strings.Join(iparr, ",")
+		keepAliveString := strconv.Itoa(int(keepalive))
+		if keepAliveString == "0" {
+			keepAliveString = "5"
+		}
+		if peer.Endpoint != nil {
+			_, err = ncutils.RunCmd("wg set "+iface+" peer "+peer.PublicKey.String()+
+				" endpoint "+udpendpoint+
+				" persistent-keepalive "+keepAliveString+
+				" allowed-ips "+allowedips, true)
+		} else {
+			_, err = ncutils.RunCmd("wg set "+iface+" peer "+peer.PublicKey.String()+
+				" persistent-keepalive "+keepAliveString+
+				" allowed-ips "+allowedips, true)
+		}
+		if err != nil {
+			log.Println("error setting peer", peer.PublicKey.String())
+		}
+	}
+
+	for _, currentPeer := range devicePeers {
+		shouldDelete := true
+		for _, peer := range peers {
+			if peer.AllowedIPs[0].String() == currentPeer.AllowedIPs[0].String() {
+				shouldDelete = false
+			}
+		}
+		if shouldDelete {
+			output, err := ncutils.RunCmd("wg set "+iface+" peer "+currentPeer.PublicKey.String()+" remove", true)
+			if err != nil {
+				log.Println(output, "error removing peer", currentPeer.PublicKey.String())
+			}
+		}
+	}
+
+	return nil
+}

+ 0 - 6
netclient/functions/checkin.go

@@ -9,7 +9,6 @@ import (
 	"strings"
 	"strings"
 
 
 	nodepb "github.com/gravitl/netmaker/grpc"
 	nodepb "github.com/gravitl/netmaker/grpc"
-	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/auth"
 	"github.com/gravitl/netmaker/netclient/auth"
 	"github.com/gravitl/netmaker/netclient/config"
 	"github.com/gravitl/netmaker/netclient/config"
@@ -197,11 +196,6 @@ func Pull(network string, manual bool) (*models.Node, error) {
 		if err = json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
 		if err = json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
-	} else { // handle server side read
-		resNode, err = logic.GetNode(node.MacAddress, node.Network)
-		if err != nil && !ncutils.IsEmptyRecord(err) {
-			return nil, err
-		}
 	}
 	}
 	// ensure that the OS never changes
 	// ensure that the OS never changes
 	resNode.OS = runtime.GOOS
 	resNode.OS = runtime.GOOS

+ 8 - 31
serverctl/serverctl.go

@@ -8,6 +8,7 @@ import (
 	"os"
 	"os"
 
 
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
+	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	nccommand "github.com/gravitl/netmaker/netclient/command"
 	nccommand "github.com/gravitl/netmaker/netclient/command"
 	"github.com/gravitl/netmaker/netclient/config"
 	"github.com/gravitl/netmaker/netclient/config"
@@ -31,30 +32,6 @@ func GetServerWGConf() (models.IntClient, error) {
 	return models.IntClient{}, errors.New("could not find comms server")
 	return models.IntClient{}, errors.New("could not find comms server")
 }
 }
 
 
-// InstallNetclient netclient installation for server - depricated
-func InstallNetclient() error {
-
-	netclientPath := ncutils.GetNetclientPath()
-	if ncutils.IsWindows() {
-		netclientPath += "\\"
-	} else {
-		netclientPath += "/"
-	}
-	if !FileExists(netclientPath + "netclient") {
-		var err error
-		if ncutils.IsWindows() {
-			_, err = copy(".\\netclient\\netclient", netclientPath+"netclient")
-		} else {
-			_, err = copy("./netclient/netclient", netclientPath+"netclient")
-		}
-		if err != nil {
-			log.Println("could not create " + netclientPath + "netclient")
-			return err
-		}
-	}
-	return nil
-}
-
 // FileExists - checks if local file exists
 // FileExists - checks if local file exists
 func FileExists(f string) bool {
 func FileExists(f string) bool {
 	info, err := os.Stat(f)
 	info, err := os.Stat(f)
@@ -95,7 +72,7 @@ func copy(src, dst string) (int64, error) {
 
 
 // RemoveNetwork - removes a network locally on server
 // RemoveNetwork - removes a network locally on server
 func RemoveNetwork(network string) (bool, error) {
 func RemoveNetwork(network string) (bool, error) {
-	err := nccommand.Leave(config.ClientConfig{Network: network})
+	err := logic.ServerLeave(servercfg.GetNodeID(), network)
 	return true, err
 	return true, err
 }
 }
 
 
@@ -188,15 +165,15 @@ func SyncNetworks(servernets []models.Network) error {
 
 
 // AddNetwork - add a network to server in client mode
 // AddNetwork - add a network to server in client mode
 func AddNetwork(network string) (bool, error) {
 func AddNetwork(network string) (bool, error) {
-	err := nccommand.Join(config.ClientConfig{
+	err := logic.ServerJoin(config.ClientConfig{
 		Network: network,
 		Network: network,
 		Daemon:  "off",
 		Daemon:  "off",
 		Node: models.Node{
 		Node: models.Node{
-			Network:  network,
-			IsServer: "yes",
-			DNSOn:    "no",
-			Name:     models.NODE_SERVER_NAME,
-			MacAddress:     servercfg.GetNodeID(),
+			Network:    network,
+			IsServer:   "yes",
+			DNSOn:      "no",
+			Name:       models.NODE_SERVER_NAME,
+			MacAddress: servercfg.GetNodeID(),
 		},
 		},
 	}, "")
 	}, "")
 	log.Println("[netmaker] Server added to network " + network)
 	log.Println("[netmaker] Server added to network " + network)