common.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. package functions
  2. import (
  3. "errors"
  4. "fmt"
  5. "log"
  6. "net"
  7. "os"
  8. "strings"
  9. nodepb "github.com/gravitl/netmaker/grpc"
  10. "github.com/gravitl/netmaker/models"
  11. "github.com/gravitl/netmaker/netclient/auth"
  12. "github.com/gravitl/netmaker/netclient/config"
  13. "github.com/gravitl/netmaker/netclient/daemon"
  14. "github.com/gravitl/netmaker/netclient/ncutils"
  15. "github.com/gravitl/netmaker/netclient/wireguard"
  16. "golang.zx2c4.com/wireguard/wgctrl"
  17. "google.golang.org/grpc"
  18. "google.golang.org/grpc/metadata"
  19. )
  20. // ListPorts - lists ports of WireGuard devices
  21. func ListPorts() error {
  22. wgclient, err := wgctrl.New()
  23. if err != nil {
  24. return err
  25. }
  26. defer wgclient.Close()
  27. devices, err := wgclient.Devices()
  28. if err != nil {
  29. return err
  30. }
  31. fmt.Println("Here are your ports:")
  32. for _, i := range devices {
  33. fmt.Println(i.ListenPort)
  34. }
  35. return err
  36. }
  37. func getPrivateAddr() (string, error) {
  38. var local string
  39. conn, err := net.Dial("udp", "8.8.8.8:80")
  40. if err != nil {
  41. log.Fatal(err)
  42. }
  43. defer conn.Close()
  44. localAddr := conn.LocalAddr().(*net.UDPAddr)
  45. localIP := localAddr.IP
  46. local = localIP.String()
  47. if local == "" {
  48. local, err = getPrivateAddrBackup()
  49. }
  50. if local == "" {
  51. err = errors.New("could not find local ip")
  52. }
  53. return local, err
  54. }
  55. func getPrivateAddrBackup() (string, error) {
  56. ifaces, err := net.Interfaces()
  57. if err != nil {
  58. return "", err
  59. }
  60. var local string
  61. found := false
  62. for _, i := range ifaces {
  63. if i.Flags&net.FlagUp == 0 {
  64. continue // interface down
  65. }
  66. if i.Flags&net.FlagLoopback != 0 {
  67. continue // loopback interface
  68. }
  69. addrs, err := i.Addrs()
  70. if err != nil {
  71. return "", err
  72. }
  73. for _, addr := range addrs {
  74. var ip net.IP
  75. switch v := addr.(type) {
  76. case *net.IPNet:
  77. if !found {
  78. ip = v.IP
  79. local = ip.String()
  80. found = true
  81. }
  82. case *net.IPAddr:
  83. if !found {
  84. ip = v.IP
  85. local = ip.String()
  86. found = true
  87. }
  88. }
  89. }
  90. }
  91. if !found {
  92. err := errors.New("local ip address not found")
  93. return "", err
  94. }
  95. return local, err
  96. }
  97. // DEPRECATED
  98. // func needInterfaceUpdate(ctx context.Context, mac string, network string, iface string) (bool, string, error) {
  99. // var header metadata.MD
  100. // req := &nodepb.Object{
  101. // Data: mac + "###" + network,
  102. // Type: nodepb.STRING_TYPE,
  103. // }
  104. // readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
  105. // if err != nil {
  106. // return false, "", err
  107. // }
  108. // var resNode models.Node
  109. // if err := json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
  110. // return false, iface, err
  111. // }
  112. // oldiface := resNode.Interface
  113. // return iface != oldiface, oldiface, err
  114. // }
  115. // GetNode - gets node locally
  116. func GetNode(network string) models.Node {
  117. modcfg, err := config.ReadConfig(network)
  118. if err != nil {
  119. log.Fatalf("Error: %v", err)
  120. }
  121. return modcfg.Node
  122. }
  123. // Uninstall - uninstalls networks from client
  124. func Uninstall() error {
  125. networks, err := ncutils.GetSystemNetworks()
  126. if err != nil {
  127. ncutils.PrintLog("unable to retrieve networks: "+err.Error(), 1)
  128. ncutils.PrintLog("continuing uninstall without leaving networks", 1)
  129. } else {
  130. for _, network := range networks {
  131. err = LeaveNetwork(network)
  132. if err != nil {
  133. ncutils.PrintLog("Encounter issue leaving network "+network+": "+err.Error(), 1)
  134. }
  135. }
  136. }
  137. // clean up OS specific stuff
  138. if ncutils.IsWindows() {
  139. daemon.CleanupWindows()
  140. } else if ncutils.IsMac() {
  141. daemon.CleanupMac()
  142. } else if ncutils.IsLinux() {
  143. daemon.CleanupLinux()
  144. } else if !ncutils.IsKernel() {
  145. ncutils.PrintLog("manual cleanup required", 1)
  146. }
  147. return err
  148. }
  149. // LeaveNetwork - client exits a network
  150. func LeaveNetwork(network string) error {
  151. cfg, err := config.ReadConfig(network)
  152. if err != nil {
  153. return err
  154. }
  155. servercfg := cfg.Server
  156. node := cfg.Node
  157. if node.IsServer != "yes" {
  158. var wcclient nodepb.NodeServiceClient
  159. conn, err := grpc.Dial(cfg.Server.GRPCAddress,
  160. ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
  161. if err != nil {
  162. log.Printf("Unable to establish client connection to "+servercfg.GRPCAddress+": %v", err)
  163. }
  164. defer conn.Close()
  165. wcclient = nodepb.NewNodeServiceClient(conn)
  166. ctx, err := auth.SetJWT(wcclient, network)
  167. if err != nil {
  168. log.Printf("Failed to authenticate: %v", err)
  169. } else { // handle client side
  170. node.SetID()
  171. var header metadata.MD
  172. _, err = wcclient.DeleteNode(
  173. ctx,
  174. &nodepb.Object{
  175. Data: node.ID,
  176. Type: nodepb.STRING_TYPE,
  177. },
  178. grpc.Header(&header),
  179. )
  180. if err != nil {
  181. ncutils.PrintLog("encountered error deleting node: "+err.Error(), 1)
  182. } else {
  183. ncutils.PrintLog("removed machine from "+node.Network+" network on remote server", 1)
  184. }
  185. }
  186. }
  187. //extra network route setting required for freebsd and windows
  188. if ncutils.IsWindows() {
  189. ip, mask, err := ncutils.GetNetworkIPMask(node.NetworkSettings.AddressRange)
  190. if err != nil {
  191. ncutils.PrintLog(err.Error(), 1)
  192. }
  193. _, _ = ncutils.RunCmd("route delete "+ip+" mask "+mask+" "+node.Address, true)
  194. } else if ncutils.IsFreeBSD() {
  195. _, _ = ncutils.RunCmd("route del -net "+node.NetworkSettings.AddressRange+" -interface "+node.Interface, true)
  196. } else if ncutils.IsLinux() {
  197. _, _ = ncutils.RunCmd("ip -4 route del "+node.NetworkSettings.AddressRange+" dev "+node.Interface, false)
  198. }
  199. return RemoveLocalInstance(cfg, network)
  200. }
  201. // RemoveLocalInstance - remove all netclient files locally for a network
  202. func RemoveLocalInstance(cfg *config.ClientConfig, networkName string) error {
  203. err := WipeLocal(networkName)
  204. if err != nil {
  205. ncutils.PrintLog("unable to wipe local config", 1)
  206. } else {
  207. ncutils.PrintLog("removed "+networkName+" network locally", 1)
  208. }
  209. if cfg.Daemon != "off" {
  210. if ncutils.IsWindows() {
  211. // TODO: Remove job?
  212. } else if ncutils.IsMac() {
  213. //TODO: Delete mac daemon
  214. } else {
  215. err = daemon.RemoveSystemDServices()
  216. }
  217. }
  218. return err
  219. }
  220. // DeleteInterface - delete an interface of a network
  221. func DeleteInterface(ifacename string, postdown string) error {
  222. return wireguard.RemoveConf(ifacename, true)
  223. }
  224. // WipeLocal - wipes local instance
  225. func WipeLocal(network string) error {
  226. cfg, err := config.ReadConfig(network)
  227. if err != nil {
  228. return err
  229. }
  230. nodecfg := cfg.Node
  231. ifacename := nodecfg.Interface
  232. if ifacename != "" {
  233. if err = wireguard.RemoveConf(ifacename, true); err == nil {
  234. ncutils.PrintLog("removed WireGuard interface: "+ifacename, 1)
  235. } else if strings.Contains(err.Error(), "does not exist") {
  236. err = nil
  237. }
  238. }
  239. home := ncutils.GetNetclientPathSpecific()
  240. if ncutils.FileExists(home + "netconfig-" + network) {
  241. _ = os.Remove(home + "netconfig-" + network)
  242. }
  243. if ncutils.FileExists(home + "backup.netconfig-" + network) {
  244. _ = os.Remove(home + "backup.netconfig-" + network)
  245. }
  246. if ncutils.FileExists(home + "nettoken-" + network) {
  247. _ = os.Remove(home + "nettoken-" + network)
  248. }
  249. if ncutils.FileExists(home + "secret-" + network) {
  250. _ = os.Remove(home + "secret-" + network)
  251. }
  252. if ncutils.FileExists(home + "wgkey-" + network) {
  253. _ = os.Remove(home + "wgkey-" + network)
  254. }
  255. if ncutils.FileExists(home + "nm-" + network + ".conf") {
  256. _ = os.Remove(home + "nm-" + network + ".conf")
  257. }
  258. return err
  259. }
  260. func getLocalIP(node models.Node) string {
  261. var local string
  262. ifaces, err := net.Interfaces()
  263. if err != nil {
  264. return local
  265. }
  266. _, localrange, err := net.ParseCIDR(node.LocalRange)
  267. if err != nil {
  268. return local
  269. }
  270. found := false
  271. for _, i := range ifaces {
  272. if i.Flags&net.FlagUp == 0 {
  273. continue // interface down
  274. }
  275. if i.Flags&net.FlagLoopback != 0 {
  276. continue // loopback interface
  277. }
  278. addrs, err := i.Addrs()
  279. if err != nil {
  280. return local
  281. }
  282. for _, addr := range addrs {
  283. var ip net.IP
  284. switch v := addr.(type) {
  285. case *net.IPNet:
  286. if !found {
  287. ip = v.IP
  288. local = ip.String()
  289. if node.IsLocal == "yes" {
  290. found = localrange.Contains(ip)
  291. } else {
  292. found = true
  293. }
  294. }
  295. case *net.IPAddr:
  296. if !found {
  297. ip = v.IP
  298. local = ip.String()
  299. if node.IsLocal == "yes" {
  300. found = localrange.Contains(ip)
  301. } else {
  302. found = true
  303. }
  304. }
  305. }
  306. }
  307. }
  308. return local
  309. }