wireguard.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. package logic
  2. import (
  3. "os"
  4. "os/exec"
  5. "strings"
  6. "github.com/gravitl/netmaker/logger"
  7. "github.com/gravitl/netmaker/models"
  8. "github.com/gravitl/netmaker/netclient/ncutils"
  9. "github.com/gravitl/netmaker/netclient/wireguard"
  10. "github.com/gravitl/netmaker/nm-proxy/manager"
  11. "github.com/gravitl/netmaker/servercfg"
  12. "golang.zx2c4.com/wireguard/wgctrl"
  13. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  14. )
  15. // RemoveConf - removes a configuration for a given WireGuard interface
  16. func RemoveConf(iface string, printlog bool) error {
  17. var err error
  18. confPath := ncutils.GetNetclientPathSpecific() + iface + ".conf"
  19. err = removeWGQuickConf(confPath, printlog)
  20. return err
  21. }
  22. // HasPeerConnected - checks if a client node has connected over WG
  23. func HasPeerConnected(node *models.Node) bool {
  24. client, err := wgctrl.New()
  25. if err != nil {
  26. return false
  27. }
  28. defer client.Close()
  29. device, err := client.Device(node.Interface)
  30. if err != nil {
  31. return false
  32. }
  33. for _, peer := range device.Peers {
  34. if peer.PublicKey.String() == node.PublicKey {
  35. if peer.Endpoint != nil {
  36. return true
  37. }
  38. }
  39. }
  40. return false
  41. }
  42. // IfaceDelta - checks if the new node causes an interface change
  43. func IfaceDelta(currentNode *models.Node, newNode *models.Node) bool {
  44. // single comparison statements
  45. if newNode.Endpoint != currentNode.Endpoint ||
  46. newNode.PublicKey != currentNode.PublicKey ||
  47. newNode.Address != currentNode.Address ||
  48. newNode.Address6 != currentNode.Address6 ||
  49. newNode.IsEgressGateway != currentNode.IsEgressGateway ||
  50. newNode.IsIngressGateway != currentNode.IsIngressGateway ||
  51. newNode.IsRelay != currentNode.IsRelay ||
  52. newNode.UDPHolePunch != currentNode.UDPHolePunch ||
  53. newNode.IsPending != currentNode.IsPending ||
  54. newNode.ListenPort != currentNode.ListenPort ||
  55. newNode.LocalListenPort != currentNode.LocalListenPort ||
  56. newNode.MTU != currentNode.MTU ||
  57. newNode.PersistentKeepalive != currentNode.PersistentKeepalive ||
  58. newNode.DNSOn != currentNode.DNSOn ||
  59. newNode.Connected != currentNode.Connected ||
  60. len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) {
  61. return true
  62. }
  63. // multi-comparison statements
  64. if newNode.IsEgressGateway == "yes" {
  65. if len(currentNode.EgressGatewayRanges) != len(newNode.EgressGatewayRanges) {
  66. return true
  67. }
  68. for _, address := range newNode.EgressGatewayRanges {
  69. if !StringSliceContains(currentNode.EgressGatewayRanges, address) {
  70. return true
  71. }
  72. }
  73. }
  74. if newNode.IsRelay == "yes" {
  75. if len(currentNode.RelayAddrs) != len(newNode.RelayAddrs) {
  76. return true
  77. }
  78. for _, address := range newNode.RelayAddrs {
  79. if !StringSliceContains(currentNode.RelayAddrs, address) {
  80. return true
  81. }
  82. }
  83. }
  84. for _, address := range newNode.AllowedIPs {
  85. if !StringSliceContains(currentNode.AllowedIPs, address) {
  86. return true
  87. }
  88. }
  89. return false
  90. }
  91. // == Private Functions ==
  92. // gets the server peers locally
  93. func getSystemPeers(node *models.Node) (map[string]string, error) {
  94. peers := make(map[string]string)
  95. client, err := wgctrl.New()
  96. if err != nil {
  97. return peers, err
  98. }
  99. defer client.Close()
  100. device, err := client.Device(node.Interface)
  101. if err != nil {
  102. return nil, err
  103. }
  104. if device.Peers != nil && len(device.Peers) > 0 {
  105. for _, peer := range device.Peers {
  106. if IsBase64(peer.PublicKey.String()) && peer.Endpoint != nil && CheckEndpoint(peer.Endpoint.String()) {
  107. peers[peer.PublicKey.String()] = peer.Endpoint.String()
  108. }
  109. }
  110. }
  111. return peers, nil
  112. }
  113. func removeWGQuickConf(confPath string, printlog bool) error {
  114. if _, err := ncutils.RunCmd("wg-quick down "+confPath, printlog); err != nil {
  115. return err
  116. }
  117. return nil
  118. }
  119. func setWGConfig(node *models.Node, peerupdate bool) error {
  120. peers, err := GetPeerUpdate(node)
  121. if err != nil {
  122. return err
  123. }
  124. privkey, err := FetchPrivKey(node.ID)
  125. if err != nil {
  126. return err
  127. }
  128. if peerupdate {
  129. if err := wireguard.SetPeers(node.Interface, node, peers.Peers); err != nil {
  130. logger.Log(0, "error updating peers", err.Error())
  131. return err
  132. }
  133. // logger.Log(0, "--------> UPDATE PEERS IN PROXY.....")
  134. // ProxyMgmChan <- &manager.ManagerAction{
  135. // Action: manager.UpdatePeer,
  136. // Payload: manager.ManagerPayload{
  137. // InterfaceName: node.Interface,
  138. // Peers: peers.Peers,
  139. // },
  140. // }
  141. logger.Log(2, "updated peers on server", node.Name)
  142. } else {
  143. err = wireguard.InitWireguard(node, privkey, peers.Peers)
  144. if err != nil {
  145. logger.Log(0, "failed to set wg config on server: ", node.Name, err.Error())
  146. return err
  147. }
  148. logger.Log(3, "finished setting wg config on server", node.Name)
  149. }
  150. if servercfg.IsProxyEnabled() {
  151. logger.Log(0, "--------> ADD/Update INTERFACE TO PROXY.....")
  152. proxyPayload, err := GetPeersForProxy(node, false)
  153. if err != nil {
  154. logger.Log(0, "failed to get peers for proxy: ", err.Error())
  155. } else {
  156. ProxyMgmChan <- &manager.ManagerAction{
  157. Action: manager.AddInterface,
  158. Payload: proxyPayload,
  159. }
  160. }
  161. }
  162. return nil
  163. }
  164. func setWGKeyConfig(node *models.Node) error {
  165. privatekey, err := wgtypes.GeneratePrivateKey()
  166. if err != nil {
  167. return err
  168. }
  169. privkeystring := privatekey.String()
  170. publickey := privatekey.PublicKey()
  171. node.PublicKey = publickey.String()
  172. err = StorePrivKey(node.ID, privkeystring)
  173. if err != nil {
  174. return err
  175. }
  176. if node.Action == models.NODE_UPDATE_KEY {
  177. node.Action = models.NODE_NOOP
  178. }
  179. return setWGConfig(node, false)
  180. }
  181. func removeLocalServer(node *models.Node) error {
  182. var err error
  183. var ifacename = node.Interface
  184. if err = RemovePrivKey(node.ID); err != nil {
  185. logger.Log(1, "failed to remove server conf from db", node.ID)
  186. }
  187. if ifacename != "" {
  188. if !ncutils.IsKernel() {
  189. if err = RemoveConf(ifacename, true); err == nil {
  190. logger.Log(1, "removed WireGuard interface:", ifacename)
  191. }
  192. } else {
  193. ipExec, err := exec.LookPath("ip")
  194. if err != nil {
  195. return err
  196. }
  197. out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false)
  198. dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device")
  199. if err != nil && !dontprint {
  200. logger.Log(1, "error running command:", ipExec, "link del", ifacename)
  201. logger.Log(1, out)
  202. }
  203. if node.PostDown != "" {
  204. ncutils.RunCmd(node.PostDown, false)
  205. }
  206. }
  207. }
  208. home := ncutils.GetNetclientPathSpecific()
  209. if ncutils.FileExists(home + "netconfig-" + node.Network) {
  210. _ = os.Remove(home + "netconfig-" + node.Network)
  211. }
  212. if ncutils.FileExists(home + "nettoken-" + node.Network) {
  213. _ = os.Remove(home + "nettoken-" + node.Network)
  214. }
  215. if ncutils.FileExists(home + "secret-" + node.Network) {
  216. _ = os.Remove(home + "secret-" + node.Network)
  217. }
  218. if ncutils.FileExists(home + "wgkey-" + node.Network) {
  219. _ = os.Remove(home + "wgkey-" + node.Network)
  220. }
  221. if ncutils.FileExists(home + "nm-" + node.Network + ".conf") {
  222. _ = os.Remove(home + "nm-" + node.Network + ".conf")
  223. }
  224. return err
  225. }