mac.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. package wireguard
  2. import (
  3. "bufio"
  4. "errors"
  5. "log"
  6. "os"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "github.com/gravitl/netmaker/models"
  11. "github.com/gravitl/netmaker/netclient/ncutils"
  12. )
  13. // WgQuickDownMac - bring down mac interface, remove routes, and run post-down commands
  14. func WgQuickDownMac(node *models.Node, iface string) error {
  15. if err := RemoveConfMac(iface); err != nil {
  16. return err
  17. }
  18. if node.PostDown != "" {
  19. runcmds := strings.Split(node.PostDown, "; ")
  20. ncutils.RunCmds(runcmds, true)
  21. }
  22. return nil
  23. }
  24. // RemoveConfMac - bring down mac interface and remove routes
  25. func RemoveConfMac(iface string) error {
  26. realIface, err := getRealIface(iface)
  27. log.Println("DELETE ME: attempting to remove " + realIface)
  28. if realIface != "" {
  29. err = deleteInterface(iface, realIface)
  30. }
  31. return err
  32. }
  33. // WgQuickUpMac - bring up mac interface and set routes
  34. func WgQuickUpMac(node *models.Node, iface string, confPath string) error {
  35. var err error
  36. var realIface string
  37. realIface, err = getRealIface(iface)
  38. if realIface != "" && err == nil {
  39. deleteInterface(iface, realIface)
  40. deleteRoutes(realIface)
  41. }
  42. realIface, err = addInterface(iface)
  43. if err != nil {
  44. ncutils.PrintLog("error creating wg interface", 1)
  45. return err
  46. }
  47. time.Sleep(time.Second / 2)
  48. err = setConfig(realIface, confPath)
  49. if err != nil {
  50. ncutils.PrintLog("error setting config for "+realIface, 1)
  51. return err
  52. }
  53. var ips = append(node.AllowedIPs, node.Address, node.Address6)
  54. peerIPs := getPeerIPs(realIface)
  55. if len(peerIPs) > 0 {
  56. ips = append(ips, peerIPs...)
  57. }
  58. for _, i := range ips {
  59. if i != "" {
  60. err = addAddress(realIface, i)
  61. if err != nil {
  62. ncutils.PrintLog("error adding address "+i+" on interface "+realIface, 1)
  63. return err
  64. }
  65. }
  66. }
  67. setMTU(realIface, int(node.MTU))
  68. err = upInterface(realIface)
  69. if err != nil {
  70. ncutils.PrintLog("error turning on interface "+iface, 1)
  71. return err
  72. }
  73. for _, i := range ips {
  74. if i != "" {
  75. err = addRoute(i, realIface)
  76. if err != nil {
  77. ncutils.PrintLog("error adding route to "+realIface+" for "+i, 1)
  78. return err
  79. }
  80. }
  81. }
  82. //next, wg-quick runs set_endpoint_direct_route
  83. //next, wg-quick runs monitor_daemon
  84. time.Sleep(time.Second / 2)
  85. if node.PostUp != "" {
  86. runcmds := strings.Split(node.PostUp, "; ")
  87. ncutils.RunCmds(runcmds, true)
  88. }
  89. return err
  90. }
  91. // addInterface - adds mac interface and creates reference file to match iface name with tun iface
  92. func addInterface(iface string) (string, error) {
  93. ncutils.RunCmd("mkdir -p /var/run/wireguard/", true)
  94. ncutils.RunCmd("wireguard-go utun", true)
  95. realIface, err := ncutils.GetNewIface("/var/run/wireguard/")
  96. if iface != "" && err == nil {
  97. ifacePath := "/var/run/wireguard/" + iface + ".name"
  98. err = os.WriteFile(ifacePath, []byte(realIface), 0600)
  99. }
  100. return realIface, err
  101. }
  102. // getRealIface - retrieves tun iface based on reference iface name from config file
  103. func getRealIface(iface string) (string, error) {
  104. ncutils.RunCmd("wg show interfaces", false)
  105. ifacePath := "/var/run/wireguard/" + iface + ".name"
  106. if !(ncutils.FileExists(ifacePath)) {
  107. return "", errors.New(ifacePath + " does not exist")
  108. }
  109. realIfaceName, err := ncutils.GetFileAsString(ifacePath)
  110. if err != nil {
  111. return "", err
  112. }
  113. if !(ncutils.FileExists("/var/run/wireguard/" + realIfaceName + ".sock")) {
  114. return "", errors.New("interface file does not exist")
  115. }
  116. return realIfaceName, nil
  117. }
  118. // deleteRoutes - deletes network routes associated with interface
  119. func deleteRoutes(iface string) error {
  120. realIface, err := getRealIface(iface)
  121. if err != nil {
  122. return err
  123. }
  124. var inets = [2]string{"inet", "inet6"}
  125. for _, inet := range inets {
  126. ifaceList, err := ncutils.RunCmd("netstat -nr -f "+inet+" | grep -e "+realIface+" | awk '{print $1}'", true)
  127. if err != nil {
  128. return err
  129. }
  130. destinations := strings.Split(ifaceList, "\n")
  131. for _, i := range destinations {
  132. ncutils.RunCmd("route -q -n delete -"+inet+" "+i, true)
  133. }
  134. }
  135. // wg-quick deletes ENDPOINTS here (runs 'route -q delete' for each peer endpoint on the interface.)
  136. // We don't believe this is necessary.
  137. return nil
  138. }
  139. // deleteInterface - deletes the real interface and the referance file
  140. func deleteInterface(iface string, realIface string) error {
  141. var err error
  142. var out string
  143. if iface != "" {
  144. os.Remove("/var/run/wireguard/" + realIface + ".sock")
  145. os.Remove("/var/run/wireguard/" + iface + ".name")
  146. }
  147. out, err = ncutils.RunCmd("ifconfig "+realIface+" down", false)
  148. if strings.Contains(err.Error(), "does not exist") {
  149. err = nil
  150. } else if err != nil && out != "" {
  151. err = errors.New(out)
  152. }
  153. return err
  154. }
  155. // upInterface - bring up the interface with ifconfig
  156. func upInterface(iface string) error {
  157. var err error
  158. _, err = ncutils.RunCmd("ifconfig "+iface+" up", true)
  159. return err
  160. }
  161. // addAddress - adds private address to the interface
  162. func addAddress(iface string, addr string) error {
  163. var err error
  164. if strings.Contains(addr, ":") {
  165. _, err = ncutils.RunCmd("ifconfig "+iface+" inet6 "+addr+" alias", true)
  166. } else {
  167. _, err = ncutils.RunCmd("ifconfig "+iface+" inet "+addr+" 255.255.255.0 alias", true)
  168. }
  169. return err
  170. }
  171. // setMTU - sets MTU for the interface
  172. func setMTU(iface string, mtu int) error {
  173. var err error
  174. if mtu == 0 {
  175. mtu = 1280
  176. }
  177. _, err = ncutils.RunCmd("ifconfig "+iface+" mtu "+strconv.Itoa(mtu), true)
  178. return err
  179. }
  180. // addRoute - adds network route to the interface if it does not already exist
  181. func addRoute(addr string, iface string) error {
  182. var err error
  183. var out string
  184. var inetx = "inet"
  185. if strings.Contains(addr, ":") {
  186. inetx = "inet6"
  187. }
  188. out, err = ncutils.RunCmd("route -n get -"+inetx+" "+addr, true)
  189. if err != nil {
  190. return err
  191. }
  192. if !(strings.Contains(out, iface)) {
  193. _, err = ncutils.RunCmd("route -q -n add -"+inetx+" "+addr+" -interface "+iface, true)
  194. }
  195. return err
  196. }
  197. // setConfig - sets configuration of the wireguard interface from the config file
  198. func setConfig(realIface string, confPath string) error {
  199. confString := getConfig(confPath)
  200. err := os.WriteFile(confPath+".tmp", []byte(confString), 0600)
  201. if err != nil {
  202. return err
  203. }
  204. _, err = ncutils.RunCmd("wg setconf "+realIface+" "+confPath+".tmp", true)
  205. os.Remove(confPath + ".tmp")
  206. return err
  207. }
  208. // getConfig - gets config from config file and strips out incompatible fields
  209. func getConfig(path string) string {
  210. var confCmd = "grep -v -e Address -e MTU -e PostUp -e PostDown "
  211. confRaw, _ := ncutils.RunCmd(confCmd+path, false)
  212. return confRaw
  213. }
  214. // SetMacPeerRoutes - sets routes for interface from the peer list for all AllowedIps
  215. func SetMacPeerRoutes(realIface string) error {
  216. var err error
  217. peerIPs := getPeerIPs(realIface)
  218. if len(peerIPs) == 0 {
  219. return err
  220. }
  221. for _, i := range peerIPs {
  222. if i != "" {
  223. err = addRoute(i, realIface)
  224. if err != nil {
  225. ncutils.PrintLog("error adding route to "+realIface+" for "+i, 1)
  226. return err
  227. }
  228. }
  229. }
  230. return err
  231. }
  232. // getPeerIPs - retrieves peer AllowedIPs from WireGuard interface
  233. func getPeerIPs(realIface string) []string {
  234. allowedIps := []string{}
  235. out, err := ncutils.RunCmd("wg show "+realIface+" allowed-ips", false)
  236. if err != nil {
  237. return allowedIps
  238. }
  239. scanner := bufio.NewScanner(strings.NewReader(out))
  240. for scanner.Scan() {
  241. fields := strings.Fields(scanner.Text())
  242. if len(fields) > 1 {
  243. allowedIps = append(allowedIps, fields[1:]...)
  244. }
  245. }
  246. return allowedIps
  247. }