diff --git a/controllers/node.go b/controllers/node.go index 5e673920..52197fcb 100644 --- a/controllers/node.go +++ b/controllers/node.go @@ -563,10 +563,10 @@ func updateNode(w http.ResponseWriter, r *http.Request) { } if servercfg.IsDNSMode() { - err = logic.SetDNS() + logic.SetDNS() } - logger.Log(1, r.Header.Get("user"), "updated node", node.MacAddress, "on network", node.Network) + logger.Log(1, r.Header.Get("user"), "updated node", node.ID, "on network", node.Network) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(newNode) diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index e30f0142..f14439e0 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -182,14 +182,15 @@ func getServerAddrs(node *models.Node) { } } - var serverAddrs = make([]models.ServerAddr, 1) + var serverAddrs = make([]models.ServerAddr, 0) for _, node := range serverNodes { - - serverAddrs = append(serverAddrs, models.ServerAddr{ - IsLeader: logic.IsLeader(&node), - Address: node.Address, - }) + if node.Address != "" { + serverAddrs = append(serverAddrs, models.ServerAddr{ + IsLeader: logic.IsLeader(&node), + Address: node.Address, + }) + } } networkSettings, _ := logic.GetParentNetwork(node.Network) diff --git a/controllers/node_test.go b/controllers/node_test.go index f3475767..c4451541 100644 --- a/controllers/node_test.go +++ b/controllers/node_test.go @@ -32,10 +32,12 @@ func TestCreateEgressGateway(t *testing.T) { assert.EqualError(t, err, "freebsd is unsupported for egress gateways") }) t.Run("Success", func(t *testing.T) { + deleteAllNodes() testnode := createTestNode() gateway.NodeID = testnode.ID node, err := logic.CreateEgressGateway(gateway) + t.Log(node) assert.Nil(t, err) assert.Equal(t, "yes", node.IsEgressGateway) assert.Equal(t, gateway.Ranges, node.EgressGatewayRanges) @@ -47,7 +49,6 @@ func TestDeleteEgressGateway(t *testing.T) { database.InitializeDatabase() deleteAllNetworks() createNet() - createTestNode() testnode := createTestNode() gateway.Interface = "eth0" gateway.Ranges = []string{"10.100.100.0/24"} diff --git a/logic/networks.go b/logic/networks.go index 2936299e..8bf5c2ea 100644 --- a/logic/networks.go +++ b/logic/networks.go @@ -752,7 +752,7 @@ func isInterfacePresent(iface string, address string) (string, bool) { } for _, addr := range currAddrs { if strings.Contains(addr.String(), address) && currIface.Name != iface { - logger.Log(2, "found iface", addr.String(), currIface.Name) + // logger.Log(2, "found iface", addr.String(), currIface.Name) interfaces = nil currAddrs = nil return currIface.Name, false @@ -761,6 +761,6 @@ func isInterfacePresent(iface string, address string) (string, bool) { currAddrs = nil } interfaces = nil - logger.Log(2, "failed to find iface", iface) + // logger.Log(2, "failed to find iface", iface) return "", true } diff --git a/logic/nodes.go b/logic/nodes.go index 6940ac19..c4166425 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -159,7 +159,7 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error { return database.Insert(newNode.ID, string(data), database.NODES_TABLE_NAME) } } - return fmt.Errorf("failed to update node " + newNode.MacAddress + ", cannot change macaddress.") + return fmt.Errorf("failed to update node " + currentNode.ID + ", cannot change ID.") } // IsNodeIDUnique - checks if node id is unique @@ -175,8 +175,10 @@ func ValidateNode(node *models.Node, isUpdate bool) error { if isUpdate { return true } - unique, _ := isMacAddressUnique(node.MacAddress, node.Network) - + var unique = true + if !(node.MacAddress == "") { + unique, _ = isMacAddressUnique(node.MacAddress, node.Network) + } isFieldUnique, _ := IsNodeIDUnique(node) return isFieldUnique && unique }) @@ -602,7 +604,10 @@ func isMacAddressUnique(macaddress string, networkName string) (bool, error) { nodes, err := GetNetworkNodes(networkName) if err != nil { - return database.IsEmptyRecord(err), err + if database.IsEmptyRecord(err) { + return true, nil + } + return false, err } for _, node := range nodes { diff --git a/main b/main new file mode 100755 index 00000000..2b3a79bb Binary files /dev/null and b/main differ diff --git a/netclient/auth/auth.go b/netclient/auth/auth.go index 35793831..26498bf9 100644 --- a/netclient/auth/auth.go +++ b/netclient/auth/auth.go @@ -27,7 +27,7 @@ func SetJWT(client nodepb.NodeServiceClient, network string) (context.Context, e if err != nil { return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong with Auto Login: %v", err)) } - tokentext, err = os.ReadFile(home + "nettoken-" + network) + tokentext, err = ncutils.GetFileWithRetry(home+"nettoken-"+network, 1) if err != nil { return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong: %v", err)) } @@ -88,7 +88,7 @@ func StoreSecret(key string, network string) error { // RetrieveSecret - fetches secret locally func RetrieveSecret(network string) (string, error) { - dat, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "secret-" + network) + dat, err := ncutils.GetFileWithRetry(ncutils.GetNetclientPathSpecific()+"secret-"+network, 3) return string(dat), err } @@ -103,7 +103,7 @@ func StoreTrafficKey(key *[32]byte, network string) error { // RetrieveTrafficKey - reads traffic file locally func RetrieveTrafficKey(network string) (*[32]byte, error) { - data, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "traffic-" + network) + data, err := ncutils.GetFileWithRetry(ncutils.GetNetclientPathSpecific()+"traffic-"+network, 2) if err != nil { return nil, err } diff --git a/netclient/config/config.go b/netclient/config/config.go index 4c409660..1943c0f6 100644 --- a/netclient/config/config.go +++ b/netclient/config/config.go @@ -68,7 +68,7 @@ func Write(config *ClientConfig, network string) error { if err != nil { return err } - return err + return f.Sync() } // ClientConfig.ReadConfig - used to read config from client disk into memory @@ -109,7 +109,6 @@ func ModConfig(node *models.Node) error { return errors.New("no network provided") } var modconfig ClientConfig - var err error if FileExists(ncutils.GetNetclientPathSpecific() + "netconfig-" + network) { useconfig, err := ReadConfig(network) if err != nil { @@ -120,8 +119,7 @@ func ModConfig(node *models.Node) error { modconfig.Node = (*node) modconfig.NetworkSettings = node.NetworkSettings - err = Write(&modconfig, network) - return err + return Write(&modconfig, network) } // ModConfig - overwrites the node inside client config on disk diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 93702b76..2a59c0dc 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -299,10 +299,9 @@ func NodeUpdate(client mqtt.Client, msg mqtt.Message) { return } if newNode.DNSOn == "yes" { - ncutils.Log("setting up DNS") - for _, server := range cfg.Node.NetworkSettings.DefaultServerAddrs { + for _, server := range newNode.NetworkSettings.DefaultServerAddrs { if server.IsLeader { - go setDNS(cfg.Node.Interface, cfg.Network, server.Address) + go local.SetDNSWithRetry(newNode.Interface, newNode.Network, server.Address) break } } @@ -581,19 +580,6 @@ func decryptMsg(cfg *config.ClientConfig, msg []byte) ([]byte, error) { return ncutils.BoxDecrypt(msg, serverPubKey, diskKey) } -func setDNS(iface, network, address string) { - var reachable bool - for counter := 0; !reachable && counter < 5; counter++ { - reachable = local.IsDNSReachable(address) - time.Sleep(time.Second << 1) - } - if !reachable { - ncutils.Log("not setting dns, server unreachable: " + address) - } else if err := local.UpdateDNS(iface, network, address); err != nil { - ncutils.Log("error applying dns" + err.Error()) - } -} - func pingServer(cfg *config.ClientConfig) error { node := getServerAddress(cfg) pinger, err := ping.NewPinger(node) diff --git a/netclient/functions/join.go b/netclient/functions/join.go index 0cf07728..2224f3f3 100644 --- a/netclient/functions/join.go +++ b/netclient/functions/join.go @@ -68,13 +68,12 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error { cfg.Node.TrafficKeys.Server = nil // == end handle keys == - if cfg.Node.LocalRange != "" && cfg.Node.LocalAddress == "" { - log.Println("local vpn, getting local address from range: " + cfg.Node.LocalRange) - cfg.Node.LocalAddress = getLocalIP(cfg.Node) - } else if cfg.Node.LocalAddress == "" { + if cfg.Node.LocalAddress == "" { intIP, err := getPrivateAddr() if err == nil { cfg.Node.LocalAddress = intIP + } else { + ncutils.PrintLog("error retrieving private address: "+err.Error(), 1) } } @@ -237,6 +236,14 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error { if err != nil { return err } + if node.DNSOn == "yes" { + for _, server := range node.NetworkSettings.DefaultServerAddrs { + if server.IsLeader { + go local.SetDNSWithRetry(node.Interface, node.Network, server.Address) + break + } + } + } if cfg.Daemon != "off" { err = daemon.InstallDaemon(cfg) } diff --git a/netclient/local/dns.go b/netclient/local/dns.go index 4dc10359..2b33fbfe 100644 --- a/netclient/local/dns.go +++ b/netclient/local/dns.go @@ -16,6 +16,19 @@ import ( const DNS_UNREACHABLE_ERROR = "nameserver unreachable" +func SetDNSWithRetry(iface, network, address string) { + var reachable bool + for counter := 0; !reachable && counter < 5; counter++ { + reachable = IsDNSReachable(address) + time.Sleep(time.Second << 1) + } + if !reachable { + ncutils.Log("not setting dns, server unreachable: " + address) + } else if err := UpdateDNS(iface, network, address); err != nil { + ncutils.Log("error applying dns" + err.Error()) + } +} + // SetDNS - sets the DNS of a local machine func SetDNS(nameserver string) error { bytes, err := os.ReadFile("/etc/resolv.conf") diff --git a/netclient/local/routes_linux.go b/netclient/local/routes_linux.go index 7989d85b..a71b62d8 100644 --- a/netclient/local/routes_linux.go +++ b/netclient/local/routes_linux.go @@ -5,19 +5,25 @@ import ( "fmt" "net" + "strings" "github.com/gravitl/netmaker/netclient/ncutils" ) func setRoute(iface string, addr *net.IPNet, address string) error { - var err error - _, err = ncutils.RunCmd(fmt.Sprintf("ip route add %s dev %s", addr.String(), iface), false) + out, err := ncutils.RunCmd(fmt.Sprintf("ip route get %s", addr.IP.String()), false) + if err != nil || !strings.Contains(out, iface) { + _, err = ncutils.RunCmd(fmt.Sprintf("ip route add %s dev %s", addr.String(), iface), false) + } return err } func deleteRoute(iface string, addr *net.IPNet, address string) error { var err error - _, err = ncutils.RunCmd(fmt.Sprintf("ip route del %s dev %s", addr.String(), iface), false) + out, _ := ncutils.RunCmd(fmt.Sprintf("ip route get %s", addr.IP.String()), false) + if strings.Contains(out, iface) { + _, err = ncutils.RunCmd(fmt.Sprintf("ip route del %s dev %s", addr.String(), iface), false) + } return err } diff --git a/netclient/local/routes_windows.go b/netclient/local/routes_windows.go index 1a7255eb..3b3754b5 100644 --- a/netclient/local/routes_windows.go +++ b/netclient/local/routes_windows.go @@ -27,6 +27,6 @@ func setCidr(iface, address string, addr *net.IPNet) { ncutils.RunCmd("route change "+addr.IP.String()+" mask "+addr.Mask.String()+" "+address, false) } -func removeCidr(iface, address string, addr *net.IPNet) { +func removeCidr(iface string, addr *net.IPNet, address string) { ncutils.RunCmd("route delete "+addr.IP.String()+" mask "+addr.Mask.String()+" "+address, false) } diff --git a/netclient/main b/netclient/main new file mode 100755 index 00000000..1a739dd8 Binary files /dev/null and b/netclient/main differ diff --git a/netclient/ncutils/netclientutils.go b/netclient/ncutils/netclientutils.go index 25d3d07d..cd44e221 100644 --- a/netclient/ncutils/netclientutils.go +++ b/netclient/ncutils/netclientutils.go @@ -320,6 +320,22 @@ func GetNetclientPath() string { } } +// GetFileWithRetry - retry getting file X number of times before failing +func GetFileWithRetry(path string, retryCount int) ([]byte, error) { + var data []byte + var err error + for count := 0; count < retryCount; count++ { + data, err = os.ReadFile(path) + if err == nil { + return data, err + } else { + PrintLog("failed to retrieve file "+path+", retrying...", 1) + time.Sleep(time.Second >> 2) + } + } + return data, err +} + // GetNetclientPathSpecific - gets specific netclient config path func GetNetclientPathSpecific() string { if IsWindows() { @@ -411,6 +427,7 @@ func Copy(src, dst string) error { return err } err = os.Chmod(dst, 0755) + return err } diff --git a/netclient/wireguard/unix.go b/netclient/wireguard/unix.go index 7b4a5e95..8c120a59 100644 --- a/netclient/wireguard/unix.go +++ b/netclient/wireguard/unix.go @@ -65,9 +65,6 @@ func ApplyWGQuickConf(confPath string, ifacename string) error { ncutils.RunCmd("wg-quick down "+confPath, true) } _, err = ncutils.RunCmd("wg-quick up "+confPath, true) - // if err != nil { - // return err - // } return err } } @@ -126,6 +123,6 @@ func StorePrivKey(key string, network string) error { // RetrievePrivKey - reads wg priv key from local disk func RetrievePrivKey(network string) (string, error) { - dat, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "wgkey-" + network) + dat, err := ncutils.GetFileWithRetry(ncutils.GetNetclientPathSpecific()+"wgkey-"+network, 2) return string(dat), err }