Browse Source

Merge pull request #785 from gravitl/bugfix_v0.10.1_openwrt

adding logic for nodes without wg-quick
dcarns 3 years ago
parent
commit
629dd909db

+ 1 - 4
netclient/functions/daemon.go

@@ -295,10 +295,7 @@ func NodeUpdate(client mqtt.Client, msg mqtt.Message) {
 			return
 		}
 		time.Sleep(time.Second >> 1)
-		// if err = Resubscribe(client, &cfg); err != nil {
-		// 	ncutils.Log("error resubscribing after interface change " + err.Error())
-		// 	return
-		// }
+
 		if newNode.DNSOn == "yes" {
 			for _, server := range newNode.NetworkSettings.DefaultServerAddrs {
 				if server.IsLeader {

+ 6 - 0
netclient/ncutils/netclientutils.go

@@ -102,6 +102,12 @@ func IsFreeBSD() bool {
 	return runtime.GOOS == "freebsd"
 }
 
+// HasWGQuick - checks if WGQuick command is present
+func HasWgQuick() bool {
+	cmd, err := exec.LookPath("wg-quick")
+	return err == nil && cmd != ""
+}
+
 // GetWireGuard - checks if wg is installed
 func GetWireGuard() string {
 	userspace := os.Getenv("WG_QUICK_USERSPACE_IMPLEMENTATION")

+ 17 - 1
netclient/wireguard/common.go

@@ -206,7 +206,13 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 	if syncconf { // should never be called really.
 		err = SyncWGQuickConf(ifacename, confPath)
 	}
-
+	if !ncutils.HasWgQuick() && ncutils.IsLinux() {
+		err = SetPeers(ifacename, node.Address, node.PersistentKeepalive, peers)
+		if err != nil {
+			ncutils.PrintLog("error setting peers: "+err.Error(), 1)
+		}
+		time.Sleep(time.Second)
+	}
 	_, cidr, cidrErr := net.ParseCIDR(modcfg.NetworkSettings.AddressRange)
 	if cidrErr == nil {
 		local.SetCIDRRoute(ifacename, node.Address, cidr)
@@ -260,8 +266,13 @@ func SetWGConfig(network string, peerupdate bool) error {
 // RemoveConf - removes a configuration for a given WireGuard interface
 func RemoveConf(iface string, printlog bool) error {
 	os := runtime.GOOS
+	if !ncutils.HasWgQuick() {
+		os = "nowgquick"
+	}
 	var err error
 	switch os {
+	case "nowgquick":
+		err = RemoveWithoutWGQuick(iface)
 	case "windows":
 		err = RemoveWindowsConf(iface, printlog)
 	case "darwin":
@@ -276,8 +287,13 @@ func RemoveConf(iface string, printlog bool) error {
 // ApplyConf - applys a conf on disk to WireGuard interface
 func ApplyConf(node *models.Node, ifacename string, confPath string) error {
 	os := runtime.GOOS
+	if ncutils.IsLinux() && !ncutils.HasWgQuick() {
+		os = "nowgquick"
+	}
 	var err error
 	switch os {
+	case "nowgquick":
+		err = ApplyWithoutWGQuick(node, ifacename, confPath)
 	case "windows":
 		_ = ApplyWindowsConf(confPath)
 	case "darwin":

+ 135 - 0
netclient/wireguard/noquick.go

@@ -0,0 +1,135 @@
+package wireguard
+
+import (
+	"errors"
+	"os"
+	"os/exec"
+	"strconv"
+	"strings"
+
+	"github.com/gravitl/netmaker/logger"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/config"
+	"github.com/gravitl/netmaker/netclient/ncutils"
+	"golang.zx2c4.com/wireguard/wgctrl"
+	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
+)
+
+// ApplyWithoutWGQuick - Function for running the equivalent of "wg-quick up" for linux if wg-quick is missing
+func ApplyWithoutWGQuick(node *models.Node, ifacename string, confPath string) error {
+
+	ipExec, err := exec.LookPath("ip")
+	if err != nil {
+		return err
+	}
+	wgclient, err := wgctrl.New()
+	if err != nil {
+		return err
+	}
+	defer wgclient.Close()
+
+	privkey, err := RetrievePrivKey(node.Network)
+	if err != nil {
+		return err
+	}
+	key, err := wgtypes.ParseKey(privkey)
+	if err != nil {
+		return err
+	}
+	conf := wgtypes.Config{}
+	nodeport := int(node.ListenPort)
+	if node.UDPHolePunch == "yes" &&
+		node.IsServer == "no" &&
+		node.IsIngressGateway != "yes" &&
+		node.IsStatic != "yes" {
+		conf = wgtypes.Config{
+			PrivateKey: &key,
+		}
+	} else {
+		conf = wgtypes.Config{
+			PrivateKey: &key,
+			ListenPort: &nodeport,
+		}
+	}
+
+	netmaskArr := strings.Split(node.NetworkSettings.AddressRange, "/")
+	var netmask = "32"
+	if len(netmaskArr) == 2 {
+		netmask = netmaskArr[1]
+	}
+	setKernelDevice(ifacename, node.Address, netmask)
+
+	_, err = wgclient.Device(ifacename)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			return errors.New("Unknown config error: " + err.Error())
+		}
+	}
+	err = wgclient.ConfigureDevice(ifacename, conf)
+	if err != nil {
+		if os.IsNotExist(err) {
+			ncutils.PrintLog("Could not configure device: "+err.Error(), 0)
+		}
+	}
+	if _, err := ncutils.RunCmd(ipExec+" link set down dev "+ifacename, false); err != nil {
+		logger.Log(2, "attempted to remove interface before editing")
+		return err
+	}
+	if node.PostDown != "" {
+		runcmds := strings.Split(node.PostDown, "; ")
+		_ = ncutils.RunCmds(runcmds, false)
+	}
+	// set MTU of node interface
+	if _, err := ncutils.RunCmd(ipExec+" link set mtu "+strconv.Itoa(int(node.MTU))+" up dev "+ifacename, true); err != nil {
+		logger.Log(2, "failed to create interface with mtu", strconv.Itoa(int(node.MTU)), "-", ifacename)
+		return err
+	}
+	if node.PostUp != "" {
+		runcmds := strings.Split(node.PostUp, "; ")
+		_ = ncutils.RunCmds(runcmds, true)
+	}
+	if node.Address6 != "" && node.IsDualStack == "yes" {
+		logger.Log(1, "adding address:", node.Address6)
+		_, _ = ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+node.Address6+"/64", true)
+	}
+	return nil
+}
+
+// RemoveWithoutWGQuick - Function for running the equivalent of "wg-quick down" for linux if wg-quick is missing
+func RemoveWithoutWGQuick(ifacename string) error {
+	ipExec, err := exec.LookPath("ip")
+	if err != nil {
+		return err
+	}
+	out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false)
+	dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device")
+	if err != nil && !dontprint {
+		logger.Log(1, "error running command:", ipExec, "link del", ifacename)
+		logger.Log(1, out)
+	}
+	network := strings.ReplaceAll(ifacename, "nm-", "")
+	nodeconf, err := config.ReadConfig(network)
+	if nodeconf != nil && err == nil {
+		if nodeconf.Node.PostDown != "" {
+			runcmds := strings.Split(nodeconf.Node.PostDown, "; ")
+			_ = ncutils.RunCmds(runcmds, false)
+		}
+	} else if err != nil {
+		ncutils.PrintLog("error retrieving config: "+err.Error(), 1)
+	}
+	return err
+}
+
+func setKernelDevice(ifacename, address, mask string) error {
+	ipExec, err := exec.LookPath("ip")
+	if err != nil {
+		return err
+	}
+
+	// == best effort ==
+	ncutils.RunCmd("ip link delete dev "+ifacename, false)
+	ncutils.RunCmd(ipExec+" link add dev "+ifacename+" type wireguard", true)
+	ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address+"/"+mask, true) // this was a bug waiting to happen
+
+	return nil
+}

+ 1 - 0
netclient/wireguard/unix.go

@@ -65,6 +65,7 @@ func ApplyWGQuickConf(confPath string, ifacename string) error {
 			ncutils.RunCmd("wg-quick down "+confPath, true)
 		}
 		_, err = ncutils.RunCmd("wg-quick up "+confPath, true)
+
 		return err
 	}
 }