netmaker/logic/server.go

311 lines
8 KiB
Go
Raw Normal View History

2021-10-13 03:44:19 +08:00
package logic
import (
"errors"
2021-10-27 21:27:52 +08:00
"fmt"
2021-10-13 03:44:19 +08:00
"net"
2021-10-13 22:02:04 +08:00
"os"
2021-10-13 03:44:19 +08:00
"runtime"
"strings"
2021-12-07 04:31:08 +08:00
"github.com/gravitl/netmaker/logger"
2021-10-13 03:44:19 +08:00
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils"
"github.com/gravitl/netmaker/servercfg"
2021-10-13 03:44:19 +08:00
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
// == Join, Checkin, and Leave for Server ==
2021-10-16 02:15:32 +08:00
// KUBERNETES_LISTEN_PORT - starting port for Kubernetes in order to use NodePort range
const KUBERNETES_LISTEN_PORT = 31821
2021-12-11 04:01:10 +08:00
// KUBERNETES_SERVER_MTU - ideal mtu for kubernetes deployments right now
2021-10-18 03:31:37 +08:00
const KUBERNETES_SERVER_MTU = 1024
2021-10-16 02:15:32 +08:00
2021-10-14 03:15:20 +08:00
// ServerJoin - responsible for joining a server to a network
2022-02-01 23:08:44 +08:00
func ServerJoin(networkSettings *models.Network) (models.Node, error) {
var returnNode models.Node
2022-01-13 08:39:10 +08:00
if networkSettings == nil || networkSettings.NetID == "" {
2022-02-01 23:08:44 +08:00
return returnNode, errors.New("no network provided")
2021-10-13 03:44:19 +08:00
}
2022-01-14 22:21:41 +08:00
2021-10-14 03:15:20 +08:00
var err error
2022-02-09 11:16:57 +08:00
var currentServers = GetServerNodes(networkSettings.NetID)
var serverCount = 1
if currentServers != nil {
serverCount = len(currentServers) + 1
}
2022-02-19 00:11:21 +08:00
var ishub = "no"
2022-02-21 21:27:31 +08:00
if networkSettings.IsPointToSite == "yes" {
2022-02-21 21:27:31 +08:00
nodes, err := GetNetworkNodes(networkSettings.NetID)
if err != nil || nodes == nil {
ishub = "yes"
} else {
sethub := true
for i := range nodes {
if nodes[i].IsHub == "yes" {
sethub = false
}
}
if sethub {
ishub = "yes"
}
}
2022-02-19 00:11:21 +08:00
}
var node = &models.Node{
IsServer: "yes",
DNSOn: "no",
IsStatic: "yes",
2022-02-09 11:16:57 +08:00
Name: fmt.Sprintf("%s-%d", models.NODE_SERVER_NAME, serverCount),
MacAddress: servercfg.GetNodeID(),
ID: "", // will be set to new uuid
UDPHolePunch: "no",
2022-01-13 08:50:00 +08:00
IsLocal: networkSettings.IsLocal,
2022-01-13 09:06:10 +08:00
LocalRange: networkSettings.LocalRange,
OS: runtime.GOOS,
Version: servercfg.Version,
2022-02-19 00:11:21 +08:00
IsHub: ishub,
2021-10-14 03:15:20 +08:00
}
2021-10-27 00:27:29 +08:00
SetNodeDefaults(node)
2021-10-18 03:31:37 +08:00
2021-10-16 02:15:32 +08:00
if servercfg.GetPlatform() == "Kubernetes" {
node.ListenPort = KUBERNETES_LISTEN_PORT
2021-10-18 03:31:37 +08:00
node.MTU = KUBERNETES_SERVER_MTU
2021-10-16 02:15:32 +08:00
}
2021-10-14 03:15:20 +08:00
if node.LocalRange != "" && node.LocalAddress == "" {
2022-01-14 01:43:17 +08:00
logger.Log(1, "local vpn, getting local address from range:", networkSettings.LocalRange)
node.LocalAddress, err = getServerLocalIP(networkSettings)
if err != nil {
2022-01-13 09:11:31 +08:00
node.LocalAddress = ""
2022-01-14 01:43:17 +08:00
node.IsLocal = "no"
2022-01-13 09:11:31 +08:00
}
2021-10-13 03:44:19 +08:00
}
2021-10-14 03:15:20 +08:00
if node.Endpoint == "" {
if node.IsLocal == "yes" && node.LocalAddress != "" {
node.Endpoint = node.LocalAddress
2021-10-13 03:44:19 +08:00
} else {
2022-05-27 22:52:47 +08:00
node.Endpoint, err = servercfg.GetPublicIP()
2021-10-13 03:44:19 +08:00
}
2021-10-14 03:15:20 +08:00
if err != nil || node.Endpoint == "" {
2021-12-07 04:31:08 +08:00
logger.Log(0, "Error setting server node Endpoint.")
2022-02-01 23:08:44 +08:00
return returnNode, err
2021-10-13 03:44:19 +08:00
}
}
2022-01-13 08:39:10 +08:00
var privateKey = ""
2021-10-13 03:44:19 +08:00
// Generate and set public/private WireGuard Keys
if privateKey == "" {
wgPrivatekey, err := wgtypes.GeneratePrivateKey()
if err != nil {
2021-12-07 04:31:08 +08:00
logger.Log(1, err.Error())
2022-02-01 23:08:44 +08:00
return returnNode, err
2021-10-13 03:44:19 +08:00
}
privateKey = wgPrivatekey.String()
2021-10-14 03:15:20 +08:00
node.PublicKey = wgPrivatekey.PublicKey().String()
2021-10-13 03:44:19 +08:00
}
2022-01-13 08:39:10 +08:00
node.Network = networkSettings.NetID
logger.Log(2, "adding a server instance on network", node.Network)
2021-10-13 03:44:19 +08:00
if err != nil {
2022-02-01 23:08:44 +08:00
return returnNode, err
2021-10-13 03:44:19 +08:00
}
err = SetNetworkNodesLastModified(node.Network)
if err != nil {
2022-02-01 23:08:44 +08:00
return returnNode, err
2021-10-13 03:44:19 +08:00
}
// get free port based on returned default listen port
node.ListenPort, err = ncutils.GetFreePort(node.ListenPort)
if err != nil {
2021-12-07 04:31:08 +08:00
logger.Log(2, "Error retrieving port:", err.Error())
2021-10-27 21:27:52 +08:00
} else {
2021-12-07 04:31:08 +08:00
logger.Log(1, "Set client port to", fmt.Sprintf("%d", node.ListenPort), "for network", node.Network)
2021-10-13 03:44:19 +08:00
}
// safety check. If returned node from server is local, but not currently configured as local, set to local addr
2021-10-14 03:15:20 +08:00
if node.IsLocal == "yes" && node.LocalRange != "" {
2021-10-13 03:44:19 +08:00
node.LocalAddress, err = ncutils.GetLocalIP(node.LocalRange)
if err != nil {
2022-02-01 23:08:44 +08:00
return returnNode, err
2021-10-13 03:44:19 +08:00
}
node.Endpoint = node.LocalAddress
}
2022-02-01 09:36:09 +08:00
if err = CreateNode(node); err != nil {
2022-02-01 23:08:44 +08:00
return returnNode, err
2021-10-13 03:44:19 +08:00
}
2022-02-01 09:36:09 +08:00
if err = StorePrivKey(node.ID, privateKey); err != nil {
2022-02-01 23:08:44 +08:00
return returnNode, err
2021-10-13 03:44:19 +08:00
}
2021-12-11 04:01:10 +08:00
peers, hasGateway, gateways, err := GetServerPeers(node)
2021-10-13 03:44:19 +08:00
if err != nil && !ncutils.IsEmptyRecord(err) {
2021-12-07 04:31:08 +08:00
logger.Log(1, "failed to retrieve peers")
2022-02-01 23:08:44 +08:00
return returnNode, err
2021-10-13 03:44:19 +08:00
}
2021-12-11 04:01:10 +08:00
err = initWireguard(node, privateKey, peers[:], hasGateway, gateways[:])
2021-10-13 03:44:19 +08:00
if err != nil {
2022-02-01 23:08:44 +08:00
return returnNode, err
2021-10-13 03:44:19 +08:00
}
2022-02-01 23:08:44 +08:00
return *node, nil
2021-10-13 03:44:19 +08:00
}
2022-01-25 20:31:50 +08:00
// ServerUpdate - updates the server
// replaces legacy Checkin code
2022-01-31 09:31:11 +08:00
func ServerUpdate(serverNode *models.Node, ifaceDelta bool) error {
var err = ServerPull(serverNode, ifaceDelta)
2021-10-14 03:15:20 +08:00
if isDeleteError(err) {
2022-01-25 20:31:50 +08:00
return DeleteNodeByID(serverNode, true)
2022-02-01 12:18:58 +08:00
} else if err != nil && !ifaceDelta {
err = ServerPull(serverNode, true)
2022-02-01 12:18:58 +08:00
if err != nil {
return err
}
2021-10-14 03:15:20 +08:00
}
2021-12-11 04:01:10 +08:00
actionCompleted := checkNodeActions(serverNode)
2021-10-14 03:15:20 +08:00
if actionCompleted == models.NODE_DELETE {
return errors.New("node has been removed")
}
2022-01-25 20:31:50 +08:00
return serverPush(serverNode)
2021-10-13 03:44:19 +08:00
}
/**
* Below function needs major refactor
*
*/
2021-10-13 22:02:04 +08:00
// GetServerPeers - gets peers of server
2021-12-11 04:01:10 +08:00
func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []string, error) {
2022-06-14 22:36:30 +08:00
update, err := GetPeerUpdate(serverNode)
2021-10-13 03:44:19 +08:00
if err != nil {
2022-06-14 22:36:30 +08:00
return []wgtypes.PeerConfig{}, false, []string{}, err
2021-10-13 03:44:19 +08:00
}
// this is temporary code, should be removed by 0.14.4
// refactor server routing to use client-side routing code
var hasGateways = false
var gateways = []string{}
nodes, err := GetNetworkNodes(serverNode.Network)
if err == nil {
for _, node := range nodes {
if node.IsEgressGateway == "yes" {
gateways = append(gateways, node.EgressGatewayRanges...)
}
}
hasGateways = len(gateways) > 0
}
// end temporary code
return update.Peers, hasGateways, gateways, nil
2021-10-13 03:44:19 +08:00
}
2021-10-14 03:15:20 +08:00
// == Private ==
func isDeleteError(err error) bool {
return err != nil && strings.Contains(err.Error(), models.NODE_DELETE)
}
2021-12-11 04:01:10 +08:00
func checkNodeActions(node *models.Node) string {
if node.Action == models.NODE_UPDATE_KEY {
err := setWGKeyConfig(node)
2021-10-14 03:15:20 +08:00
if err != nil {
2021-12-07 04:31:08 +08:00
logger.Log(1, "unable to process reset keys request:", err.Error())
2021-10-14 03:15:20 +08:00
return ""
}
}
2021-12-11 04:01:10 +08:00
if node.Action == models.NODE_DELETE {
2022-01-25 20:31:50 +08:00
err := DeleteNodeByID(node, true)
2021-10-14 03:15:20 +08:00
if err != nil {
2021-12-07 04:31:08 +08:00
logger.Log(1, "error deleting locally:", err.Error())
2021-10-14 03:15:20 +08:00
}
return models.NODE_DELETE
}
return ""
}
2022-01-14 01:43:17 +08:00
2022-01-25 20:31:50 +08:00
// == Private ==
// ServerPull - performs a server pull
func ServerPull(serverNode *models.Node, ifaceDelta bool) error {
if serverNode.IsServer != "yes" {
return fmt.Errorf("attempted pull from non-server node: %s - %s", serverNode.Name, serverNode.ID)
}
2022-01-25 20:31:50 +08:00
var err error
if serverNode.IPForwarding == "yes" {
if err = setIPForwardingLinux(); err != nil {
return err
}
}
serverNode.OS = runtime.GOOS
2022-02-18 23:15:21 +08:00
if ifaceDelta {
2022-01-25 20:31:50 +08:00
// check for interface change
// checks if address is in use by another interface
var oldIfaceName, isIfacePresent = isInterfacePresent(serverNode.Interface, serverNode.Address)
if !isIfacePresent {
if err = deleteInterface(oldIfaceName, serverNode.PostDown); err != nil {
logger.Log(1, "could not delete old interface", oldIfaceName)
}
logger.Log(1, "removed old interface", oldIfaceName)
}
if err = setWGConfig(serverNode, false); err != nil {
return err
}
// handle server side update
if err = UpdateNode(serverNode, serverNode); err != nil {
return err
}
} else {
if err = setWGConfig(serverNode, true); err != nil {
if errors.Is(err, os.ErrNotExist) {
return ServerPull(serverNode, true)
2022-01-25 20:31:50 +08:00
} else {
return err
}
}
}
return nil
}
2022-01-14 01:43:17 +08:00
func getServerLocalIP(networkSettings *models.Network) (string, error) {
var networkCIDR = networkSettings.LocalRange
var currentAddresses, _ = net.InterfaceAddrs()
var _, currentCIDR, cidrErr = net.ParseCIDR(networkCIDR)
if cidrErr != nil {
logger.Log(1, "error on server local IP, invalid CIDR provided:", networkCIDR)
return "", cidrErr
}
for _, addr := range currentAddresses {
ip, _, err := net.ParseCIDR(addr.String())
if err != nil {
continue
}
if currentCIDR.Contains(ip) {
logger.Log(1, "found local ip on network,", networkSettings.NetID, ", set to", ip.String())
return ip.String(), nil
}
}
return "", errors.New("could not find a local ip for server")
}
2022-01-25 20:31:50 +08:00
func serverPush(serverNode *models.Node) error {
serverNode.OS = runtime.GOOS
serverNode.SetLastCheckIn()
return UpdateNode(serverNode, serverNode)
}