kernel.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. package wireguard
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "io/ioutil"
  9. "log"
  10. "net"
  11. "os"
  12. "os/exec"
  13. "strconv"
  14. "strings"
  15. nodepb "github.com/gravitl/netmaker/grpc"
  16. "github.com/gravitl/netmaker/models"
  17. "github.com/gravitl/netmaker/netclient/auth"
  18. "github.com/gravitl/netmaker/netclient/config"
  19. "github.com/gravitl/netmaker/netclient/local"
  20. "github.com/gravitl/netmaker/netclient/server"
  21. "golang.zx2c4.com/wireguard/wgctrl"
  22. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  23. "google.golang.org/grpc"
  24. "google.golang.org/grpc/credentials"
  25. "google.golang.org/grpc/metadata"
  26. //homedir "github.com/mitchellh/go-homedir"
  27. )
  28. func InitGRPCWireguard(client models.IntClient) error {
  29. key, err := wgtypes.ParseKey(client.PrivateKey)
  30. if err != nil {
  31. return err
  32. }
  33. serverkey, err := wgtypes.ParseKey(client.ServerKey)
  34. if err != nil {
  35. return err
  36. }
  37. serverport, err := strconv.Atoi(client.ServerWGPort)
  38. if err != nil {
  39. return err
  40. }
  41. wgclient, err := wgctrl.New()
  42. if err != nil {
  43. log.Fatalf("failed to open client: %v", err)
  44. }
  45. defer wgclient.Close()
  46. ifacename := "grpc-wg-001"
  47. if client.Address6 == "" && client.Address == "" {
  48. return errors.New("no address to configure")
  49. }
  50. currentiface, err := net.InterfaceByName(ifacename)
  51. if err != nil {
  52. _, err = local.RunCmd("ip link add dev " + ifacename + " type wireguard")
  53. if err != nil && !strings.Contains(err.Error(), "exists") {
  54. log.Println("Error creating interface")
  55. }
  56. }
  57. match := false
  58. match6 := false
  59. addrs, _ := currentiface.Addrs()
  60. //Add IPv4Address (make into separate function)
  61. for _, a := range addrs {
  62. if strings.Contains(a.String(), client.Address) {
  63. match = true
  64. }
  65. if strings.Contains(a.String(), client.Address6) {
  66. match6 = true
  67. }
  68. }
  69. if !match && client.Address != "" {
  70. _, err = local.RunCmd("ip address add dev " + ifacename + " " + client.Address + "/24")
  71. if err != nil {
  72. log.Println("Error adding ipv4 address")
  73. fmt.Println(err)
  74. }
  75. }
  76. if !match6 && client.Address6 != "" {
  77. _, err = local.RunCmd("ip address add dev" + ifacename + " " + client.Address6 + "/64")
  78. if err != nil {
  79. log.Println("Error adding ipv6 address")
  80. fmt.Println(err)
  81. }
  82. }
  83. var peers []wgtypes.PeerConfig
  84. var peeraddr = net.IPNet{
  85. IP: net.ParseIP(client.ServerPrivateAddress),
  86. Mask: net.CIDRMask(32, 32),
  87. }
  88. var allowedips []net.IPNet
  89. allowedips = append(allowedips, peeraddr)
  90. net.ParseIP(client.ServerPublicEndpoint)
  91. peer := wgtypes.PeerConfig{
  92. PublicKey: serverkey,
  93. Endpoint: &net.UDPAddr{
  94. IP: net.ParseIP(client.ServerPublicEndpoint),
  95. Port: serverport,
  96. },
  97. ReplaceAllowedIPs: true,
  98. AllowedIPs: allowedips,
  99. }
  100. peers = append(peers, peer)
  101. conf := wgtypes.Config{
  102. PrivateKey: &key,
  103. ReplacePeers: true,
  104. Peers: peers,
  105. }
  106. _, err = wgclient.Device(ifacename)
  107. if err != nil {
  108. if os.IsNotExist(err) {
  109. log.Println("Device does not exist: ")
  110. log.Println(err)
  111. } else {
  112. return err
  113. }
  114. }
  115. err = wgclient.ConfigureDevice(ifacename, conf)
  116. if err != nil {
  117. if os.IsNotExist(err) {
  118. log.Println("Device does not exist: ")
  119. log.Println(err)
  120. } else {
  121. log.Printf("This is inconvenient: %v", err)
  122. }
  123. }
  124. _, err = local.RunCmd("ip link set up dev " + ifacename)
  125. _, err = local.RunCmd("ip link set down dev " + ifacename)
  126. if err != nil {
  127. return err
  128. }
  129. return err
  130. }
  131. func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error {
  132. ipExec, err := exec.LookPath("ip")
  133. if err != nil {
  134. return err
  135. }
  136. key, err := wgtypes.ParseKey(privkey)
  137. if err != nil {
  138. return err
  139. }
  140. wgclient, err := wgctrl.New()
  141. if err != nil {
  142. return err
  143. }
  144. modcfg, err := config.ReadConfig(node.Network)
  145. if err != nil {
  146. return err
  147. }
  148. nodecfg := modcfg.Node
  149. servercfg := modcfg.Server
  150. if err != nil {
  151. log.Fatalf("failed to open client: %v", err)
  152. }
  153. defer wgclient.Close()
  154. ifacename := node.Interface
  155. if nodecfg.Interface != "" {
  156. ifacename = nodecfg.Interface
  157. } else if node.Interface != "" {
  158. ifacename = node.Interface
  159. } else {
  160. log.Fatal("no interface to configure")
  161. }
  162. if node.Address == "" {
  163. log.Fatal("no address to configure")
  164. }
  165. nameserver := servercfg.CoreDNSAddr
  166. network := node.Network
  167. if nodecfg.Network != "" {
  168. network = nodecfg.Network
  169. } else if node.Network != "" {
  170. network = node.Network
  171. }
  172. _, delErr := local.RunCmd("ip link delete dev " + ifacename)
  173. _, addLinkErr := local.RunCmd(ipExec + " link add dev " + ifacename + " type wireguard")
  174. _, addErr := local.RunCmd(ipExec + " address add dev " + ifacename + " " + node.Address + "/24")
  175. if delErr != nil {
  176. log.Println(delErr)
  177. }
  178. if addLinkErr != nil {
  179. log.Println(addLinkErr)
  180. }
  181. if addErr != nil {
  182. log.Println(addErr)
  183. }
  184. var nodeport int
  185. nodeport = int(node.ListenPort)
  186. conf := wgtypes.Config{}
  187. if nodecfg.UDPHolePunch == "yes" && nodecfg.Name != "netmaker" {
  188. conf = wgtypes.Config{
  189. PrivateKey: &key,
  190. ReplacePeers: true,
  191. Peers: peers,
  192. }
  193. } else {
  194. conf = wgtypes.Config{
  195. PrivateKey: &key,
  196. ListenPort: &nodeport,
  197. ReplacePeers: true,
  198. Peers: peers,
  199. }
  200. }
  201. _, err = wgclient.Device(ifacename)
  202. if err != nil {
  203. if os.IsNotExist(err) {
  204. fmt.Println("Device does not exist: ")
  205. fmt.Println(err)
  206. } else {
  207. log.Fatalf("Unknown config error: %v", err)
  208. }
  209. }
  210. err = wgclient.ConfigureDevice(ifacename, conf)
  211. if err != nil {
  212. if os.IsNotExist(err) {
  213. fmt.Println("Device does not exist: ")
  214. fmt.Println(err)
  215. } else {
  216. fmt.Printf("This is inconvenient: %v", err)
  217. }
  218. }
  219. //=========DNS Setup==========\\
  220. if nodecfg.DNSOn == "yes" {
  221. _ = local.UpdateDNS(ifacename, network, nameserver)
  222. }
  223. //=========End DNS Setup=======\\
  224. cmdIPLinkUp := &exec.Cmd{
  225. Path: ipExec,
  226. Args: []string{ipExec, "link", "set", "up", "dev", ifacename},
  227. Stdout: os.Stdout,
  228. Stderr: os.Stdout,
  229. }
  230. cmdIPLinkDown := &exec.Cmd{
  231. Path: ipExec,
  232. Args: []string{ipExec, "link", "set", "down", "dev", ifacename},
  233. Stdout: os.Stdout,
  234. Stderr: os.Stdout,
  235. }
  236. err = cmdIPLinkDown.Run()
  237. if nodecfg.PostDown != "" {
  238. runcmds := strings.Split(nodecfg.PostDown, "; ")
  239. err = local.RunCmds(runcmds)
  240. if err != nil {
  241. fmt.Println("Error encountered running PostDown: " + err.Error())
  242. }
  243. }
  244. err = cmdIPLinkUp.Run()
  245. if err != nil {
  246. return err
  247. }
  248. if nodecfg.PostUp != "" {
  249. runcmds := strings.Split(nodecfg.PostUp, "; ")
  250. err = local.RunCmds(runcmds)
  251. if err != nil {
  252. fmt.Println("Error encountered running PostUp: " + err.Error())
  253. }
  254. }
  255. if hasGateway {
  256. for _, gateway := range gateways {
  257. out, err := local.RunCmd(ipExec + " -4 route add " + gateway + " dev " + ifacename)
  258. fmt.Println(string(out))
  259. if err != nil {
  260. fmt.Println("Error encountered adding gateway: " + err.Error())
  261. }
  262. }
  263. }
  264. if node.Address6 != "" && node.IsDualStack == "yes" {
  265. fmt.Println("Adding address: " + node.Address6)
  266. out, err := local.RunCmd(ipExec + " address add dev " + ifacename + " " + node.Address6 + "/64")
  267. if err != nil {
  268. fmt.Println(out)
  269. fmt.Println("Error encountered adding ipv6: " + err.Error())
  270. }
  271. }
  272. return err
  273. }
  274. func SetWGKeyConfig(network string, serveraddr string) error {
  275. ctx := context.Background()
  276. var header metadata.MD
  277. cfg, err := config.ReadConfig(network)
  278. if err != nil {
  279. return err
  280. }
  281. var wcclient nodepb.NodeServiceClient
  282. var requestOpts grpc.DialOption
  283. requestOpts = grpc.WithInsecure()
  284. if cfg.Server.GRPCSSL == "on" {
  285. h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
  286. requestOpts = grpc.WithTransportCredentials(h2creds)
  287. }
  288. conn, err := grpc.Dial(serveraddr, requestOpts)
  289. if err != nil {
  290. fmt.Printf("Cant dial GRPC server: %v", err)
  291. return err
  292. }
  293. wcclient = nodepb.NewNodeServiceClient(conn)
  294. ctx, err = auth.SetJWT(wcclient, network)
  295. if err != nil {
  296. fmt.Printf("Failed to authenticate: %v", err)
  297. return err
  298. }
  299. node := config.GetNode(network)
  300. privatekey, err := wgtypes.GeneratePrivateKey()
  301. if err != nil {
  302. return err
  303. }
  304. privkeystring := privatekey.String()
  305. publickey := privatekey.PublicKey()
  306. node.PublicKey = publickey.String()
  307. err = StorePrivKey(privkeystring, network)
  308. if err != nil {
  309. return err
  310. }
  311. if node.Action == models.NODE_UPDATE_KEY {
  312. node.Action = models.NODE_NOOP
  313. }
  314. err = config.ModConfig(&node)
  315. if err != nil {
  316. return err
  317. }
  318. postnode := config.GetNode(network)
  319. nodeData, err := json.Marshal(&postnode)
  320. if err != nil {
  321. return err
  322. }
  323. req := &nodepb.Object{
  324. Data: string(nodeData),
  325. Type: nodepb.NODE_TYPE,
  326. }
  327. _, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
  328. if err != nil {
  329. return err
  330. }
  331. err = SetWGConfig(network, false)
  332. if err != nil {
  333. return err
  334. }
  335. return err
  336. }
  337. func SetWGConfig(network string, peerupdate bool) error {
  338. cfg, err := config.ReadConfig(network)
  339. if err != nil {
  340. return err
  341. }
  342. servercfg := cfg.Server
  343. nodecfg := cfg.Node
  344. node := config.GetNode(network)
  345. peers, hasGateway, gateways, err := server.GetPeers(node.MacAddress, nodecfg.Network, servercfg.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes")
  346. if err != nil {
  347. return err
  348. }
  349. privkey, err := RetrievePrivKey(network)
  350. if err != nil {
  351. return err
  352. }
  353. if peerupdate {
  354. SetPeers(node.Interface, node.PersistentKeepalive, peers)
  355. } else {
  356. err = InitWireguard(&node, privkey, peers, hasGateway, gateways)
  357. }
  358. if err != nil {
  359. return err
  360. }
  361. return err
  362. }
  363. func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) {
  364. client, err := wgctrl.New()
  365. if err != nil {
  366. log.Println("failed to start wgctrl")
  367. return
  368. }
  369. device, err := client.Device(iface)
  370. if err != nil {
  371. log.Println("failed to parse interface")
  372. return
  373. }
  374. for _, peer := range peers {
  375. for _, currentPeer := range device.Peers {
  376. if currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() &&
  377. currentPeer.PublicKey.String() == peer.PublicKey.String() {
  378. _, err := local.RunCmd("wg set " + iface + " peer " + currentPeer.PublicKey.String() + " delete")
  379. if err != nil {
  380. log.Println("error setting peer", peer.Endpoint.String())
  381. }
  382. }
  383. }
  384. udpendpoint := peer.Endpoint.IP.String() + ":" + peer.Endpoint.IP.String()
  385. var allowedips string
  386. var iparr []string
  387. for _, ipaddr := range peer.AllowedIPs {
  388. iparr = append(iparr, ipaddr.String())
  389. }
  390. allowedips = strings.Join(iparr, ",")
  391. _, err = local.RunCmd("wg set " + iface + " peer " + peer.PublicKey.String() +
  392. " endpoint " + udpendpoint +
  393. " persistent-keepalive " + string(keepalive) +
  394. " allowed-ips " + allowedips)
  395. if err != nil {
  396. log.Println("error setting peer", peer.Endpoint.String())
  397. }
  398. }
  399. }
  400. func StorePrivKey(key string, network string) error {
  401. d1 := []byte(key)
  402. err := ioutil.WriteFile("/etc/netclient/wgkey-"+network, d1, 0644)
  403. return err
  404. }
  405. func RetrievePrivKey(network string) (string, error) {
  406. dat, err := ioutil.ReadFile("/etc/netclient/wgkey-" + network)
  407. return string(dat), err
  408. }