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. len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) {
  57. return true
  58. }
  59. // multi-comparison statements
  60. if newNode.IsEgressGateway == "yes" {
  61. if len(currentNode.EgressGatewayRanges) != len(newNode.EgressGatewayRanges) {
  62. return true
  63. }
  64. for _, address := range newNode.EgressGatewayRanges {
  65. if !StringSliceContains(currentNode.EgressGatewayRanges, address) {
  66. return true
  67. }
  68. }
  69. }
  70. if newNode.IsRelay == "yes" {
  71. if len(currentNode.RelayAddrs) != len(newNode.RelayAddrs) {
  72. return true
  73. }
  74. for _, address := range newNode.RelayAddrs {
  75. if !StringSliceContains(currentNode.RelayAddrs, address) {
  76. return true
  77. }
  78. }
  79. }
  80. for _, address := range newNode.AllowedIPs {
  81. if !StringSliceContains(currentNode.AllowedIPs, address) {
  82. return true
  83. }
  84. }
  85. return false
  86. }
  87. // == Private Functions ==
  88. // gets the server peers locally
  89. func getSystemPeers(node *models.Node) (map[string]string, error) {
  90. peers := make(map[string]string)
  91. client, err := wgctrl.New()
  92. if err != nil {
  93. return peers, err
  94. }
  95. defer client.Close()
  96. device, err := client.Device(node.Interface)
  97. if err != nil {
  98. return nil, err
  99. }
  100. if device.Peers != nil && len(device.Peers) > 0 {
  101. for _, peer := range device.Peers {
  102. if IsBase64(peer.PublicKey.String()) && peer.Endpoint != nil && CheckEndpoint(peer.Endpoint.String()) {
  103. peers[peer.PublicKey.String()] = peer.Endpoint.String()
  104. }
  105. }
  106. }
  107. return peers, nil
  108. }
  109. func removeWGQuickConf(confPath string, printlog bool) error {
  110. if _, err := ncutils.RunCmd("wg-quick down "+confPath, printlog); err != nil {
  111. return err
  112. }
  113. return nil
  114. }
  115. func setWGConfig(node *models.Node, peerupdate bool) error {
  116. peers, err := GetPeerUpdate(node)
  117. if err != nil {
  118. return err
  119. }
  120. privkey, err := FetchPrivKey(node.ID)
  121. if err != nil {
  122. return err
  123. }
  124. if peerupdate {
  125. if err := wireguard.SetPeers(node.Interface, node, peers.Peers); err != nil {
  126. logger.Log(0, "error updating peers", err.Error())
  127. }
  128. logger.Log(2, "updated peers on server", node.Name)
  129. } else {
  130. err = wireguard.InitWireguard(node, privkey, peers.Peers, false)
  131. logger.Log(3, "finished setting wg config on server", node.Name)
  132. }
  133. return err
  134. }
  135. func setWGKeyConfig(node *models.Node) error {
  136. privatekey, err := wgtypes.GeneratePrivateKey()
  137. if err != nil {
  138. return err
  139. }
  140. privkeystring := privatekey.String()
  141. publickey := privatekey.PublicKey()
  142. node.PublicKey = publickey.String()
  143. err = StorePrivKey(node.ID, privkeystring)
  144. if err != nil {
  145. return err
  146. }
  147. if node.Action == models.NODE_UPDATE_KEY {
  148. node.Action = models.NODE_NOOP
  149. }
  150. return setWGConfig(node, false)
  151. }
  152. func removeLocalServer(node *models.Node) error {
  153. var err error
  154. var ifacename = node.Interface
  155. if err = RemovePrivKey(node.ID); err != nil {
  156. logger.Log(1, "failed to remove server conf from db", node.ID)
  157. }
  158. if ifacename != "" {
  159. if !ncutils.IsKernel() {
  160. if err = RemoveConf(ifacename, true); err == nil {
  161. logger.Log(1, "removed WireGuard interface:", ifacename)
  162. }
  163. } else {
  164. ipExec, err := exec.LookPath("ip")
  165. if err != nil {
  166. return err
  167. }
  168. out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false)
  169. dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device")
  170. if err != nil && !dontprint {
  171. logger.Log(1, "error running command:", ipExec, "link del", ifacename)
  172. logger.Log(1, out)
  173. }
  174. if node.PostDown != "" {
  175. runcmds := strings.Split(node.PostDown, "; ")
  176. _ = ncutils.RunCmds(runcmds, 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. }