grpc.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. package server
  2. import (
  3. "fmt"
  4. "context"
  5. "log"
  6. "strings"
  7. "strconv"
  8. "net"
  9. "time"
  10. "io"
  11. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  12. "github.com/gravitl/netmaker/netclient/config"
  13. "github.com/gravitl/netmaker/netclient/auth"
  14. "github.com/gravitl/netmaker/netclient/local"
  15. nodepb "github.com/gravitl/netmaker/grpc"
  16. "google.golang.org/grpc"
  17. "google.golang.org/grpc/metadata"
  18. //homedir "github.com/mitchellh/go-homedir"
  19. )
  20. func GetNode(network string) nodepb.Node {
  21. modcfg, err := config.ReadConfig(network)
  22. if err != nil {
  23. log.Fatalf("Error: %v", err)
  24. }
  25. nodecfg := modcfg.Node
  26. var node nodepb.Node
  27. node.Name = nodecfg.Name
  28. node.Interface = nodecfg.Interface
  29. node.Nodenetwork = nodecfg.Network
  30. node.Localaddress = nodecfg.LocalAddress
  31. node.Address = nodecfg.WGAddress
  32. node.Address6 = nodecfg.WGAddress6
  33. node.Listenport = nodecfg.Port
  34. node.Keepalive = nodecfg.KeepAlive
  35. node.Postup = nodecfg.PostUp
  36. node.Postdown = nodecfg.PostDown
  37. node.Publickey = nodecfg.PublicKey
  38. node.Macaddress = nodecfg.MacAddress
  39. node.Endpoint = nodecfg.Endpoint
  40. node.Password = nodecfg.Password
  41. if nodecfg.DNS == "on" {
  42. node.Dnsoff = false
  43. } else {
  44. node.Dnsoff = true
  45. }
  46. if nodecfg.IsDualStack == "yes" {
  47. node.Isdualstack = true
  48. } else {
  49. node.Isdualstack = false
  50. }
  51. if nodecfg.IsIngressGateway == "yes" {
  52. node.Isingressgateway= true
  53. } else {
  54. node.Isingressgateway = false
  55. }
  56. return node
  57. }
  58. func RemoveNetwork(network string) error {
  59. //need to implement checkin on server side
  60. cfg, err := config.ReadConfig(network)
  61. if err != nil {
  62. return err
  63. }
  64. servercfg := cfg.Server
  65. node := cfg.Node
  66. fmt.Println("Deleting remote node with MAC: " + node.MacAddress)
  67. var wcclient nodepb.NodeServiceClient
  68. var requestOpts grpc.DialOption
  69. requestOpts = grpc.WithInsecure()
  70. conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
  71. if err != nil {
  72. log.Printf("Unable to establish client connection to " + servercfg.GRPCAddress + ": %v", err)
  73. //return err
  74. }else {
  75. wcclient = nodepb.NewNodeServiceClient(conn)
  76. ctx := context.Background()
  77. ctx, err = auth.SetJWT(wcclient, network)
  78. if err != nil {
  79. //return err
  80. log.Printf("Failed to authenticate: %v", err)
  81. } else {
  82. var header metadata.MD
  83. _, err = wcclient.DeleteNode(
  84. ctx,
  85. &nodepb.DeleteNodeReq{
  86. Macaddress: node.MacAddress,
  87. NetworkName: node.Network,
  88. },
  89. grpc.Header(&header),
  90. )
  91. if err != nil {
  92. log.Printf("Encountered error deleting node: %v", err)
  93. fmt.Println(err)
  94. } else {
  95. fmt.Println("Deleted node " + node.MacAddress)
  96. }
  97. }
  98. }
  99. err = local.WipeLocal(network)
  100. if err != nil {
  101. log.Printf("Unable to wipe local config: %v", err)
  102. }
  103. if cfg.Daemon != "off" {
  104. err = local.RemoveSystemDServices(network)
  105. }
  106. return err
  107. }
  108. func GetPeers(macaddress string, network string, server string, dualstack bool, isIngressGateway bool) ([]wgtypes.PeerConfig, bool, []string, error) {
  109. //need to implement checkin on server side
  110. hasGateway := false
  111. var gateways []string
  112. var peers []wgtypes.PeerConfig
  113. var wcclient nodepb.NodeServiceClient
  114. cfg, err := config.ReadConfig(network)
  115. if err != nil {
  116. log.Fatalf("Issue retrieving config for network: " + network + ". Please investigate: %v", err)
  117. }
  118. nodecfg := cfg.Node
  119. keepalive := nodecfg.KeepAlive
  120. keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
  121. if err != nil {
  122. log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
  123. }
  124. requestOpts := grpc.WithInsecure()
  125. conn, err := grpc.Dial(server, requestOpts)
  126. if err != nil {
  127. log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
  128. }
  129. // Instantiate the BlogServiceClient with our client connection to the server
  130. wcclient = nodepb.NewNodeServiceClient(conn)
  131. req := &nodepb.GetPeersReq{
  132. Macaddress: macaddress,
  133. Network: network,
  134. }
  135. ctx := context.Background()
  136. ctx, err = auth.SetJWT(wcclient, network)
  137. if err != nil {
  138. fmt.Println("Failed to authenticate.")
  139. return peers, hasGateway, gateways, err
  140. }
  141. var header metadata.MD
  142. stream, err := wcclient.GetPeers(ctx, req, grpc.Header(&header))
  143. if err != nil {
  144. fmt.Println("Error retrieving peers")
  145. fmt.Println(err)
  146. return nil, hasGateway, gateways, err
  147. }
  148. for {
  149. res, err := stream.Recv()
  150. // If end of stream, break the loop
  151. if err == io.EOF {
  152. break
  153. }
  154. // if err, return an error
  155. if err != nil {
  156. if strings.Contains(err.Error(), "mongo: no documents in result") {
  157. continue
  158. } else {
  159. fmt.Println("ERROR ENCOUNTERED WITH RESPONSE")
  160. fmt.Println(res)
  161. return peers, hasGateway, gateways, err
  162. }
  163. }
  164. pubkey, err := wgtypes.ParseKey(res.Peers.Publickey)
  165. if err != nil {
  166. fmt.Println("error parsing key")
  167. return peers, hasGateway, gateways, err
  168. }
  169. if nodecfg.PublicKey == res.Peers.Publickey {
  170. continue
  171. }
  172. if nodecfg.Endpoint == res.Peers.Endpoint {
  173. if nodecfg.LocalAddress != res.Peers.Localaddress && res.Peers.Localaddress != "" {
  174. res.Peers.Endpoint = res.Peers.Localaddress
  175. } else {
  176. continue
  177. }
  178. }
  179. var peer wgtypes.PeerConfig
  180. var peeraddr = net.IPNet{
  181. IP: net.ParseIP(res.Peers.Address),
  182. Mask: net.CIDRMask(32, 32),
  183. }
  184. var allowedips []net.IPNet
  185. allowedips = append(allowedips, peeraddr)
  186. if res.Peers.Isegressgateway {
  187. hasGateway = true
  188. gateways = append(gateways,res.Peers.Egressgatewayrange)
  189. _, ipnet, err := net.ParseCIDR(res.Peers.Egressgatewayrange)
  190. if err != nil {
  191. fmt.Println("ERROR ENCOUNTERED SETTING GATEWAY")
  192. fmt.Println("NOT SETTING GATEWAY")
  193. fmt.Println(err)
  194. } else {
  195. fmt.Println(" Gateway Range: " + res.Peers.Egressgatewayrange)
  196. allowedips = append(allowedips, *ipnet)
  197. }
  198. }
  199. if res.Peers.Address6 != "" && dualstack {
  200. var addr6 = net.IPNet{
  201. IP: net.ParseIP(res.Peers.Address6),
  202. Mask: net.CIDRMask(128, 128),
  203. }
  204. allowedips = append(allowedips, addr6)
  205. }
  206. if keepalive != 0 {
  207. peer = wgtypes.PeerConfig{
  208. PublicKey: pubkey,
  209. PersistentKeepaliveInterval: &keepalivedur,
  210. Endpoint: &net.UDPAddr{
  211. IP: net.ParseIP(res.Peers.Endpoint),
  212. Port: int(res.Peers.Listenport),
  213. },
  214. ReplaceAllowedIPs: true,
  215. AllowedIPs: allowedips,
  216. }
  217. } else {
  218. peer = wgtypes.PeerConfig{
  219. PublicKey: pubkey,
  220. Endpoint: &net.UDPAddr{
  221. IP: net.ParseIP(res.Peers.Endpoint),
  222. Port: int(res.Peers.Listenport),
  223. },
  224. ReplaceAllowedIPs: true,
  225. AllowedIPs: allowedips,
  226. }
  227. }
  228. peers = append(peers, peer)
  229. }
  230. if isIngressGateway {
  231. extPeers, err := GetExtPeers(macaddress, network, server, dualstack)
  232. if err == nil {
  233. peers = append(peers, extPeers...)
  234. } else {
  235. fmt.Println("ERROR RETRIEVING EXTERNAL PEERS")
  236. fmt.Println(err)
  237. }
  238. }
  239. return peers, hasGateway, gateways, err
  240. }
  241. func GetExtPeers(macaddress string, network string, server string, dualstack bool) ([]wgtypes.PeerConfig, error) {
  242. var peers []wgtypes.PeerConfig
  243. var wcclient nodepb.NodeServiceClient
  244. cfg, err := config.ReadConfig(network)
  245. if err != nil {
  246. log.Fatalf("Issue retrieving config for network: " + network + ". Please investigate: %v", err)
  247. }
  248. nodecfg := cfg.Node
  249. requestOpts := grpc.WithInsecure()
  250. conn, err := grpc.Dial(server, requestOpts)
  251. if err != nil {
  252. log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
  253. }
  254. // Instantiate the BlogServiceClient with our client connection to the server
  255. wcclient = nodepb.NewNodeServiceClient(conn)
  256. req := &nodepb.GetExtPeersReq{
  257. Macaddress: macaddress,
  258. Network: network,
  259. }
  260. ctx := context.Background()
  261. ctx, err = auth.SetJWT(wcclient, network)
  262. if err != nil {
  263. fmt.Println("Failed to authenticate.")
  264. return peers, err
  265. }
  266. var header metadata.MD
  267. stream, err := wcclient.GetExtPeers(ctx, req, grpc.Header(&header))
  268. if err != nil {
  269. fmt.Println("Error retrieving peers")
  270. fmt.Println(err)
  271. return nil, err
  272. }
  273. for {
  274. res, err := stream.Recv()
  275. // If end of stream, break the loop
  276. if err == io.EOF {
  277. break
  278. }
  279. // if err, return an error
  280. if err != nil {
  281. if strings.Contains(err.Error(), "mongo: no documents in result") {
  282. continue
  283. } else {
  284. fmt.Println("ERROR ENCOUNTERED WITH RESPONSE")
  285. fmt.Println(res)
  286. return peers, err
  287. }
  288. }
  289. pubkey, err := wgtypes.ParseKey(res.Extpeers.Publickey)
  290. if err != nil {
  291. fmt.Println("error parsing key")
  292. return peers, err
  293. }
  294. if nodecfg.PublicKey == res.Extpeers.Publickey {
  295. continue
  296. }
  297. var peer wgtypes.PeerConfig
  298. var peeraddr = net.IPNet{
  299. IP: net.ParseIP(res.Extpeers.Address),
  300. Mask: net.CIDRMask(32, 32),
  301. }
  302. var allowedips []net.IPNet
  303. allowedips = append(allowedips, peeraddr)
  304. if res.Extpeers.Address6 != "" && dualstack {
  305. var addr6 = net.IPNet{
  306. IP: net.ParseIP(res.Extpeers.Address6),
  307. Mask: net.CIDRMask(128, 128),
  308. }
  309. allowedips = append(allowedips, addr6)
  310. }
  311. peer = wgtypes.PeerConfig{
  312. PublicKey: pubkey,
  313. ReplaceAllowedIPs: true,
  314. AllowedIPs: allowedips,
  315. }
  316. peers = append(peers, peer)
  317. }
  318. return peers, err
  319. }