mac.go 7.3 KB

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