NET-1990: add peerkey to network egress routes model (#3379)

* add peerkey to network egress routes model

* add peerkey to network egress routes model

* filter out conflicting routes from node

* add support for egress HA on relay

* add support for egress HA on relay

* add support for egress HA on relay

* skip if curr node is relay node of the peer

* skip if curr node is relay node of the peer

* fix failover egress HA

* add network to egress route model

* clone before modifying
This commit is contained in:
Abhishek K 2025-03-24 15:33:39 +04:00 committed by GitHub
parent 39d812f137
commit 4cc56fd3be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 80 additions and 4 deletions

View file

@ -854,6 +854,7 @@ func GetExtPeers(node, peer *models.Node) ([]wgtypes.PeerConfig, []models.IDandA
func getExtPeerEgressRoute(node models.Node, extPeer models.ExtClient) (egressRoutes []models.EgressNetworkRoutes) {
egressRoutes = append(egressRoutes, models.EgressNetworkRoutes{
PeerKey: extPeer.PublicKey,
EgressGwAddr: extPeer.AddressIPNet4(),
EgressGwAddr6: extPeer.AddressIPNet6(),
NodeAddr: node.Address,

View file

@ -241,20 +241,45 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
PersistentKeepaliveInterval: &peerHost.PersistentKeepalive,
ReplaceAllowedIPs: true,
}
_, isFailOverPeer := node.FailOverPeers[peer.ID.String()]
if peer.IsEgressGateway {
peerKey := peerHost.PublicKey.String()
if isFailOverPeer && peer.FailedOverBy.String() != node.ID.String() {
// get relay host
failOverNode, err := GetNodeByID(peer.FailedOverBy.String())
if err == nil {
relayHost, err := GetHost(failOverNode.HostID.String())
if err == nil {
peerKey = relayHost.PublicKey.String()
}
}
}
if peer.IsRelayed && (peer.RelayedBy != node.ID.String()) {
// get relay host
relayNode, err := GetNodeByID(peer.RelayedBy)
if err == nil {
relayHost, err := GetHost(relayNode.HostID.String())
if err == nil {
peerKey = relayHost.PublicKey.String()
}
}
}
hostPeerUpdate.EgressRoutes = append(hostPeerUpdate.EgressRoutes, models.EgressNetworkRoutes{
PeerKey: peerKey,
EgressGwAddr: peer.Address,
EgressGwAddr6: peer.Address6,
NodeAddr: node.Address,
NodeAddr6: node.Address6,
EgressRanges: peer.EgressGatewayRanges,
EgressRangesWithMetric: peer.EgressGatewayRequest.RangesWithMetric,
EgressRanges: filterConflictingEgressRoutes(node, peer),
EgressRangesWithMetric: filterConflictingEgressRoutesWithMetric(node, peer),
Network: peer.Network,
})
}
if peer.IsIngressGateway {
hostPeerUpdate.EgressRoutes = append(hostPeerUpdate.EgressRoutes, getExtpeersExtraRoutes(node)...)
}
_, isFailOverPeer := node.FailOverPeers[peer.ID.String()]
if (node.IsRelayed && node.RelayedBy != peer.ID.String()) ||
(peer.IsRelayed && peer.RelayedBy != node.ID.String()) || isFailOverPeer {
// if node is relayed and peer is not the relay, set remove to true
@ -517,6 +542,42 @@ func GetPeerListenPort(host *models.Host) int {
return peerPort
}
func filterConflictingEgressRoutes(node, peer models.Node) []string {
egressIPs := slices.Clone(peer.EgressGatewayRanges)
if node.IsEgressGateway {
// filter conflicting addrs
nodeEgressMap := make(map[string]struct{})
for _, rangeI := range node.EgressGatewayRanges {
nodeEgressMap[rangeI] = struct{}{}
}
for i := len(egressIPs) - 1; i >= 0; i-- {
if _, ok := nodeEgressMap[egressIPs[i]]; ok {
egressIPs = append(egressIPs[:i], egressIPs[i+1:]...)
}
}
}
return egressIPs
}
func filterConflictingEgressRoutesWithMetric(node, peer models.Node) []models.EgressRangeMetric {
egressIPs := slices.Clone(peer.EgressGatewayRequest.RangesWithMetric)
if node.IsEgressGateway {
// filter conflicting addrs
nodeEgressMap := make(map[string]struct{})
for _, rangeI := range node.EgressGatewayRanges {
nodeEgressMap[rangeI] = struct{}{}
}
for i := len(egressIPs) - 1; i >= 0; i-- {
if _, ok := nodeEgressMap[egressIPs[i].Network]; ok {
egressIPs = append(egressIPs[:i], egressIPs[i+1:]...)
}
}
}
return egressIPs
}
// GetAllowedIPs - calculates the wireguard allowedip field for a peer of a node based on the peer and node settings
func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet {
var allowedips []net.IPNet
@ -605,6 +666,18 @@ func getNodeAllowedIPs(peer, node *models.Node) []net.IPNet {
if peer.IsEgressGateway {
// hasGateway = true
egressIPs := GetEgressIPs(peer)
if node.IsEgressGateway {
// filter conflicting addrs
nodeEgressMap := make(map[string]struct{})
for _, rangeI := range node.EgressGatewayRanges {
nodeEgressMap[rangeI] = struct{}{}
}
for i := len(egressIPs) - 1; i >= 0; i-- {
if _, ok := nodeEgressMap[egressIPs[i].String()]; ok {
egressIPs = append(egressIPs[:i], egressIPs[i+1:]...)
}
}
}
allowedips = append(allowedips, egressIPs...)
}
if peer.IsRelay {

View file

@ -70,12 +70,14 @@ type EgressInfo struct {
// EgressNetworkRoutes - struct for egress network routes for adding routes to peer's interface
type EgressNetworkRoutes struct {
PeerKey string `json:"peer_key"`
EgressGwAddr net.IPNet `json:"egress_gw_addr" yaml:"egress_gw_addr"`
EgressGwAddr6 net.IPNet `json:"egress_gw_addr6" yaml:"egress_gw_addr6"`
NodeAddr net.IPNet `json:"node_addr"`
NodeAddr6 net.IPNet `json:"node_addr6"`
EgressRanges []string `json:"egress_ranges"`
EgressRangesWithMetric []EgressRangeMetric `json:"egress_ranges_metric"`
Network string `json:"network"`
}
// PeerRouteInfo - struct for peer info for an ext. client

View file

@ -424,7 +424,7 @@ func createUserGroup(w http.ResponseWriter, r *http.Request) {
ID: uuid.New().String(),
Name: fmt.Sprintf("%s group", userGroupReq.Group.Name),
MetaData: "This Policy allows user group to communicate with all gateways",
Default: true,
Default: false,
ServiceType: models.Any,
NetworkID: models.NetworkID(network.NetID),
Proto: models.ALL,