noquick.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package wireguard
  2. import (
  3. "errors"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "strconv"
  8. "strings"
  9. "github.com/gravitl/netmaker/logger"
  10. "github.com/gravitl/netmaker/models"
  11. "github.com/gravitl/netmaker/netclient/config"
  12. "github.com/gravitl/netmaker/netclient/ncutils"
  13. "golang.zx2c4.com/wireguard/wgctrl"
  14. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  15. )
  16. const disconnect_error = "node disconnected"
  17. // ApplyWithoutWGQuick - Function for running the equivalent of "wg-quick up" for linux if wg-quick is missing
  18. func ApplyWithoutWGQuick(node *models.Node, ifacename, confPath string, isConnected bool) error {
  19. ipExec, err := exec.LookPath("ip")
  20. if err != nil {
  21. return err
  22. }
  23. wgclient, err := wgctrl.New()
  24. if err != nil {
  25. return err
  26. }
  27. defer wgclient.Close()
  28. privkey, err := RetrievePrivKey(node.Network)
  29. if err != nil {
  30. return err
  31. }
  32. key, err := wgtypes.ParseKey(privkey)
  33. if err != nil {
  34. return err
  35. }
  36. conf := wgtypes.Config{}
  37. nodeport := int(node.ListenPort)
  38. if node.UDPHolePunch == "yes" &&
  39. node.IsServer == "no" &&
  40. node.IsIngressGateway != "yes" {
  41. conf = wgtypes.Config{
  42. PrivateKey: &key,
  43. }
  44. } else {
  45. conf = wgtypes.Config{
  46. PrivateKey: &key,
  47. ListenPort: &nodeport,
  48. }
  49. }
  50. var address4 string
  51. var address6 string
  52. var mask4 string
  53. var mask6 string
  54. if node.Address != "" {
  55. netmaskArr := strings.Split(node.NetworkSettings.AddressRange, "/")
  56. var netmask = "32"
  57. if len(netmaskArr) == 2 {
  58. netmask = netmaskArr[1]
  59. }
  60. mask4 = netmask
  61. address4 = node.Address
  62. }
  63. if node.Address6 != "" {
  64. netmaskArr := strings.Split(node.NetworkSettings.AddressRange6, "/")
  65. var netmask = "128"
  66. if len(netmaskArr) == 2 {
  67. netmask = netmaskArr[1]
  68. }
  69. mask6 = netmask
  70. address6 = node.Address6
  71. }
  72. err = setKernelDevice(ifacename, address4, mask4, address6, mask6, isConnected)
  73. if err != nil {
  74. if err.Error() == disconnect_error {
  75. return nil
  76. }
  77. }
  78. _, err = wgclient.Device(ifacename)
  79. if err != nil {
  80. if !os.IsNotExist(err) {
  81. return errors.New("Unknown config error: " + err.Error())
  82. }
  83. }
  84. err = wgclient.ConfigureDevice(ifacename, conf)
  85. if err != nil {
  86. if os.IsNotExist(err) {
  87. logger.Log(0, "Could not configure device: ", err.Error())
  88. }
  89. }
  90. if _, err := ncutils.RunCmd(ipExec+" link set down dev "+ifacename, false); err != nil {
  91. logger.Log(1, "attempted to remove interface before editing")
  92. return err
  93. }
  94. if node.PostDown != "" {
  95. runcmds := strings.Split(node.PostDown, "; ")
  96. _ = ncutils.RunCmds(runcmds, false)
  97. }
  98. // set MTU of node interface
  99. if _, err := ncutils.RunCmd(ipExec+" link set mtu "+strconv.Itoa(int(node.MTU))+" up dev "+ifacename, true); err != nil {
  100. logger.Log(1, "failed to create interface with mtu ", strconv.Itoa(int(node.MTU)), "-", ifacename)
  101. return err
  102. }
  103. if node.PostUp != "" {
  104. runcmds := strings.Split(node.PostUp, "; ")
  105. _ = ncutils.RunCmds(runcmds, true)
  106. }
  107. if node.Address6 != "" {
  108. logger.Log(1, "adding address: ", node.Address6)
  109. netmaskArr := strings.Split(node.NetworkSettings.AddressRange6, "/")
  110. var netmask = "64"
  111. if len(netmaskArr) == 2 {
  112. netmask = netmaskArr[1]
  113. }
  114. ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+node.Address6+"/"+netmask, true)
  115. }
  116. return nil
  117. }
  118. // RemoveWithoutWGQuick - Function for running the equivalent of "wg-quick down" for linux if wg-quick is missing
  119. func RemoveWithoutWGQuick(ifacename string) error {
  120. ipExec, err := exec.LookPath("ip")
  121. if err != nil {
  122. return err
  123. }
  124. out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false)
  125. dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device")
  126. if err != nil && !dontprint {
  127. logger.Log(1, "error running command: ", ipExec, " link del ", ifacename)
  128. logger.Log(1, out)
  129. }
  130. network := strings.ReplaceAll(ifacename, "nm-", "")
  131. nodeconf, err := config.ReadConfig(network)
  132. if nodeconf != nil && err == nil {
  133. if nodeconf.Node.PostDown != "" {
  134. runcmds := strings.Split(nodeconf.Node.PostDown, "; ")
  135. _ = ncutils.RunCmds(runcmds, false)
  136. }
  137. } else if err != nil {
  138. logger.Log(1, "error retrieving config: ", err.Error())
  139. }
  140. return err
  141. }
  142. func setKernelDevice(ifacename, address4, mask4, address6, mask6 string, isConnected bool) error {
  143. ipExec, err := exec.LookPath("ip")
  144. if err != nil {
  145. return err
  146. }
  147. // == best effort ==
  148. ncutils.RunCmd("ip link delete dev "+ifacename, false)
  149. if !isConnected {
  150. return fmt.Errorf(disconnect_error)
  151. }
  152. ncutils.RunCmd(ipExec+" link add dev "+ifacename+" type wireguard", true)
  153. if address4 != "" {
  154. ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address4+"/"+mask4, true)
  155. }
  156. if address6 != "" {
  157. ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address6+"/"+mask6, true)
  158. }
  159. return nil
  160. }