transplanted setwgconfig and pull

This commit is contained in:
0xdcarns 2021-10-13 10:02:04 -04:00
parent 3f2e4ab764
commit 340f50c535
6 changed files with 249 additions and 55 deletions

View file

@ -2,8 +2,11 @@ package logic
import (
"net"
"os/exec"
"strings"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils"
)
// GetLocalIP - gets the local ip
@ -61,3 +64,50 @@ func GetLocalIP(node models.Node) string {
}
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
}

View file

@ -4,6 +4,7 @@ import (
"errors"
"log"
"net"
"os"
"runtime"
"strconv"
"strings"
@ -35,7 +36,7 @@ func ServerJoin(cfg config.ClientConfig, privateKey string) error {
cfg.Node.Endpoint, err = ncutils.GetPublicIP()
}
if err != nil || cfg.Node.Endpoint == "" {
ncutils.Log("Error setting cfg.Node.Endpoint.")
Log("Error setting cfg.Node.Endpoint.", 0)
return err
}
}
@ -117,9 +118,9 @@ func ServerJoin(cfg config.ClientConfig, privateKey string) error {
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) {
ncutils.Log("failed to retrieve peers")
Log("failed to retrieve peers", 1)
return err
}
@ -131,22 +132,84 @@ func ServerJoin(cfg config.ClientConfig, privateKey string) error {
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
func ServerPush(mac string, network string) error {
var serverNode models.Node
var err error
serverNode, err = GetNode(mac, network)
if err != nil && !ncutils.IsEmptyRecord(err) {
if err != nil /* && !ncutils.IsEmptyRecord(err) May not be necessary */ {
return err
}
serverNode.OS = runtime.GOOS
serverNode.SetLastCheckIn()
err = serverNode.Update(&serverNode)
return err
return serverNode.Update(&serverNode)
}
func GetServerPeers(macaddress string, network string, server string, dualstack bool, isIngressGateway bool, isServer bool) ([]wgtypes.PeerConfig, bool, []string, error) {
// 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)
}
// GetServerPeers - gets peers of server
func GetServerPeers(macaddress string, network string, dualstack bool, isIngressGateway bool) ([]wgtypes.PeerConfig, bool, []string, error) {
hasGateway := false
var err error
var gateways []string
@ -277,7 +340,7 @@ func GetServerPeers(macaddress string, network string, server string, dualstack
peers = append(peers, peer)
}
if isIngressGateway {
extPeers, err := GetServerExtPeers(macaddress, network, server, dualstack)
extPeers, err := GetServerExtPeers(macaddress, network, dualstack)
if err == nil {
peers = append(peers, extPeers...)
} else {
@ -288,7 +351,7 @@ func GetServerPeers(macaddress string, network string, server string, dualstack
}
// 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 nodecfg models.Node
var extPeers []models.Node

View file

@ -13,6 +13,7 @@ import (
"github.com/gravitl/netmaker/dnslogic"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils"
"github.com/gravitl/netmaker/relay"
"github.com/gravitl/netmaker/servercfg"
"golang.org/x/crypto/bcrypt"
@ -296,6 +297,26 @@ func setPeerInfo(node models.Node) models.Node {
func Log(message string, loglevel int) {
log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
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
}

View file

@ -12,7 +12,6 @@ import (
"time"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/netclient/ncutils"
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
@ -38,6 +37,27 @@ func GetSystemPeers(node *models.Node) (map[string]string, error) {
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 {
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
var deviceiface string
if ncutils.IsMac() {
deviceiface, err = local.GetMacIface(node.Address)
if err != nil || deviceiface == "" {
deviceiface = ifacename
}
}
deviceiface = ifacename
d, _ := wgclient.Device(deviceiface)
for d != nil && d.Name == deviceiface {
_ = RemoveConf(ifacename, false) // remove interface first
@ -104,7 +119,7 @@ func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
}
err = applyWGQuickConf(confPath)
if err != nil {
ncutils.PrintLog("failed to create wireguard interface", 1)
Log("failed to create wireguard interface", 1)
return err
}
} else {
@ -202,3 +217,77 @@ func removeWGQuickConf(confPath string, printlog bool) error {
}
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
}

View file

@ -9,7 +9,6 @@ import (
"strings"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
"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 {
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
resNode.OS = runtime.GOOS

View file

@ -8,6 +8,7 @@ import (
"os"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
nccommand "github.com/gravitl/netmaker/netclient/command"
"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")
}
// 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
func FileExists(f string) bool {
info, err := os.Stat(f)
@ -95,7 +72,7 @@ func copy(src, dst string) (int64, error) {
// RemoveNetwork - removes a network locally on server
func RemoveNetwork(network string) (bool, error) {
err := nccommand.Leave(config.ClientConfig{Network: network})
err := logic.ServerLeave(servercfg.GetNodeID(), network)
return true, err
}
@ -188,15 +165,15 @@ func SyncNetworks(servernets []models.Network) error {
// AddNetwork - add a network to server in client mode
func AddNetwork(network string) (bool, error) {
err := nccommand.Join(config.ClientConfig{
err := logic.ServerJoin(config.ClientConfig{
Network: network,
Daemon: "off",
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)