gateway.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. package logic
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "slices"
  7. "sort"
  8. "time"
  9. "github.com/google/uuid"
  10. "github.com/gravitl/netmaker/database"
  11. "github.com/gravitl/netmaker/logger"
  12. "github.com/gravitl/netmaker/models"
  13. "github.com/gravitl/netmaker/servercfg"
  14. "golang.org/x/exp/slog"
  15. )
  16. var (
  17. IPv4Network = "0.0.0.0/0"
  18. IPv6Network = "::/0"
  19. )
  20. // IsInternetGw - checks if node is acting as internet gw
  21. func IsInternetGw(node models.Node) bool {
  22. return node.IsInternetGateway
  23. }
  24. // GetInternetGateways - gets all the nodes that are internet gateways
  25. func GetInternetGateways() ([]models.Node, error) {
  26. nodes, err := GetAllNodes()
  27. if err != nil {
  28. return nil, err
  29. }
  30. igs := make([]models.Node, 0)
  31. for _, node := range nodes {
  32. if node.IsInternetGateway {
  33. igs = append(igs, node)
  34. }
  35. }
  36. return igs, nil
  37. }
  38. // GetAllIngresses - gets all the nodes that are ingresses
  39. func GetAllIngresses() ([]models.Node, error) {
  40. nodes, err := GetAllNodes()
  41. if err != nil {
  42. return nil, err
  43. }
  44. ingresses := make([]models.Node, 0)
  45. for _, node := range nodes {
  46. if node.IsIngressGateway {
  47. ingresses = append(ingresses, node)
  48. }
  49. }
  50. return ingresses, nil
  51. }
  52. // GetAllEgresses - gets all the nodes that are egresses
  53. func GetAllEgresses() ([]models.Node, error) {
  54. nodes, err := GetAllNodes()
  55. if err != nil {
  56. return nil, err
  57. }
  58. egresses := make([]models.Node, 0)
  59. for _, node := range nodes {
  60. if node.EgressDetails.IsEgressGateway {
  61. egresses = append(egresses, node)
  62. }
  63. }
  64. return egresses, nil
  65. }
  66. // CreateEgressGateway - creates an egress gateway
  67. func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, error) {
  68. node, err := GetNodeByID(gateway.NodeID)
  69. if err != nil {
  70. return models.Node{}, err
  71. }
  72. host, err := GetHost(node.HostID.String())
  73. if err != nil {
  74. return models.Node{}, err
  75. }
  76. if host.OS != "linux" { // support for other OS to be added
  77. return models.Node{}, errors.New(host.OS + " is unsupported for egress gateways")
  78. }
  79. if host.FirewallInUse == models.FIREWALL_NONE {
  80. return models.Node{}, errors.New("please install iptables or nftables on the device")
  81. }
  82. if len(gateway.RangesWithMetric) == 0 && len(gateway.Ranges) > 0 {
  83. for _, rangeI := range gateway.Ranges {
  84. gateway.RangesWithMetric = append(gateway.RangesWithMetric, models.EgressRangeMetric{
  85. Network: rangeI,
  86. RouteMetric: 256,
  87. })
  88. }
  89. }
  90. for i := len(gateway.Ranges) - 1; i >= 0; i-- {
  91. // check if internet gateway IPv4
  92. if gateway.Ranges[i] == "0.0.0.0/0" || gateway.Ranges[i] == "::/0" {
  93. // remove inet range
  94. gateway.Ranges = append(gateway.Ranges[:i], gateway.Ranges[i+1:]...)
  95. continue
  96. }
  97. normalized, err := NormalizeCIDR(gateway.Ranges[i])
  98. if err != nil {
  99. return models.Node{}, err
  100. }
  101. gateway.Ranges[i] = normalized
  102. }
  103. rangesWithMetric := []string{}
  104. for i := len(gateway.RangesWithMetric) - 1; i >= 0; i-- {
  105. if gateway.RangesWithMetric[i].Network == "0.0.0.0/0" || gateway.RangesWithMetric[i].Network == "::/0" {
  106. // remove inet range
  107. gateway.RangesWithMetric = append(gateway.RangesWithMetric[:i], gateway.RangesWithMetric[i+1:]...)
  108. continue
  109. }
  110. normalized, err := NormalizeCIDR(gateway.RangesWithMetric[i].Network)
  111. if err != nil {
  112. return models.Node{}, err
  113. }
  114. gateway.RangesWithMetric[i].Network = normalized
  115. rangesWithMetric = append(rangesWithMetric, gateway.RangesWithMetric[i].Network)
  116. if gateway.RangesWithMetric[i].RouteMetric <= 0 || gateway.RangesWithMetric[i].RouteMetric > 999 {
  117. gateway.RangesWithMetric[i].RouteMetric = 256
  118. }
  119. }
  120. sort.Strings(gateway.Ranges)
  121. sort.Strings(rangesWithMetric)
  122. if !slices.Equal(gateway.Ranges, rangesWithMetric) {
  123. return models.Node{}, errors.New("invalid ranges")
  124. }
  125. if gateway.NatEnabled == "" {
  126. gateway.NatEnabled = "yes"
  127. }
  128. err = ValidateEgressGateway(gateway)
  129. if err != nil {
  130. return models.Node{}, err
  131. }
  132. if gateway.Ranges == nil {
  133. gateway.Ranges = make([]string, 0)
  134. }
  135. node.EgressDetails.IsEgressGateway = true
  136. node.EgressDetails.EgressGatewayRanges = gateway.Ranges
  137. node.EgressDetails.EgressGatewayNatEnabled = models.ParseBool(gateway.NatEnabled)
  138. node.EgressDetails.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway
  139. node.SetLastModified()
  140. if err = UpsertNode(&node); err != nil {
  141. return models.Node{}, err
  142. }
  143. return node, nil
  144. }
  145. // ValidateEgressGateway - validates the egress gateway model
  146. func ValidateEgressGateway(gateway models.EgressGatewayRequest) error {
  147. return nil
  148. }
  149. // DeleteEgressGateway - deletes egress from node
  150. func DeleteEgressGateway(network, nodeid string) (models.Node, error) {
  151. node, err := GetNodeByID(nodeid)
  152. if err != nil {
  153. return models.Node{}, err
  154. }
  155. node.EgressDetails.IsEgressGateway = false
  156. node.EgressDetails.EgressGatewayRanges = []string{}
  157. node.EgressDetails.EgressGatewayRequest = models.EgressGatewayRequest{} // remove preserved request as the egress gateway is gone
  158. node.SetLastModified()
  159. if err = UpsertNode(&node); err != nil {
  160. return models.Node{}, err
  161. }
  162. return node, nil
  163. }
  164. // CreateIngressGateway - creates an ingress gateway
  165. func CreateIngressGateway(netid string, nodeid string, ingress models.IngressRequest) (models.Node, error) {
  166. node, err := GetNodeByID(nodeid)
  167. if err != nil {
  168. return models.Node{}, err
  169. }
  170. if node.IsRelayed {
  171. return models.Node{}, errors.New("gateway cannot be created on a relayed node")
  172. }
  173. host, err := GetHost(node.HostID.String())
  174. if err != nil {
  175. return models.Node{}, err
  176. }
  177. if host.OS != "linux" {
  178. return models.Node{}, errors.New("gateway can only be created on linux based node")
  179. }
  180. network, err := GetParentNetwork(netid)
  181. if err != nil {
  182. return models.Node{}, err
  183. }
  184. node.IsIngressGateway = true
  185. node.IsGw = true
  186. node.IsInternetGateway = ingress.IsInternetGateway
  187. node.IngressGatewayRange = network.AddressRange
  188. node.IngressGatewayRange6 = network.AddressRange6
  189. node.IngressDNS = ingress.ExtclientDNS
  190. if node.IsInternetGateway && node.IngressDNS == "" {
  191. node.IngressDNS = "1.1.1.1"
  192. }
  193. node.IngressPersistentKeepalive = 20
  194. if ingress.PersistentKeepalive != 0 {
  195. node.IngressPersistentKeepalive = ingress.PersistentKeepalive
  196. }
  197. node.IngressMTU = 1420
  198. if ingress.MTU != 0 {
  199. node.IngressMTU = ingress.MTU
  200. }
  201. if servercfg.IsPro {
  202. if _, exists := FailOverExists(node.Network); exists {
  203. ResetFailedOverPeer(&node)
  204. }
  205. }
  206. node.SetLastModified()
  207. node.Metadata = ingress.Metadata
  208. if node.Metadata == "" {
  209. node.Metadata = "This host can be used for remote access"
  210. }
  211. if node.Tags == nil {
  212. node.Tags = make(map[models.TagID]struct{})
  213. }
  214. node.Tags[models.TagID(fmt.Sprintf("%s.%s", netid, models.GwTagName))] = struct{}{}
  215. err = UpsertNode(&node)
  216. if err != nil {
  217. return models.Node{}, err
  218. }
  219. err = SetNetworkNodesLastModified(netid)
  220. return node, err
  221. }
  222. // GetIngressGwUsers - lists the users having to access to ingressGW
  223. func GetIngressGwUsers(node models.Node) (models.IngressGwUsers, error) {
  224. gwUsers := models.IngressGwUsers{
  225. NodeID: node.ID.String(),
  226. Network: node.Network,
  227. }
  228. users, err := GetUsers()
  229. if err != nil {
  230. return gwUsers, err
  231. }
  232. for _, user := range users {
  233. if !user.IsAdmin && !user.IsSuperAdmin {
  234. gwUsers.Users = append(gwUsers.Users, user)
  235. }
  236. }
  237. return gwUsers, nil
  238. }
  239. // DeleteIngressGateway - deletes an ingress gateway
  240. func DeleteIngressGateway(nodeid string) (models.Node, []models.ExtClient, error) {
  241. removedClients := []models.ExtClient{}
  242. node, err := GetNodeByID(nodeid)
  243. if err != nil {
  244. return models.Node{}, removedClients, err
  245. }
  246. clients, err := GetExtClientsByID(nodeid, node.Network)
  247. if err != nil && !database.IsEmptyRecord(err) {
  248. return models.Node{}, removedClients, err
  249. }
  250. removedClients = clients
  251. // delete ext clients belonging to ingress gateway
  252. if err = DeleteGatewayExtClients(node.ID.String(), node.Network); err != nil {
  253. return models.Node{}, removedClients, err
  254. }
  255. logger.Log(3, "deleting ingress gateway")
  256. node.LastModified = time.Now().UTC()
  257. node.IsIngressGateway = false
  258. if !servercfg.IsPro {
  259. node.IsInternetGateway = false
  260. }
  261. delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName)))
  262. node.IngressGatewayRange = ""
  263. node.Metadata = ""
  264. err = UpsertNode(&node)
  265. if err != nil {
  266. return models.Node{}, removedClients, err
  267. }
  268. err = SetNetworkNodesLastModified(node.Network)
  269. return node, removedClients, err
  270. }
  271. // DeleteGatewayExtClients - deletes ext clients based on gateway (mac) of ingress node and network
  272. func DeleteGatewayExtClients(gatewayID string, networkName string) error {
  273. currentExtClients, err := GetNetworkExtClients(networkName)
  274. if database.IsEmptyRecord(err) {
  275. return nil
  276. }
  277. if err != nil {
  278. return err
  279. }
  280. for _, extClient := range currentExtClients {
  281. if extClient.IngressGatewayID == gatewayID {
  282. if err = DeleteExtClient(networkName, extClient.ClientID); err != nil {
  283. logger.Log(1, "failed to remove ext client", extClient.ClientID)
  284. continue
  285. }
  286. }
  287. }
  288. return nil
  289. }
  290. // IsUserAllowedAccessToExtClient - checks if user has permission to access extclient
  291. func IsUserAllowedAccessToExtClient(username string, client models.ExtClient) bool {
  292. if username == MasterUser {
  293. return true
  294. }
  295. user, err := GetUser(username)
  296. if err != nil {
  297. return false
  298. }
  299. if user.UserName != client.OwnerID {
  300. return false
  301. }
  302. return true
  303. }
  304. func ValidateInetGwReq(inetNode models.Node, req models.InetNodeReq, update bool) error {
  305. inetHost, err := GetHost(inetNode.HostID.String())
  306. if err != nil {
  307. return err
  308. }
  309. if inetHost.FirewallInUse == models.FIREWALL_NONE {
  310. return errors.New("iptables or nftables needs to be installed")
  311. }
  312. if inetNode.InternetGwID != "" {
  313. return fmt.Errorf("node %s is using a internet gateway already", inetHost.Name)
  314. }
  315. if inetNode.IsRelayed {
  316. return fmt.Errorf("node %s is being relayed", inetHost.Name)
  317. }
  318. for _, clientNodeID := range req.InetNodeClientIDs {
  319. clientNode, err := GetNodeByID(clientNodeID)
  320. if err != nil {
  321. return err
  322. }
  323. if clientNode.IsFailOver {
  324. return errors.New("failover node cannot be set to use internet gateway")
  325. }
  326. clientHost, err := GetHost(clientNode.HostID.String())
  327. if err != nil {
  328. return err
  329. }
  330. if clientHost.IsDefault {
  331. return errors.New("default host cannot be set to use internet gateway")
  332. }
  333. if clientHost.OS != models.OS_Types.Linux && clientHost.OS != models.OS_Types.Windows {
  334. return errors.New("can only attach linux or windows machine to a internet gateway")
  335. }
  336. if clientNode.IsInternetGateway {
  337. return fmt.Errorf("node %s acting as internet gateway cannot use another internet gateway", clientHost.Name)
  338. }
  339. if update {
  340. if clientNode.InternetGwID != "" && clientNode.InternetGwID != inetNode.ID.String() {
  341. return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
  342. }
  343. } else {
  344. if clientNode.InternetGwID != "" {
  345. return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
  346. }
  347. }
  348. if clientNode.FailedOverBy != uuid.Nil {
  349. ResetFailedOverPeer(&clientNode)
  350. }
  351. if clientNode.IsRelayed && clientNode.RelayedBy != inetNode.ID.String() {
  352. return fmt.Errorf("node %s is being relayed", clientHost.Name)
  353. }
  354. for _, nodeID := range clientHost.Nodes {
  355. node, err := GetNodeByID(nodeID)
  356. if err != nil {
  357. continue
  358. }
  359. if node.InternetGwID != "" && node.InternetGwID != inetNode.ID.String() {
  360. return errors.New("nodes on same host cannot use different internet gateway")
  361. }
  362. }
  363. }
  364. return nil
  365. }
  366. // SetInternetGw - sets the node as internet gw based on flag bool
  367. func SetInternetGw(node *models.Node, req models.InetNodeReq) {
  368. node.IsInternetGateway = true
  369. node.InetNodeReq = req
  370. for _, clientNodeID := range req.InetNodeClientIDs {
  371. clientNode, err := GetNodeByID(clientNodeID)
  372. if err != nil {
  373. continue
  374. }
  375. clientNode.InternetGwID = node.ID.String()
  376. UpsertNode(&clientNode)
  377. }
  378. }
  379. func UnsetInternetGw(node *models.Node) {
  380. nodes, err := GetNetworkNodes(node.Network)
  381. if err != nil {
  382. slog.Error("failed to get network nodes", "network", node.Network, "error", err)
  383. return
  384. }
  385. for _, clientNode := range nodes {
  386. if node.ID.String() == clientNode.InternetGwID {
  387. clientNode.InternetGwID = ""
  388. UpsertNode(&clientNode)
  389. }
  390. }
  391. node.IsInternetGateway = false
  392. node.InetNodeReq = models.InetNodeReq{}
  393. }
  394. func SetDefaultGwForRelayedUpdate(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
  395. if relay.InternetGwID != "" {
  396. relayedHost, err := GetHost(relayed.HostID.String())
  397. if err != nil {
  398. return peerUpdate
  399. }
  400. peerUpdate.ChangeDefaultGw = true
  401. peerUpdate.DefaultGwIp = relay.Address.IP
  402. if peerUpdate.DefaultGwIp == nil || relayedHost.EndpointIP == nil {
  403. peerUpdate.DefaultGwIp = relay.Address6.IP
  404. }
  405. }
  406. return peerUpdate
  407. }
  408. func SetDefaultGw(node models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
  409. if node.InternetGwID != "" {
  410. inetNode, err := GetNodeByID(node.InternetGwID)
  411. if err != nil {
  412. return peerUpdate
  413. }
  414. host, err := GetHost(node.HostID.String())
  415. if err != nil {
  416. return peerUpdate
  417. }
  418. peerUpdate.ChangeDefaultGw = true
  419. peerUpdate.DefaultGwIp = inetNode.Address.IP
  420. if peerUpdate.DefaultGwIp == nil || host.EndpointIP == nil {
  421. peerUpdate.DefaultGwIp = inetNode.Address6.IP
  422. }
  423. }
  424. return peerUpdate
  425. }
  426. // GetAllowedIpForInetNodeClient - get inet cidr for node using a inet gw
  427. func GetAllowedIpForInetNodeClient(node, peer *models.Node) []net.IPNet {
  428. var allowedips = []net.IPNet{}
  429. if peer.Address.IP != nil {
  430. _, ipnet, _ := net.ParseCIDR(IPv4Network)
  431. allowedips = append(allowedips, *ipnet)
  432. }
  433. if peer.Address6.IP != nil {
  434. _, ipnet, _ := net.ParseCIDR(IPv6Network)
  435. allowedips = append(allowedips, *ipnet)
  436. }
  437. return allowedips
  438. }