Forráskód Böngészése

NET-1784: Adv Acl Rules (#3239)

* define direction on acl req

* define protocol types and rule model

* get rules for node

* fetch acl rule for a node

* redine acl firewall model

* add json tags

* update port,protocol, and direction

* add json tags to acl options

* convert protocol to string

* simplify acl map

* add json tags to acl rules

* add networks to fw update

* add acls rules

* NET-1784: add allow all field

* add allow all field on fw udpate

* remove debug logs

* fix port and protocol types

* migrate default acl policies

* define constants for service types

* add adv options for user rules on ingress gw

* debug log

* allow whole network

* add static nodes to acl rules

* replace peers on acl updates

* initiliase rule map

* add user acl rules on target node

* revert acl check on extclient

* handle static node rules on ingress gw

* update multiple policies for users

* check allowed direction

* remove debug logs
Abhishek K 9 hónapja
szülő
commit
f124b10c35
12 módosított fájl, 707 hozzáadás és 118 törlés
  1. 71 9
      controllers/acls.go
  2. 345 28
      logic/acls.go
  3. 156 69
      logic/extpeers.go
  4. 25 1
      logic/nodes.go
  5. 17 5
      logic/peers.go
  6. 1 1
      logic/tags.go
  7. 19 0
      logic/user_mgmt.go
  8. 1 0
      migrate/migrate.go
  9. 47 0
      models/acl.go
  10. 8 3
      models/mqtt.go
  11. 13 0
      models/node.go
  12. 4 2
      pro/logic/status.go

+ 71 - 9
controllers/acls.go

@@ -52,6 +52,73 @@ func aclPolicyTypes(w http.ResponseWriter, r *http.Request) {
 			// models.NetmakerIPAclID,
 			// models.NetmakerSubNetRangeAClID,
 		},
+		ProtocolTypes: []models.ProtocolType{
+			{
+				Name: models.Http,
+				AllowedProtocols: []models.Protocol{
+					models.TCP,
+				},
+				PortRange: "80",
+			},
+			{
+				Name: models.Https,
+				AllowedProtocols: []models.Protocol{
+					models.TCP,
+				},
+				PortRange: "443",
+			},
+			// {
+			// 	Name: "MySQL",
+			// 	AllowedProtocols: []models.Protocol{
+			// 		models.TCP,
+			// 	},
+			// 	PortRange: "3306",
+			// },
+			// {
+			// 	Name: "DNS TCP",
+			// 	AllowedProtocols: []models.Protocol{
+			// 		models.TCP,
+			// 	},
+			// 	PortRange: "53",
+			// },
+			// {
+			// 	Name: "DNS UDP",
+			// 	AllowedProtocols: []models.Protocol{
+			// 		models.UDP,
+			// 	},
+			// 	PortRange: "53",
+			// },
+			{
+				Name: models.AllTCP,
+				AllowedProtocols: []models.Protocol{
+					models.TCP,
+				},
+				PortRange: "All ports",
+			},
+			{
+				Name: models.AllUDP,
+				AllowedProtocols: []models.Protocol{
+					models.UDP,
+				},
+				PortRange: "All ports",
+			},
+			{
+				Name: models.ICMPService,
+				AllowedProtocols: []models.Protocol{
+					models.ICMP,
+				},
+				PortRange: "",
+			},
+			{
+				Name: models.Custom,
+				AllowedProtocols: []models.Protocol{
+					models.UDP,
+					models.TCP,
+				},
+				PortRange:        "All ports",
+				AllowPortSetting: true,
+			},
+		},
 	}
 	logic.ReturnSuccessResponseWithJson(w, r, resp, "fetched acls types")
 }
@@ -69,7 +136,7 @@ func aclDebug(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
-	allowed := logic.IsNodeAllowedToCommunicate(node, peer, true)
+	allowed, _ := logic.IsNodeAllowedToCommunicate(node, peer, true)
 	logic.ReturnSuccessResponseWithJson(w, r, allowed, "fetched all acls in the network ")
 }
 
@@ -132,11 +199,6 @@ func createAcl(w http.ResponseWriter, r *http.Request) {
 	acl.CreatedBy = user.UserName
 	acl.CreatedAt = time.Now().UTC()
 	acl.Default = false
-	if acl.RuleType == models.DevicePolicy {
-		acl.AllowedDirection = models.TrafficDirectionBi
-	} else {
-		acl.AllowedDirection = models.TrafficDirectionUni
-	}
 	// validate create acl policy
 	if !logic.IsAclPolicyValid(acl) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("invalid policy"), "badrequest"))
@@ -152,7 +214,7 @@ func createAcl(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
-	go mq.PublishPeerUpdate(false)
+	go mq.PublishPeerUpdate(true)
 	logic.ReturnSuccessResponseWithJson(w, r, acl, "created acl successfully")
 }
 
@@ -194,7 +256,7 @@ func updateAcl(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
-	go mq.PublishPeerUpdate(false)
+	go mq.PublishPeerUpdate(true)
 	logic.ReturnSuccessResponse(w, r, "updated acl "+acl.Name)
 }
 
@@ -225,6 +287,6 @@ func deleteAcl(w http.ResponseWriter, r *http.Request) {
 			logic.FormatError(errors.New("cannot delete default policy"), "internal"))
 		return
 	}
-	go mq.PublishPeerUpdate(false)
+	go mq.PublishPeerUpdate(true)
 	logic.ReturnSuccessResponse(w, r, "deleted acl "+acl.Name)
 }

+ 345 - 28
logic/acls.go

@@ -18,6 +18,39 @@ var (
 	aclCacheMap   = make(map[string]models.Acl)
 )
 
