mac.go 7.1 KB

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