adding logic for nodes without wg-quick

This commit is contained in:
afeiszli 2022-02-16 20:19:51 -05:00
parent 5b6553153b
commit a33ff31a59
5 changed files with 159 additions and 1 deletions

View file

@ -299,6 +299,7 @@ func NodeUpdate(client mqtt.Client, msg mqtt.Message) {
// ncutils.Log("error resubscribing after interface change " + err.Error())
// return
// }
// set MTU of node interface
if newNode.DNSOn == "yes" {
for _, server := range newNode.NetworkSettings.DefaultServerAddrs {
if server.IsLeader {

View file

@ -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")

View file

@ -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":

View file

@ -0,0 +1,134 @@
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
}
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
}

View file

@ -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
}
}