wireguard.go 5.8 KB

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