common.go 7.8 KB

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