+func MigrateDefaulAclPolicies(netID models.NetworkID) {
+	if netID.String() == "" {
+		return
+	}
+	acl, err := GetAcl(fmt.Sprintf("%s.%s", netID, "all-nodes"))
+	if err == nil {
+		//if acl.Proto.String() == "" {
+		acl.Proto = models.ALL
+		acl.ServiceType = models.Custom
+		acl.Port = []string{}
+		UpsertAcl(acl)
+		//}
+	}
+	acl, err = GetAcl(fmt.Sprintf("%s.%s", netID, "all-users"))
+	if err == nil {
+		//if acl.Proto.String() == "" {
+		acl.Proto = models.ALL
+		acl.ServiceType = models.Custom
+		acl.Port = []string{}
+		UpsertAcl(acl)
+		//}
+	}
+	acl, err = GetAcl(fmt.Sprintf("%s.%s", netID, "all-remote-access-gws"))
+	if err == nil {
+		//if acl.Proto.String() == "" {
+		acl.Proto = models.ALL
+		acl.ServiceType = models.Custom
+		acl.Port = []string{}
+		UpsertAcl(acl)
+		//}
+	}
+}
+
 // CreateDefaultAclNetworkPolicies - create default acl network policies
 func CreateDefaultAclNetworkPolicies(netID models.NetworkID) {
 	if netID.String() == "" {
@@ -31,6 +64,8 @@ func CreateDefaultAclNetworkPolicies(netID models.NetworkID) {
 			MetaData:  "This Policy allows all nodes in the network to communicate with each other",
 			Default:   true,
 			NetworkID: netID,
+			Proto:     models.ALL,
+			Port:      []string{},
 			RuleType:  models.DevicePolicy,
 			Src: []models.AclPolicyTag{
 				{
@@ -56,6 +91,8 @@ func CreateDefaultAclNetworkPolicies(netID models.NetworkID) {
 			Name:      "All Users",
 			MetaData:  "This policy gives access to everything in the network for an user",
 			NetworkID: netID,
+			Proto:     models.ALL,
+			Port:      []string{},
 			RuleType:  models.UserPolicy,
 			Src: []models.AclPolicyTag{
 				{
@@ -81,6 +118,8 @@ func CreateDefaultAclNetworkPolicies(netID models.NetworkID) {
 			Default:   true,
 			Name:      "All Remote Access Gateways",
 			NetworkID: netID,
+			Proto:     models.ALL,
+			Port:      []string{},
 			RuleType:  models.DevicePolicy,
 			Src: []models.AclPolicyTag{
 				{
@@ -202,7 +241,10 @@ func IsAclExists(aclID string) bool {
 // IsAclPolicyValid - validates if acl policy is valid
 func IsAclPolicyValid(acl models.Acl) bool {
 	//check if src and dst are valid
-
+	if acl.AllowedDirection != models.TrafficDirectionBi &&
+		acl.AllowedDirection != models.TrafficDirectionUni {
+		return false
+	}
 	switch acl.RuleType {
 	case models.UserPolicy:
 		// src list should only contain users
@@ -298,6 +340,10 @@ func UpdateAcl(newAcl, acl models.Acl) error {
 		acl.Name = newAcl.Name
 		acl.Src = newAcl.Src
 		acl.Dst = newAcl.Dst
+		acl.AllowedDirection = newAcl.AllowedDirection
+		acl.Port = newAcl.Port
+		acl.Proto = newAcl.Proto
+		acl.ServiceType = newAcl.ServiceType
 	}
 	acl.Enabled = newAcl.Enabled
 	d, err := json.Marshal(acl)
@@ -382,7 +428,6 @@ func ListAcls() (acls []models.Acl) {
 	if err != nil && !database.IsEmptyRecord(err) {
 		return []models.Acl{}
 	}
-
 	for _, dataI := range data {
 		acl := models.Acl{}
 		err := json.Unmarshal([]byte(dataI), &acl)
@@ -463,6 +508,18 @@ func listDevicePolicies(netID models.NetworkID) []models.Acl {
 	return deviceAcls
 }
 
+// listUserPolicies - lists all user policies in a network
+func listUserPolicies(netID models.NetworkID) []models.Acl {
+	allAcls := ListAcls()
+	deviceAcls := []models.Acl{}
+	for _, acl := range allAcls {
+		if acl.NetworkID == netID && acl.RuleType == models.UserPolicy {
+			deviceAcls = append(deviceAcls, acl)
+		}
+	}
+	return deviceAcls
+}
+
 // ListAcls - lists all acl policies
 func ListAclsByNetwork(netID models.NetworkID) ([]models.Acl, error) {
 
@@ -485,19 +542,19 @@ func convAclTagToValueMap(acltags []models.AclPolicyTag) map[string]struct{} {
 }
 
 // IsUserAllowedToCommunicate - check if user is allowed to communicate with peer
-func IsUserAllowedToCommunicate(userName string, peer models.Node) bool {
+func IsUserAllowedToCommunicate(userName string, peer models.Node) (bool, []models.Acl) {
 	if peer.IsStatic {
 		peer = peer.StaticNode.ConvertToStaticNode()
 	}
 	acl, _ := GetDefaultPolicy(models.NetworkID(peer.Network), models.UserPolicy)
 	if acl.Enabled {
-		return true
+		return true, []models.Acl{acl}
 	}
 	user, err := GetUser(userName)
 	if err != nil {
-		return false
+		return false, []models.Acl{}
 	}
-
+	allowedPolicies := []models.Acl{}
 	policies := listPoliciesOfUser(*user, models.NetworkID(peer.Network))
 	for _, policy := range policies {
 		if !policy.Enabled {
@@ -505,20 +562,25 @@ func IsUserAllowedToCommunicate(userName string, peer models.Node) bool {
 		}
 		dstMap := convAclTagToValueMap(policy.Dst)
 		if _, ok := dstMap["*"]; ok {
-			return true
+			allowedPolicies = append(allowedPolicies, policy)
+			continue
 		}
 		for tagID := range peer.Tags {
 			if _, ok := dstMap[tagID.String()]; ok {
-				return true
+				allowedPolicies = append(allowedPolicies, policy)
+				break
 			}
 		}
 
 	}
-	return false
+	if len(allowedPolicies) > 0 {
+		return true, allowedPolicies
+	}
+	return false, []models.Acl{}
 }
 
 // IsNodeAllowedToCommunicate - check node is allowed to communicate with the peer
-func IsNodeAllowedToCommunicate(node, peer models.Node, checkDefaultPolicy bool) bool {
+func IsNodeAllowedToCommunicate(node, peer models.Node, checkDefaultPolicy bool) (bool, []models.Acl) {
 	if node.IsStatic {
 		node = node.StaticNode.ConvertToStaticNode()
 	}
@@ -530,11 +592,11 @@ func IsNodeAllowedToCommunicate(node, peer models.Node, checkDefaultPolicy bool)
 		defaultPolicy, err := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
 		if err == nil {
 			if defaultPolicy.Enabled {
-				return true
+				return true, []models.Acl{defaultPolicy}
 			}
 		}
 	}
-
+	allowedPolicies := []models.Acl{}
 	// list device policies
 	policies := listDevicePolicies(models.NetworkID(peer.Network))
 	srcMap := make(map[string]struct{})
@@ -549,57 +611,88 @@ func IsNodeAllowedToCommunicate(node, peer models.Node, checkDefaultPolicy bool)
 		}
 		srcMap = convAclTagToValueMap(policy.Src)
 		dstMap = convAclTagToValueMap(policy.Dst)
-		// fmt.Printf("\n======> SRCMAP: %+v\n", srcMap)
-		// fmt.Printf("\n======> DSTMAP: %+v\n", dstMap)
-		// fmt.Printf("\n======> node Tags: %+v\n", node.Tags)
-		// fmt.Printf("\n======> peer Tags: %+v\n", peer.Tags)
 		for tagID := range node.Tags {
-			if _, ok := dstMap[tagID.String()]; ok {
+			allowed := false
+			if _, ok := dstMap[tagID.String()]; policy.AllowedDirection == models.TrafficDirectionBi && ok {
 				if _, ok := srcMap["*"]; ok {
-					return true
+					allowed = true
+					allowedPolicies = append(allowedPolicies, policy)
+					break
 				}
 				for tagID := range peer.Tags {
 					if _, ok := srcMap[tagID.String()]; ok {
-						return true
+						allowed = true
+						break
 					}
 				}
 			}
+			if allowed {
+				allowedPolicies = append(allowedPolicies, policy)
+				break
+			}
 			if _, ok := srcMap[tagID.String()]; ok {
 				if _, ok := dstMap["*"]; ok {
-					return true
+					allowed = true
+					allowedPolicies = append(allowedPolicies, policy)
+					break
 				}
 				for tagID := range peer.Tags {
 					if _, ok := dstMap[tagID.String()]; ok {
-						return true
+						allowed = true
+						break
 					}
 				}
 			}
+			if allowed {
+				allowedPolicies = append(allowedPolicies, policy)
+				break
+			}
 		}
 		for tagID := range peer.Tags {
+			allowed := false
 			if _, ok := dstMap[tagID.String()]; ok {
 				if _, ok := srcMap["*"]; ok {
-					return true
+					allowed = true
+					allowedPolicies = append(allowedPolicies, policy)
+					break
 				}
 				for tagID := range node.Tags {
 
 					if _, ok := srcMap[tagID.String()]; ok {
-						return true
+						allowed = true
+						break
 					}
 				}
 			}
-			if _, ok := srcMap[tagID.String()]; ok {
+			if allowed {
+				allowedPolicies = append(allowedPolicies, policy)
+				break
+			}
+
+			if _, ok := srcMap[tagID.String()]; policy.AllowedDirection == models.TrafficDirectionBi && ok {
 				if _, ok := dstMap["*"]; ok {
-					return true
+					allowed = true
+					allowedPolicies = append(allowedPolicies, policy)
+					break
 				}
 				for tagID := range node.Tags {
 					if _, ok := dstMap[tagID.String()]; ok {
-						return true
+						allowed = true
+						break
 					}
 				}
 			}
+			if allowed {
+				allowedPolicies = append(allowedPolicies, policy)
+				break
+			}
 		}
 	}
-	return false
+
+	if len(allowedPolicies) > 0 {
+		return true, allowedPolicies
+	}
+	return false, allowedPolicies
 }
 
 // SortTagEntrys - Sorts slice of Tag entries by their id
@@ -648,7 +741,9 @@ func CheckIfTagAsActivePolicy(tagID models.TagID, netID models.NetworkID) bool {
 		}
 		for _, dstTagI := range acl.Dst {
 			if dstTagI.ID == models.DeviceAclID {
-				return true
+				if tagID.String() == dstTagI.Value {
+					return true
+				}
 			}
 		}
 	}
@@ -682,3 +777,225 @@ func RemoveDeviceTagFromAclPolicies(tagID models.TagID, netID models.NetworkID)
 	}
 	return nil
 }
+
+func getUserAclRulesForNode(targetnode *models.Node,
+	rules map[string]models.AclRule) map[string]models.AclRule {
+	userNodes := GetStaticUserNodesByNetwork(models.NetworkID(targetnode.Network))
+	userGrpMap := GetUserGrpMap()
+	allowedUsers := make(map[string][]models.Acl)
+	acls := listUserPolicies(models.NetworkID(targetnode.Network))
+	for nodeTag := range targetnode.Tags {
+		for _, acl := range acls {
+			if !acl.Enabled {
+				continue
+			}
+			dstTags := convAclTagToValueMap(acl.Dst)
+			if _, ok := dstTags[nodeTag.String()]; ok {
+				// get all src tags
+				for _, srcAcl := range acl.Src {
+					if srcAcl.ID == models.UserAclID {
+						allowedUsers[srcAcl.Value] = append(allowedUsers[srcAcl.Value], acl)
+					} else if srcAcl.ID == models.UserGroupAclID {
+						// fetch all users in the group
+						if usersMap, ok := userGrpMap[models.UserGroupID(srcAcl.Value)]; ok {
+							for userName := range usersMap {
+								allowedUsers[userName] = append(allowedUsers[userName], acl)
+							}
+						}
+					}
+				}
+
+			}
+		}
+	}
+	for _, userNode := range userNodes {
+		if !userNode.StaticNode.Enabled {
+			continue
+		}
+		acls, ok := allowedUsers[userNode.StaticNode.OwnerID]
+		if !ok {
+			continue
+		}
+		for _, acl := range acls {
+
+			if !acl.Enabled {
+				continue
+			}
+
+			r := models.AclRule{
+				ID:              acl.ID,
+				AllowedProtocol: acl.Proto,
+				AllowedPorts:    acl.Port,
+				Direction:       acl.AllowedDirection,
+				Allowed:         true,
+			}
+			// Get peers in the tags and add allowed rules
+			if userNode.StaticNode.Address != "" {
+				r.IPList = append(r.IPList, userNode.StaticNode.AddressIPNet4())
+			}
+			if userNode.StaticNode.Address6 != "" {
+				r.IP6List = append(r.IP6List, userNode.StaticNode.AddressIPNet6())
+			}
+			if aclRule, ok := rules[acl.ID]; ok {
+				aclRule.IPList = append(aclRule.IPList, r.IPList...)
+				aclRule.IP6List = append(aclRule.IP6List, r.IP6List...)
+				rules[acl.ID] = aclRule
+			} else {
+				rules[acl.ID] = r
+			}
+		}
+	}
+	return rules
+}
+
+func GetAclRulesForNode(targetnode *models.Node) (rules map[string]models.AclRule) {
+	defer func() {
+		if !targetnode.IsIngressGateway {
+			rules = getUserAclRulesForNode(targetnode, rules)
+		}
+
+	}()
+	rules = make(map[string]models.AclRule)
+	var taggedNodes map[models.TagID][]models.Node
+	if targetnode.IsIngressGateway {
+		taggedNodes = GetTagMapWithNodesByNetwork(models.NetworkID(targetnode.Network), false)
+	} else {
+		taggedNodes = GetTagMapWithNodesByNetwork(models.NetworkID(targetnode.Network), true)
+	}
+
+	acls := listDevicePolicies(models.NetworkID(targetnode.Network))
+	for nodeTag := range targetnode.Tags {
+		for _, acl := range acls {
+			if !acl.Enabled {
+				continue
+			}
+			srcTags := convAclTagToValueMap(acl.Src)
+			dstTags := convAclTagToValueMap(acl.Dst)
+			aclRule := models.AclRule{
+				ID:              acl.ID,
+				AllowedProtocol: acl.Proto,
+				AllowedPorts:    acl.Port,
+				Direction:       acl.AllowedDirection,
+				Allowed:         true,
+			}
+			if acl.AllowedDirection == models.TrafficDirectionBi {
+				var existsInSrcTag bool
+				var existsInDstTag bool
+
+				if _, ok := srcTags[nodeTag.String()]; ok {
+					existsInSrcTag = true
+				}
+				if _, ok := dstTags[nodeTag.String()]; ok {
+					existsInDstTag = true
+				}
+
+				if existsInSrcTag && !existsInDstTag {
+					// get all dst tags
+					for dst := range dstTags {
+						if dst == nodeTag.String() {
+							continue
+						}
+						// Get peers in the tags and add allowed rules
+						nodes := taggedNodes[models.TagID(dst)]
+						for _, node := range nodes {
+							if node.ID == targetnode.ID {
+								continue
+							}
+							if node.Address.IP != nil {
+								aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+							}
+							if node.Address6.IP != nil {
+								aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+							}
+							if node.IsStatic && node.StaticNode.Address != "" {
+								aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+							}
+							if node.IsStatic && node.StaticNode.Address6 != "" {
+								aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+							}
+						}
+					}
+				}
+				if existsInDstTag && !existsInSrcTag {
+					// get all src tags
+					for src := range srcTags {
+						if src == nodeTag.String() {
+							continue
+						}
+						// Get peers in the tags and add allowed rules
+						nodes := taggedNodes[models.TagID(src)]
+						for _, node := range nodes {
+							if node.ID == targetnode.ID {
+								continue
+							}
+							if node.Address.IP != nil {
+								aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+							}
+							if node.Address6.IP != nil {
+								aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+							}
+							if node.IsStatic && node.StaticNode.Address != "" {
+								aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+							}
+							if node.IsStatic && node.StaticNode.Address6 != "" {
+								aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+							}
+						}
+					}
+				}
+				if existsInDstTag && existsInSrcTag {
+					nodes := taggedNodes[nodeTag]
+					for _, node := range nodes {
+						if node.ID == targetnode.ID {
+							continue
+						}
+						if node.Address.IP != nil {
+							aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+						}
+						if node.Address6.IP != nil {
+							aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+						}
+						if node.IsStatic && node.StaticNode.Address != "" {
+							aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+						}
+						if node.IsStatic && node.StaticNode.Address6 != "" {
+							aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+						}
+					}
+				}
+			} else {
+				if _, ok := dstTags[nodeTag.String()]; ok {
+					// get all src tags
+					for src := range srcTags {
+						if src == nodeTag.String() {
+							continue
+						}
+						// Get peers in the tags and add allowed rules
+						nodes := taggedNodes[models.TagID(src)]
+						for _, node := range nodes {
+							if node.ID == targetnode.ID {
+								continue
+							}
+							if node.Address.IP != nil {
+								aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+							}
+							if node.Address6.IP != nil {
+								aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+							}
+							if node.IsStatic && node.StaticNode.Address != "" {
+								aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+							}
+							if node.IsStatic && node.StaticNode.Address6 != "" {
+								aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+							}
+						}
+					}
+				}
+			}
+			if len(aclRule.IPList) > 0 || len(aclRule.IP6List) > 0 {
+				rules[acl.ID] = aclRule
+			}
+		}
+	}
+	return rules
+}

+ 156 - 69
logic/extpeers.go

@@ -456,6 +456,10 @@ func GetStaticNodeIps(node models.Node) (ips []net.IP) {
 
 func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
 	// fetch user access to static clients via policies
+	defer func() {
+		logger.Log(0, fmt.Sprintf("node.ID: %s, Rules: %+v\n", node.ID, rules))
+	}()
+
 	defaultUserPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy)
 	defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
 	nodes, _ := GetNetworkNodes(node.Network)
@@ -468,36 +472,50 @@ func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
 			if peer.IsUserNode {
 				continue
 			}
-			if IsUserAllowedToCommunicate(userNodeI.StaticNode.OwnerID, peer) {
+			if ok, allowedPolicies := IsUserAllowedToCommunicate(userNodeI.StaticNode.OwnerID, peer); ok {
 				if peer.IsStatic {
 					if userNodeI.StaticNode.Address != "" {
 						if !defaultUserPolicy.Enabled {
-							rules = append(rules, models.FwRule{
-								SrcIP: userNodeI.StaticNode.AddressIPNet4(),
-								DstIP: peer.StaticNode.AddressIPNet4(),
-								Allow: true,
-							})
+							for _, policy := range allowedPolicies {
+								rules = append(rules, models.FwRule{
+									SrcIP:           userNodeI.StaticNode.AddressIPNet4(),
+									DstIP:           peer.StaticNode.AddressIPNet4(),
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+									Allow:           true,
+								})
+								rules = append(rules, models.FwRule{
+									SrcIP:           peer.StaticNode.AddressIPNet4(),
+									DstIP:           userNodeI.StaticNode.AddressIPNet4(),
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+									Allow:           true,
+								})
+							}
 						}
-						rules = append(rules, models.FwRule{
-							SrcIP: peer.StaticNode.AddressIPNet4(),
-							DstIP: userNodeI.StaticNode.AddressIPNet4(),
-							Allow: true,
-						})
+
 					}
 					if userNodeI.StaticNode.Address6 != "" {
 						if !defaultUserPolicy.Enabled {
-							rules = append(rules, models.FwRule{
-								SrcIP: userNodeI.StaticNode.AddressIPNet6(),
-								DstIP: peer.StaticNode.AddressIPNet6(),
-								Allow: true,
-							})
+							for _, policy := range allowedPolicies {
+								rules = append(rules, models.FwRule{
+									SrcIP:           userNodeI.StaticNode.AddressIPNet6(),
+									DstIP:           peer.StaticNode.AddressIPNet6(),
+									Allow:           true,
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+								})
+								rules = append(rules, models.FwRule{
+									SrcIP:           peer.StaticNode.AddressIPNet6(),
+									DstIP:           userNodeI.StaticNode.AddressIPNet6(),
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+									Allow:           true,
+								})
+
+							}
 						}
 
-						rules = append(rules, models.FwRule{
-							SrcIP: peer.StaticNode.AddressIPNet6(),
-							DstIP: userNodeI.StaticNode.AddressIPNet6(),
-							Allow: true,
-						})
 					}
 					if len(peer.StaticNode.ExtraAllowedIPs) > 0 {
 						for _, additionalAllowedIPNet := range peer.StaticNode.ExtraAllowedIPs {
@@ -526,29 +544,39 @@ func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
 
 					if userNodeI.StaticNode.Address != "" {
 						if !defaultUserPolicy.Enabled {
-							rules = append(rules, models.FwRule{
-								SrcIP: userNodeI.StaticNode.AddressIPNet4(),
-								DstIP: net.IPNet{
-									IP:   peer.Address.IP,
-									Mask: net.CIDRMask(32, 32),
-								},
-								Allow: true,
-							})
+							for _, policy := range allowedPolicies {
+								rules = append(rules, models.FwRule{
+									SrcIP: userNodeI.StaticNode.AddressIPNet4(),
+									DstIP: net.IPNet{
+										IP:   peer.Address.IP,
+										Mask: net.CIDRMask(32, 32),
+									},
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+									Allow:           true,
+								})
+							}
+
 						}
 					}
 
 					if userNodeI.StaticNode.Address6 != "" {
-						rules = append(rules, models.FwRule{
-							SrcIP: userNodeI.StaticNode.AddressIPNet6(),
-							DstIP: net.IPNet{
-								IP:   peer.Address6.IP,
-								Mask: net.CIDRMask(128, 128),
-							},
-							Allow: true,
-						})
+						if !defaultUserPolicy.Enabled {
+							for _, policy := range allowedPolicies {
+								rules = append(rules, models.FwRule{
+									SrcIP: userNodeI.StaticNode.AddressIPNet6(),
+									DstIP: net.IPNet{
+										IP:   peer.Address6.IP,
+										Mask: net.CIDRMask(128, 128),
+									},
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+									Allow:           true,
+								})
+							}
+						}
 					}
 				}
-
 			}
 		}
 	}
@@ -564,21 +592,48 @@ func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
 			if peer.StaticNode.ClientID == nodeI.StaticNode.ClientID || peer.IsUserNode {
 				continue
 			}
-			if IsNodeAllowedToCommunicate(nodeI, peer, true) {
+			if ok, allowedPolicies := IsNodeAllowedToCommunicate(nodeI, peer, true); ok {
 				if peer.IsStatic {
 					if nodeI.StaticNode.Address != "" {
-						rules = append(rules, models.FwRule{
-							SrcIP: nodeI.StaticNode.AddressIPNet4(),
-							DstIP: peer.StaticNode.AddressIPNet4(),
-							Allow: true,
-						})
+						for _, policy := range allowedPolicies {
+							rules = append(rules, models.FwRule{
+								SrcIP:           nodeI.StaticNode.AddressIPNet4(),
+								DstIP:           peer.StaticNode.AddressIPNet4(),
+								AllowedProtocol: policy.Proto,
+								AllowedPorts:    policy.Port,
+								Allow:           true,
+							})
+							if policy.AllowedDirection == models.TrafficDirectionBi {
+								rules = append(rules, models.FwRule{
+									SrcIP:           peer.StaticNode.AddressIPNet4(),
+									DstIP:           nodeI.StaticNode.AddressIPNet4(),
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+									Allow:           true,
+								})
+							}
+						}
+
 					}
 					if nodeI.StaticNode.Address6 != "" {
-						rules = append(rules, models.FwRule{
-							SrcIP: nodeI.StaticNode.AddressIPNet6(),
-							DstIP: peer.StaticNode.AddressIPNet6(),
-							Allow: true,
-						})
+						for _, policy := range allowedPolicies {
+							rules = append(rules, models.FwRule{
+								SrcIP:           nodeI.StaticNode.AddressIPNet6(),
+								DstIP:           peer.StaticNode.AddressIPNet6(),
+								AllowedProtocol: policy.Proto,
+								AllowedPorts:    policy.Port,
+								Allow:           true,
+							})
+							if policy.AllowedDirection == models.TrafficDirectionBi {
+								rules = append(rules, models.FwRule{
+									SrcIP:           peer.StaticNode.AddressIPNet6(),
+									DstIP:           nodeI.StaticNode.AddressIPNet6(),
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+									Allow:           true,
+								})
+							}
+						}
 					}
 					if len(peer.StaticNode.ExtraAllowedIPs) > 0 {
 						for _, additionalAllowedIPNet := range peer.StaticNode.ExtraAllowedIPs {
@@ -605,24 +660,56 @@ func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
 					}
 				} else {
 					if nodeI.StaticNode.Address != "" {
-						rules = append(rules, models.FwRule{
-							SrcIP: nodeI.StaticNode.AddressIPNet4(),
-							DstIP: net.IPNet{
-								IP:   peer.Address.IP,
-								Mask: net.CIDRMask(32, 32),
-							},
-							Allow: true,
-						})
+						for _, policy := range allowedPolicies {
+							rules = append(rules, models.FwRule{
+								SrcIP: nodeI.StaticNode.AddressIPNet4(),
+								DstIP: net.IPNet{
+									IP:   peer.Address.IP,
+									Mask: net.CIDRMask(32, 32),
+								},
+								AllowedProtocol: policy.Proto,
+								AllowedPorts:    policy.Port,
+								Allow:           true,
+							})
+							if policy.AllowedDirection == models.TrafficDirectionBi {
+								rules = append(rules, models.FwRule{
+									SrcIP: net.IPNet{
+										IP:   peer.Address.IP,
+										Mask: net.CIDRMask(32, 32),
+									},
+									DstIP:           nodeI.StaticNode.AddressIPNet4(),
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+									Allow:           true,
+								})
+							}
+						}
 					}
 					if nodeI.StaticNode.Address6 != "" {
-						rules = append(rules, models.FwRule{
-							SrcIP: nodeI.StaticNode.AddressIPNet6(),
-							DstIP: net.IPNet{
-								IP:   peer.Address6.IP,
-								Mask: net.CIDRMask(128, 128),
-							},
-							Allow: true,
-						})
+						for _, policy := range allowedPolicies {
+							rules = append(rules, models.FwRule{
+								SrcIP: nodeI.StaticNode.AddressIPNet6(),
+								DstIP: net.IPNet{
+									IP:   peer.Address6.IP,
+									Mask: net.CIDRMask(128, 128),
+								},
+								AllowedProtocol: policy.Proto,
+								AllowedPorts:    policy.Port,
+								Allow:           true,
+							})
+							if policy.AllowedDirection == models.TrafficDirectionBi {
+								rules = append(rules, models.FwRule{
+									SrcIP: net.IPNet{
+										IP:   peer.Address6.IP,
+										Mask: net.CIDRMask(128, 128),
+									},
+									DstIP:           nodeI.StaticNode.AddressIPNet6(),
+									AllowedProtocol: policy.Proto,
+									AllowedPorts:    policy.Port,
+									Allow:           true,
+								})
+							}
+						}
 					}
 				}
 
@@ -650,11 +737,11 @@ func GetExtPeers(node, peer *models.Node) ([]wgtypes.PeerConfig, []models.IDandA
 			continue
 		}
 		if extPeer.RemoteAccessClientID == "" {
-			if !IsNodeAllowedToCommunicate(extPeer.ConvertToStaticNode(), *peer, true) {
+			if ok, _ := IsNodeAllowedToCommunicate(extPeer.ConvertToStaticNode(), *peer, true); !ok {
 				continue
 			}
 		} else {
-			if !IsUserAllowedToCommunicate(extPeer.OwnerID, *peer) {
+			if ok, _ := IsUserAllowedToCommunicate(extPeer.OwnerID, *peer); !ok {
 				continue
 			}
 		}
@@ -739,7 +826,7 @@ func getExtpeerEgressRanges(node models.Node) (ranges, ranges6 []net.IPNet) {
 		if len(extPeer.ExtraAllowedIPs) == 0 {
 			continue
 		}
-		if !IsNodeAllowedToCommunicate(extPeer.ConvertToStaticNode(), node, true) {
+		if ok, _ := IsNodeAllowedToCommunicate(extPeer.ConvertToStaticNode(), node, true); !ok {
 			continue
 		}
 		for _, allowedRange := range extPeer.ExtraAllowedIPs {
@@ -766,7 +853,7 @@ func getExtpeersExtraRoutes(node models.Node) (egressRoutes []models.EgressNetwo
 		if len(extPeer.ExtraAllowedIPs) == 0 {
 			continue
 		}
-		if !IsNodeAllowedToCommunicate(extPeer.ConvertToStaticNode(), node, true) {
+		if ok, _ := IsNodeAllowedToCommunicate(extPeer.ConvertToStaticNode(), node, true); !ok {
 			continue
 		}
 		egressRoutes = append(egressRoutes, getExtPeerEgressRoute(node, extPeer)...)

+ 25 - 1
logic/nodes.go

@@ -818,7 +818,7 @@ func GetTagMapWithNodes() (tagNodesMap map[models.TagID][]models.Node) {
 	return
 }
 
-func GetTagMapWithNodesByNetwork(netID models.NetworkID) (tagNodesMap map[models.TagID][]models.Node) {
+func GetTagMapWithNodesByNetwork(netID models.NetworkID, withStaticNodes bool) (tagNodesMap map[models.TagID][]models.Node) {
 	tagNodesMap = make(map[models.TagID][]models.Node)
 	nodes, _ := GetNetworkNodes(netID.String())
 	for _, nodeI := range nodes {
@@ -829,6 +829,9 @@ func GetTagMapWithNodesByNetwork(netID models.NetworkID) (tagNodesMap map[models
 			tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
 		}
 	}
+	if !withStaticNodes {
+		return
+	}
 	return AddTagMapWithStaticNodes(netID, tagNodesMap)
 }
 
@@ -853,6 +856,27 @@ func AddTagMapWithStaticNodes(netID models.NetworkID,
 	return tagNodesMap
 }
 
+func AddTagMapWithStaticNodesWithUsers(netID models.NetworkID,
+	tagNodesMap map[models.TagID][]models.Node) map[models.TagID][]models.Node {
+	extclients, err := GetNetworkExtClients(netID.String())
+	if err != nil {
+		return tagNodesMap
+	}
+	for _, extclient := range extclients {
+		if extclient.Tags == nil {
+			continue
+		}
+		for tagID := range extclient.Tags {
+			tagNodesMap[tagID] = append(tagNodesMap[tagID], models.Node{
+				IsStatic:   true,
+				StaticNode: extclient,
+			})
+		}
+
+	}
+	return tagNodesMap
+}
+
 func GetNodesWithTag(tagID models.TagID) map[string]models.Node {
 	nMap := make(map[string]models.Node)
 	tag, err := GetTag(tagID)

+ 17 - 5
logic/peers.go

@@ -74,8 +74,10 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 		ServerVersion: servercfg.GetVersion(),
 		ServerAddrs:   []models.ServerAddr{},
 		FwUpdate: models.FwUpdate{
+			AllowAll:    true,
 			EgressInfo:  make(map[string]models.EgressInfo),
 			IngressInfo: make(map[string]models.IngressInfo),
+			AclRules:    make(map[string]models.AclRule),
 		},
 		PeerIDs:           make(models.PeerMap, 0),
 		Peers:             []wgtypes.PeerConfig{},
@@ -96,8 +98,6 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 		if !node.Connected || node.PendingDelete || node.Action == models.NODE_DELETE {
 			continue
 		}
-		// check default policy if all allowed return true
-		defaultPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
 		if host.OS == models.OS_Types.IoT {
 			hostPeerUpdate.NodeAddrs = append(hostPeerUpdate.NodeAddrs, node.PrimaryAddressIPNet())
 			if node.IsRelayed {
@@ -156,6 +156,19 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 		if !hostPeerUpdate.IsInternetGw {
 			hostPeerUpdate.IsInternetGw = IsInternetGw(node)
 		}
+		defaultUserPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy)
+		defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
+		if node.NetworkRange.IP != nil {
+			hostPeerUpdate.FwUpdate.Networks = append(hostPeerUpdate.FwUpdate.Networks, node.NetworkRange)
+		}
+		if node.NetworkRange6.IP != nil {
+			hostPeerUpdate.FwUpdate.Networks = append(hostPeerUpdate.FwUpdate.Networks, node.NetworkRange6)
+		}
+
+		if !defaultDevicePolicy.Enabled || !defaultUserPolicy.Enabled {
+			hostPeerUpdate.FwUpdate.AllowAll = false
+		}
+		hostPeerUpdate.FwUpdate.AclRules = GetAclRulesForNode(&node)
 		currentPeers := GetNetworkNodesMemory(allNodes, node.Network)
 		for _, peer := range currentPeers {
 			peer := peer
@@ -257,11 +270,12 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 				peerConfig.Endpoint.Port = peerHost.ListenPort
 			}
 			allowedips := GetAllowedIPs(&node, &peer, nil)
+			allowedToComm, _ := IsNodeAllowedToCommunicate(node, peer, false)
 			if peer.Action != models.NODE_DELETE &&
 				!peer.PendingDelete &&
 				peer.Connected &&
 				nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), nodeacls.NodeID(peer.ID.String())) &&
-				(defaultPolicy.Enabled || IsNodeAllowedToCommunicate(node, peer, false)) &&
+				(defaultDevicePolicy.Enabled || allowedToComm) &&
 				(deletedNode == nil || (deletedNode != nil && peer.ID.String() != deletedNode.ID.String())) {
 				peerConfig.AllowedIPs = allowedips // only append allowed IPs if valid connection
 			}
@@ -311,8 +325,6 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 			hostPeerUpdate.FwUpdate.IsIngressGw = true
 			extPeers, extPeerIDAndAddrs, egressRoutes, err = GetExtPeers(&node, &node)
 			if err == nil {
-				defaultUserPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy)
-				defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
 				if !defaultDevicePolicy.Enabled || !defaultUserPolicy.Enabled {
 					ingFwUpdate := models.IngressInfo{
 						IngressID:     node.ID.String(),

+ 1 - 1
logic/tags.go

@@ -85,7 +85,7 @@ func ListTagsWithNodes(netID models.NetworkID) ([]models.TagListResp, error) {
 	if err != nil {
 		return []models.TagListResp{}, err
 	}
-	tagsNodeMap := GetTagMapWithNodesByNetwork(netID)
+	tagsNodeMap := GetTagMapWithNodesByNetwork(netID, true)
 	resp := []models.TagListResp{}
 	for _, tagI := range tags {
 		tagRespI := models.TagListResp{

+ 19 - 0
logic/user_mgmt.go

@@ -98,6 +98,25 @@ func ListPlatformRoles() ([]models.UserRolePermissionTemplate, error) {
 	return userRoles, nil
 }
 
+func GetUserGrpMap() map[models.UserGroupID]map[string]struct{} {
+	grpUsersMap := make(map[models.UserGroupID]map[string]struct{})
+	users, _ := GetUsersDB()
+	for _, user := range users {
+		for gID := range user.UserGroups {
+			if grpUsers, ok := grpUsersMap[gID]; ok {
+				grpUsers[user.UserName] = struct{}{}
+				grpUsersMap[gID] = grpUsers
+			} else {
+				grpUsersMap[gID] = make(map[string]struct{})
+				grpUsersMap[gID][user.UserName] = struct{}{}
+			}
+		}
+
+	}
+
+	return grpUsersMap
+}
+
 func userRolesInit() {
 	d, _ := json.Marshal(SuperAdminPermissionTemplate)
 	database.Insert(SuperAdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)

+ 1 - 0
migrate/migrate.go

@@ -437,5 +437,6 @@ func createDefaultTagsAndPolicies() {
 	for _, network := range networks {
 		logic.CreateDefaultTags(models.NetworkID(network.NetID))
 		logic.CreateDefaultAclNetworkPolicies(models.NetworkID(network.NetID))
+		logic.MigrateDefaulAclPolicies(models.NetworkID(network.NetID))
 	}
 }

+ 47 - 0
models/acl.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"net"
 	"time"
 )
 
@@ -14,6 +15,31 @@ const (
 	TrafficDirectionBi
 )
 
+// Protocol - allowed protocol
+type Protocol string
+
+const (
+	ALL  Protocol = "all"
+	UDP  Protocol = "udp"
+	TCP  Protocol = "tcp"
+	ICMP Protocol = "icmp"
+)
+
+type ServiceType string
+
+const (
+	Http        = "HTTP"
+	Https       = "HTTPS"
+	AllTCP      = "All TCP"
+	AllUDP      = "All UDP"
+	ICMPService = "ICMP"
+	Custom      = "Custom"
+)
+
+func (p Protocol) String() string {
+	return string(p)
+}
+
 type AclPolicyType string
 
 const (
@@ -59,6 +85,9 @@ type Acl struct {
 	RuleType         AclPolicyType           `json:"policy_type"`
 	Src              []AclPolicyTag          `json:"src_type"`
 	Dst              []AclPolicyTag          `json:"dst_type"`
+	Proto            Protocol                `json:"protocol"` // tcp, udp, etc.
+	ServiceType      string                  `json:"type"`
+	Port             []string                `json:"ports"`
 	AllowedDirection AllowedTrafficDirection `json:"allowed_traffic_direction"`
 	Enabled          bool                    `json:"enabled"`
 	CreatedBy        string                  `json:"created_by"`
@@ -66,7 +95,25 @@ type Acl struct {
 }
 
 type AclPolicyTypes struct {
+	ProtocolTypes []ProtocolType
 	RuleTypes     []AclPolicyType `json:"policy_types"`
 	SrcGroupTypes []AclGroupType  `json:"src_grp_types"`
 	DstGroupTypes []AclGroupType  `json:"dst_grp_types"`
 }
+
+type ProtocolType struct {
+	Name             string     `json:"name"`
+	AllowedProtocols []Protocol `json:"allowed_protocols"`
+	PortRange        string     `json:"port_range"`
+	AllowPortSetting bool       `json:"allow_port_setting"`
+}
+
+type AclRule struct {
+	ID              string                  `json:"id"`
+	IPList          []net.IPNet             `json:"ip_list"`
+	IP6List         []net.IPNet             `json:"ip6_list"`
+	AllowedProtocol Protocol                `json:"allowed_protocols"` // tcp, udp, etc.
+	AllowedPorts    []string                `json:"allowed_ports"`
+	Direction       AllowedTrafficDirection `json:"direction"` // single or two-way
+	Allowed         bool
+}

+ 8 - 3
models/mqtt.go

@@ -30,9 +30,11 @@ type HostPeerUpdate struct {
 }
 
 type FwRule struct {
-	SrcIP net.IPNet
-	DstIP net.IPNet
-	Allow bool
+	SrcIP           net.IPNet `json:"src_ip"`
+	DstIP           net.IPNet `json:"dst_ip"`
+	AllowedProtocol Protocol  `json:"allowed_protocols"` // tcp, udp, etc.
+	AllowedPorts    []string  `json:"allowed_ports"`
+	Allow           bool      `json:"allow"`
 }
 
 // IngressInfo - struct for ingress info
@@ -92,10 +94,13 @@ type KeyUpdate struct {
 
 // FwUpdate - struct for firewall updates
 type FwUpdate struct {
+	AllowAll    bool                   `json:"allow_all"`
+	Networks    []net.IPNet            `json:"networks"`
 	IsEgressGw  bool                   `json:"is_egress_gw"`
 	IsIngressGw bool                   `json:"is_ingress_gw"`
 	EgressInfo  map[string]EgressInfo  `json:"egress_info"`
 	IngressInfo map[string]IngressInfo `json:"ingress_info"`
+	AclRules    map[string]AclRule     `json:"acl_rules"`
 }
 
 // FailOverMeReq - struct for failover req

+ 13 - 0
models/node.go

@@ -215,6 +215,19 @@ func (node *Node) PrimaryAddress() string {
 	return node.Address6.IP.String()
 }
 
+func (node *Node) AddressIPNet4() net.IPNet {
+	return net.IPNet{
+		IP:   node.Address.IP,
+		Mask: net.CIDRMask(32, 32),
+	}
+}
+func (node *Node) AddressIPNet6() net.IPNet {
+	return net.IPNet{
+		IP:   node.Address6.IP,
+		Mask: net.CIDRMask(128, 128),
+	}
+}
+
 // ExtClient.PrimaryAddress - returns ipv4 IPNet format
 func (extPeer *ExtClient) AddressIPNet4() net.IPNet {
 	return net.IPNet{

+ 4 - 2
pro/logic/status.go

@@ -133,7 +133,8 @@ func checkPeerStatus(node *models.Node, defaultAclPolicy bool) {
 		if err != nil {
 			continue
 		}
-		if !defaultAclPolicy && !logic.IsNodeAllowedToCommunicate(*node, peer, false) {
+		allowed, _ := logic.IsNodeAllowedToCommunicate(*node, peer, false)
+		if !defaultAclPolicy && !allowed {
 			continue
 		}
 
@@ -167,7 +168,8 @@ func checkPeerConnectivity(node *models.Node, metrics *models.Metrics, defaultAc
 		if err != nil {
 			continue
 		}
-		if !defaultAclPolicy && !logic.IsNodeAllowedToCommunicate(*node, peer, false) {
+		allowed, _ := logic.IsNodeAllowedToCommunicate(*node, peer, false)
+		if !defaultAclPolicy && !allowed {
 			continue
 		}