mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-16 13:51:42 +08:00
Merge pull request #1468 from gravitl/feature_v0.14.9_node_disconnect
Feature v0.14.9 node disconnect
This commit is contained in:
@@ -433,6 +433,7 @@ func SetNodeDefaults(node *models.Node) {
|
||||
node.SetDefaultIsDocker()
|
||||
node.SetDefaultIsK8S()
|
||||
node.SetDefaultIsHub()
|
||||
node.SetDefaultConnected()
|
||||
}
|
||||
|
||||
// GetRecordKey - get record key
|
||||
|
@@ -154,7 +154,7 @@ func ServerJoin(networkSettings *models.Network) (models.Node, error) {
|
||||
return returnNode, err
|
||||
}
|
||||
|
||||
err = wireguard.InitWireguard(node, privateKey, peers.Peers, false)
|
||||
err = wireguard.InitWireguard(node, privateKey, peers.Peers)
|
||||
if err != nil {
|
||||
return returnNode, err
|
||||
}
|
||||
|
@@ -58,6 +58,7 @@ func IfaceDelta(currentNode *models.Node, newNode *models.Node) bool {
|
||||
newNode.MTU != currentNode.MTU ||
|
||||
newNode.PersistentKeepalive != currentNode.PersistentKeepalive ||
|
||||
newNode.DNSOn != currentNode.DNSOn ||
|
||||
newNode.Connected != currentNode.Connected ||
|
||||
len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) {
|
||||
return true
|
||||
}
|
||||
@@ -139,7 +140,7 @@ func setWGConfig(node *models.Node, peerupdate bool) error {
|
||||
}
|
||||
logger.Log(2, "updated peers on server", node.Name)
|
||||
} else {
|
||||
err = wireguard.InitWireguard(node, privkey, peers.Peers, false)
|
||||
err = wireguard.InitWireguard(node, privkey, peers.Peers)
|
||||
logger.Log(3, "finished setting wg config on server", node.Name)
|
||||
}
|
||||
return err
|
||||
|
@@ -93,6 +93,7 @@ type Node struct {
|
||||
TrafficKeys TrafficKeys `json:"traffickeys" bson:"traffickeys" yaml:"traffickeys"`
|
||||
FirewallInUse string `json:"firewallinuse" bson:"firewallinuse" yaml:"firewallinuse"`
|
||||
InternetGateway string `json:"internetgateway" bson:"internetgateway" yaml:"internetgateway"`
|
||||
Connected string `json:"connected" bson:"connected" yaml:"connected" validate:"checkyesorno"`
|
||||
}
|
||||
|
||||
// NodesArray - used for node sorting
|
||||
@@ -121,6 +122,16 @@ func (node *Node) PrimaryAddress() string {
|
||||
return node.Address6
|
||||
}
|
||||
|
||||
// Node.SetDefaultConnected
|
||||
func (node *Node) SetDefaultConnected() {
|
||||
if node.Connected == "" {
|
||||
node.Connected = "yes"
|
||||
}
|
||||
if node.IsServer == "yes" {
|
||||
node.Connected = "yes"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetDefaultMTU - sets default MTU of a node
|
||||
func (node *Node) SetDefaultMTU() {
|
||||
if node.MTU == 0 {
|
||||
@@ -382,6 +393,7 @@ func (newNode *Node) Fill(currentNode *Node) { // TODO add new field for nftable
|
||||
}
|
||||
if newNode.IsServer == "yes" {
|
||||
newNode.IsStatic = "yes"
|
||||
newNode.Connected = "yes"
|
||||
}
|
||||
if newNode.MTU == 0 {
|
||||
newNode.MTU = currentNode.MTU
|
||||
@@ -413,6 +425,9 @@ func (newNode *Node) Fill(currentNode *Node) { // TODO add new field for nftable
|
||||
if newNode.Server == "" {
|
||||
newNode.Server = currentNode.Server
|
||||
}
|
||||
if newNode.Connected == "" {
|
||||
newNode.Connected = currentNode.Connected
|
||||
}
|
||||
newNode.TrafficKeys = currentNode.TrafficKeys
|
||||
}
|
||||
|
||||
|
@@ -104,6 +104,32 @@ func GetCommands(cliFlags []cli.Flag) []*cli.Command {
|
||||
return command.Install()
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "connect",
|
||||
Usage: "connect netclient to a given network if disconnected",
|
||||
Flags: cliFlags,
|
||||
Action: func(c *cli.Context) error {
|
||||
parseVerbosity(c)
|
||||
cfg, _, err := config.GetCLIConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return command.Connect(cfg)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "disconnect",
|
||||
Usage: "disconnect netclient from a given network if connected",
|
||||
Flags: cliFlags,
|
||||
Action: func(c *cli.Context) error {
|
||||
parseVerbosity(c)
|
||||
cfg, _, err := config.GetCLIConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return command.Disconnect(cfg)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@ package command
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
@@ -142,3 +143,27 @@ func Daemon() error {
|
||||
func Install() error {
|
||||
return functions.Install()
|
||||
}
|
||||
|
||||
// Connect - re-instates a connection of a node
|
||||
func Connect(cfg config.ClientConfig) error {
|
||||
networkName := cfg.Network
|
||||
if networkName == "" {
|
||||
networkName = cfg.Node.Network
|
||||
}
|
||||
if networkName == "all" {
|
||||
return fmt.Errorf("no network specified")
|
||||
}
|
||||
return functions.Connect(networkName)
|
||||
}
|
||||
|
||||
// Disconnect - disconnects a connection of a node
|
||||
func Disconnect(cfg config.ClientConfig) error {
|
||||
networkName := cfg.Network
|
||||
if networkName == "" {
|
||||
networkName = cfg.Node.Network
|
||||
}
|
||||
if networkName == "all" {
|
||||
return fmt.Errorf("no network specified")
|
||||
}
|
||||
return functions.Disconnect(networkName)
|
||||
}
|
||||
|
@@ -43,6 +43,9 @@ func UpdateClientConfig() {
|
||||
if err := PublishNodeUpdate(&cfg); err != nil {
|
||||
logger.Log(0, "error publishing node update during schema change", err.Error())
|
||||
}
|
||||
if err := config.ModNodeConfig(&cfg.Node); err != nil {
|
||||
logger.Log(0, "error saving local config for node,", cfg.Node.Name, ", on network,", cfg.Node.Network)
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.Log(0, "finished updates")
|
||||
|
54
netclient/functions/connection.go
Normal file
54
netclient/functions/connection.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package functions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
"github.com/gravitl/netmaker/netclient/config"
|
||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||
"github.com/gravitl/netmaker/netclient/wireguard"
|
||||
)
|
||||
|
||||
// Connect - will attempt to connect a node on given network
|
||||
func Connect(network string) error {
|
||||
cfg, err := config.ReadConfig(network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cfg.Node.Connected == "yes" {
|
||||
return fmt.Errorf("node already connected")
|
||||
}
|
||||
cfg.Node.Connected = "yes"
|
||||
filePath := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf"
|
||||
|
||||
if err = wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, filePath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := PublishNodeUpdate(cfg); err != nil {
|
||||
logger.Log(0, "network:", cfg.Node.Network, "could not publish connection change, it will likely get reverted")
|
||||
}
|
||||
|
||||
return config.ModNodeConfig(&cfg.Node)
|
||||
}
|
||||
|
||||
// Disconnect - attempts to disconnect a node on given network
|
||||
func Disconnect(network string) error {
|
||||
cfg, err := config.ReadConfig(network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cfg.Node.Connected == "no" {
|
||||
return fmt.Errorf("node already disconnected")
|
||||
}
|
||||
cfg.Node.Connected = "no"
|
||||
filePath := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf"
|
||||
|
||||
if err = wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, filePath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := PublishNodeUpdate(cfg); err != nil {
|
||||
logger.Log(0, "network:", cfg.Node.Network, "could not publish connection change, it will likely get reverted")
|
||||
}
|
||||
|
||||
return config.ModNodeConfig(&cfg.Node)
|
||||
}
|
@@ -211,7 +211,7 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
|
||||
}
|
||||
|
||||
logger.Log(0, "starting wireguard")
|
||||
err = wireguard.InitWireguard(&node, privateKey, nodeGET.Peers[:], false)
|
||||
err = wireguard.InitWireguard(&node, privateKey, nodeGET.Peers[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ func init() {
|
||||
addUpgrades([]UpgradeInfo{
|
||||
upgrade0145,
|
||||
upgrade0146,
|
||||
upgrade0148,
|
||||
})
|
||||
}
|
||||
|
||||
|
22
netclient/functions/upgrades/v0-14-8.go
Normal file
22
netclient/functions/upgrades/v0-14-8.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package upgrades
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/netclient/config"
|
||||
)
|
||||
|
||||
var upgrade0148 = UpgradeInfo{
|
||||
RequiredVersions: []string{
|
||||
"v0.14.5",
|
||||
"v0.14.6",
|
||||
"v0.14.7",
|
||||
},
|
||||
NewVersion: "v0.14.8",
|
||||
OP: update0148,
|
||||
}
|
||||
|
||||
func update0148(cfg *config.ClientConfig) {
|
||||
// set connect default if not present 14.X -> 14.8
|
||||
if cfg.Node.Connected == "" {
|
||||
cfg.Node.SetDefaultConnected()
|
||||
}
|
||||
}
|
@@ -22,6 +22,7 @@ func IfaceDelta(currentNode *models.Node, newNode *models.Node) bool {
|
||||
newNode.IsPending != currentNode.IsPending ||
|
||||
newNode.PersistentKeepalive != currentNode.PersistentKeepalive ||
|
||||
newNode.DNSOn != currentNode.DNSOn ||
|
||||
newNode.Connected != currentNode.Connected ||
|
||||
len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) {
|
||||
return true
|
||||
}
|
||||
|
@@ -123,7 +123,7 @@ func SetPeers(iface string, node *models.Node, peers []wgtypes.PeerConfig) error
|
||||
}
|
||||
|
||||
// Initializes a WireGuard interface
|
||||
func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, syncconf bool) error {
|
||||
func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig) error {
|
||||
|
||||
key, err := wgtypes.ParseKey(privkey)
|
||||
if err != nil {
|
||||
@@ -191,10 +191,7 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
|
||||
}
|
||||
}
|
||||
logger.Log(1, "interface ready - netclient.. ENGAGE")
|
||||
if syncconf { // should never be called really.
|
||||
fmt.Println("why here")
|
||||
err = SyncWGQuickConf(ifacename, confPath)
|
||||
}
|
||||
|
||||
if !ncutils.HasWgQuick() && ncutils.IsLinux() {
|
||||
err = SetPeers(ifacename, node, peers)
|
||||
if err != nil {
|
||||
@@ -248,12 +245,9 @@ func SetWGConfig(network string, peerupdate bool, peers []wgtypes.PeerConfig) er
|
||||
}
|
||||
}
|
||||
err = SetPeers(iface, &cfg.Node, peers)
|
||||
} else if peerupdate {
|
||||
err = InitWireguard(&cfg.Node, privkey, peers, true)
|
||||
} else {
|
||||
err = InitWireguard(&cfg.Node, privkey, peers, false)
|
||||
err = InitWireguard(&cfg.Node, privkey, peers)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -284,16 +278,17 @@ func ApplyConf(node *models.Node, ifacename string, confPath string) error {
|
||||
if ncutils.IsLinux() && !ncutils.HasWgQuick() {
|
||||
os = "nowgquick"
|
||||
}
|
||||
var isConnected = node.Connected != "no"
|
||||
var err error
|
||||
switch os {
|
||||
case "windows":
|
||||
ApplyWindowsConf(confPath)
|
||||
ApplyWindowsConf(confPath, isConnected)
|
||||
case "darwin":
|
||||
ApplyMacOSConf(node, ifacename, confPath)
|
||||
ApplyMacOSConf(node, ifacename, confPath, isConnected)
|
||||
case "nowgquick":
|
||||
ApplyWithoutWGQuick(node, ifacename, confPath)
|
||||
ApplyWithoutWGQuick(node, ifacename, confPath, isConnected)
|
||||
default:
|
||||
ApplyWGQuickConf(confPath, ifacename)
|
||||
ApplyWGQuickConf(confPath, ifacename, isConnected)
|
||||
}
|
||||
|
||||
var nodeCfg config.ClientConfig
|
||||
|
@@ -2,6 +2,7 @@ package wireguard
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
@@ -15,8 +16,10 @@ import (
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
const disconnect_error = "node disconnected"
|
||||
|
||||
// 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 {
|
||||
func ApplyWithoutWGQuick(node *models.Node, ifacename, confPath string, isConnected bool) error {
|
||||
|
||||
ipExec, err := exec.LookPath("ip")
|
||||
if err != nil {
|
||||
@@ -72,7 +75,12 @@ func ApplyWithoutWGQuick(node *models.Node, ifacename string, confPath string) e
|
||||
mask6 = netmask
|
||||
address6 = node.Address6
|
||||
}
|
||||
setKernelDevice(ifacename, address4, mask4, address6, mask6)
|
||||
err = setKernelDevice(ifacename, address4, mask4, address6, mask6, isConnected)
|
||||
if err != nil {
|
||||
if err.Error() == disconnect_error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
_, err = wgclient.Device(ifacename)
|
||||
if err != nil {
|
||||
@@ -140,7 +148,7 @@ func RemoveWithoutWGQuick(ifacename string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func setKernelDevice(ifacename, address4, mask4, address6, mask6 string) error {
|
||||
func setKernelDevice(ifacename, address4, mask4, address6, mask6 string, isConnected bool) error {
|
||||
ipExec, err := exec.LookPath("ip")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -148,6 +156,10 @@ func setKernelDevice(ifacename, address4, mask4, address6, mask6 string) error {
|
||||
|
||||
// == best effort ==
|
||||
ncutils.RunCmd("ip link delete dev "+ifacename, false)
|
||||
if !isConnected {
|
||||
return fmt.Errorf(disconnect_error)
|
||||
}
|
||||
|
||||
ncutils.RunCmd(ipExec+" link add dev "+ifacename+" type wireguard", true)
|
||||
if address4 != "" {
|
||||
ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address4+"/"+mask4, true)
|
||||
|
@@ -2,9 +2,7 @@ package wireguard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
@@ -12,9 +10,9 @@ import (
|
||||
)
|
||||
|
||||
// ApplyWGQuickConf - applies wg-quick commands if os supports
|
||||
func ApplyWGQuickConf(confPath string, ifacename string) error {
|
||||
func ApplyWGQuickConf(confPath, ifacename string, isConnected bool) error {
|
||||
if ncutils.IsWindows() {
|
||||
return ApplyWindowsConf(confPath)
|
||||
return ApplyWindowsConf(confPath, isConnected)
|
||||
} else {
|
||||
_, err := os.Stat(confPath)
|
||||
if err != nil {
|
||||
@@ -24,6 +22,9 @@ func ApplyWGQuickConf(confPath string, ifacename string) error {
|
||||
if ncutils.IfaceExists(ifacename) {
|
||||
ncutils.RunCmd("wg-quick down "+confPath, true)
|
||||
}
|
||||
if !isConnected {
|
||||
return nil
|
||||
}
|
||||
_, err = ncutils.RunCmd("wg-quick up "+confPath, true)
|
||||
|
||||
return err
|
||||
@@ -31,43 +32,16 @@ func ApplyWGQuickConf(confPath string, ifacename string) error {
|
||||
}
|
||||
|
||||
// ApplyMacOSConf - applies system commands similar to wg-quick using golang for MacOS
|
||||
func ApplyMacOSConf(node *models.Node, ifacename string, confPath string) error {
|
||||
func ApplyMacOSConf(node *models.Node, ifacename, confPath string, isConnected bool) error {
|
||||
var err error
|
||||
_ = WgQuickDownMac(node, ifacename)
|
||||
if !isConnected {
|
||||
return nil
|
||||
}
|
||||
err = WgQuickUpMac(node, ifacename, confPath)
|
||||
return err
|
||||
}
|
||||
|
||||
// SyncWGQuickConf - formats config file and runs sync command
|
||||
func SyncWGQuickConf(iface string, confPath string) error {
|
||||
var tmpConf = confPath + ".sync.tmp"
|
||||
var confCmd = "wg-quick strip "
|
||||
if ncutils.IsMac() {
|
||||
confCmd = "grep -v -e Address -e MTU -e PostUp -e PostDown "
|
||||
}
|
||||
confRaw, err := ncutils.RunCmd(confCmd+confPath, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
regex := regexp.MustCompile(".*Warning.*\n")
|
||||
conf := regex.ReplaceAllString(confRaw, "")
|
||||
err = os.WriteFile(tmpConf, []byte(conf), 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = ncutils.RunCmd("wg syncconf "+iface+" "+tmpConf, true)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
logger.Log(0, "error syncing conf, resetting")
|
||||
err = ApplyWGQuickConf(confPath, iface)
|
||||
}
|
||||
errN := os.Remove(tmpConf)
|
||||
if errN != nil {
|
||||
logger.Log(0, errN.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveWGQuickConf - calls wg-quick down
|
||||
func RemoveWGQuickConf(confPath string, printlog bool) error {
|
||||
_, err := ncutils.RunCmd(fmt.Sprintf("wg-quick down %s", confPath), printlog)
|
||||
|
@@ -8,7 +8,10 @@ import (
|
||||
)
|
||||
|
||||
// ApplyWindowsConf - applies the WireGuard configuration file on Windows
|
||||
func ApplyWindowsConf(confPath string) error {
|
||||
func ApplyWindowsConf(confPath string, isConnected bool) error {
|
||||
if !isConnected {
|
||||
return nil
|
||||
}
|
||||
var commandLine = fmt.Sprintf(`wireguard.exe /installtunnelservice "%s"`, confPath)
|
||||
if _, err := ncutils.RunCmdFormatted(commandLine, false); err != nil {
|
||||
return err
|
||||
|
Reference in New Issue
Block a user