noquick.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. ncutils.RunCmd(node.PostDown, false)
  96. }
  97. // set MTU of node interface
  98. if _, err := ncutils.RunCmd(ipExec+" link set mtu "+strconv.Itoa(int(node.MTU))+" up dev "+ifacename, true); err != nil {
  99. logger.Log(1, "failed to create interface with mtu ", strconv.Itoa(int(node.MTU)), "-", ifacename)
  100. return err
  101. }
  102. if node.PostUp != "" {
  103. ncutils.RunCmd(node.PostUp, false)
  104. }
  105. if node.Address6 != "" {
  106. logger.Log(1, "adding address: ", node.Address6)
  107. netmaskArr := strings.Split(node.NetworkSettings.AddressRange6, "/")
  108. var netmask = "64"
  109. if len(netmaskArr) == 2 {
  110. netmask = netmaskArr[1]
  111. }
  112. ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+node.Address6+"/"+netmask, true)
  113. }
  114. return nil
  115. }
  116. // RemoveWithoutWGQuick - Function for running the equivalent of "wg-quick down" for linux if wg-quick is missing
  117. func RemoveWithoutWGQuick(ifacename string) error {
  118. ipExec, err := exec.LookPath("ip")
  119. if err != nil {
  120. return err
  121. }
  122. out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false)
  123. dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device")
  124. if err != nil && !dontprint {
  125. logger.Log(1, "error running command: ", ipExec, " link del ", ifacename)
  126. logger.Log(1, out)
  127. }
  128. network := strings.ReplaceAll(ifacename, "nm-", "")
  129. nodeconf, err := config.ReadConfig(network)
  130. if nodeconf != nil && err == nil {
  131. if nodeconf.Node.PostDown != "" {
  132. ncutils.RunCmd(nodeconf.Node.PostDown, false)
  133. }
  134. } else if err != nil {
  135. logger.Log(1, "error retrieving config: ", err.Error())
  136. }
  137. return err
  138. }
  139. func setKernelDevice(ifacename, address4, mask4, address6, mask6 string, isConnected bool) error {
  140. ipExec, err := exec.LookPath("ip")
  141. if err != nil {
  142. return err
  143. }
  144. // == best effort ==
  145. ncutils.RunCmd("ip link delete dev "+ifacename, false)
  146. if !isConnected {
  147. return fmt.Errorf(disconnect_error)
  148. }
  149. ncutils.RunCmd(ipExec+" link add dev "+ifacename+" type wireguard", true)
  150. if address4 != "" {
  151. ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address4+"/"+mask4, true)
  152. }
  153. if address6 != "" {
  154. ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address6+"/"+mask6, true)
  155. }
  156. return nil
  157. }