optimize generateACLPeerCacheMap (#1377)

This commit is contained in:
Philipp Krivanec 2023-04-26 06:02:54 +02:00 committed by GitHub
parent 6215eb6471
commit d0113732fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 47 deletions

15
acls.go
View file

@ -163,23 +163,20 @@ func (h *Headscale) UpdateACLRules() error {
// generateACLPeerCacheMap takes a list of Tailscale filter rules and generates a map // generateACLPeerCacheMap takes a list of Tailscale filter rules and generates a map
// of which Sources ("*" and IPs) can access destinations. This is to speed up the // of which Sources ("*" and IPs) can access destinations. This is to speed up the
// process of generating MapResponses when deciding which Peers to inform nodes about. // process of generating MapResponses when deciding which Peers to inform nodes about.
func generateACLPeerCacheMap(rules []tailcfg.FilterRule) map[string]map[string]struct{} { func generateACLPeerCacheMap(rules []tailcfg.FilterRule) map[string][]string {
aclCachePeerMap := make(map[string]map[string]struct{}) aclCachePeerMap := make(map[string][]string)
for _, rule := range rules { for _, rule := range rules {
for _, srcIP := range rule.SrcIPs { for _, srcIP := range rule.SrcIPs {
for _, ip := range expandACLPeerAddr(srcIP) { for _, ip := range expandACLPeerAddr(srcIP) {
if data, ok := aclCachePeerMap[ip]; ok { if data, ok := aclCachePeerMap[ip]; ok {
for _, dstPort := range rule.DstPorts { for _, dstPort := range rule.DstPorts {
for _, dstIP := range expandACLPeerAddr(dstPort.IP) { data = append(data, dstPort.IP)
data[dstIP] = struct{}{}
}
} }
aclCachePeerMap[ip] = data
} else { } else {
dstPortsMap := make(map[string]struct{}, len(rule.DstPorts)) dstPortsMap := make([]string, 0)
for _, dstPort := range rule.DstPorts { for _, dstPort := range rule.DstPorts {
for _, dstIP := range expandACLPeerAddr(dstPort.IP) { dstPortsMap = append(dstPortsMap, dstPort.IP)
dstPortsMap[dstIP] = struct{}{}
}
} }
aclCachePeerMap[ip] = dstPortsMap aclCachePeerMap[ip] = dstPortsMap
} }

2
app.go
View file

@ -87,7 +87,7 @@ type Headscale struct {
aclPolicy *ACLPolicy aclPolicy *ACLPolicy
aclRules []tailcfg.FilterRule aclRules []tailcfg.FilterRule
aclPeerCacheMapRW sync.RWMutex aclPeerCacheMapRW sync.RWMutex
aclPeerCacheMap map[string]map[string]struct{} aclPeerCacheMap map[string][]string
sshPolicy *tailcfg.SSHPolicy sshPolicy *tailcfg.SSHPolicy
lastStateChange *xsync.MapOf[string, time.Time] lastStateChange *xsync.MapOf[string, time.Time]

View file

@ -4,6 +4,7 @@ import (
"database/sql/driver" "database/sql/driver"
"errors" "errors"
"fmt" "fmt"
"net"
"net/netip" "net/netip"
"sort" "sort"
"strconv" "strconv"
@ -172,7 +173,7 @@ func filterMachinesByACL(
machine *Machine, machine *Machine,
machines Machines, machines Machines,
lock *sync.RWMutex, lock *sync.RWMutex,
aclPeerCacheMap map[string]map[string]struct{}, aclPeerCacheMap map[string][]string,
) Machines { ) Machines {
log.Trace(). log.Trace().
Caller(). Caller().
@ -197,43 +198,34 @@ func filterMachinesByACL(
if dstMap, ok := aclPeerCacheMap["*"]; ok { if dstMap, ok := aclPeerCacheMap["*"]; ok {
// match source and all destination // match source and all destination
if _, dstOk := dstMap["*"]; dstOk {
peers[peer.ID] = peer
continue for _, dst := range dstMap {
if dst == "*" {
peers[peer.ID] = peer
continue
}
} }
// match source and all destination // match source and all destination
for _, peerIP := range peerIPs { for _, peerIP := range peerIPs {
if _, dstOk := dstMap[peerIP]; dstOk { for _, dst := range dstMap {
peers[peer.ID] = peer _, cdr, _ := net.ParseCIDR(dst)
ip := net.ParseIP(peerIP)
if dst == peerIP || (cdr != nil && ip != nil && cdr.Contains(ip)) {
peers[peer.ID] = peer
continue continue
}
} }
} }
// match all sources and source // match all sources and source
for _, machineIP := range machineIPs { for _, machineIP := range machineIPs {
if _, dstOk := dstMap[machineIP]; dstOk { for _, dst := range dstMap {
peers[peer.ID] = peer _, cdr, _ := net.ParseCIDR(dst)
ip := net.ParseIP(machineIP)
continue if dst == machineIP || (cdr != nil && ip != nil && cdr.Contains(ip)) {
}
}
}
for _, machineIP := range machineIPs {
if dstMap, ok := aclPeerCacheMap[machineIP]; ok {
// match source and all destination
if _, dstOk := dstMap["*"]; dstOk {
peers[peer.ID] = peer
continue
}
// match source and destination
for _, peerIP := range peerIPs {
if _, dstOk := dstMap[peerIP]; dstOk {
peers[peer.ID] = peer peers[peer.ID] = peer
continue continue
@ -242,22 +234,55 @@ func filterMachinesByACL(
} }
} }
for _, peerIP := range peerIPs { for _, machineIP := range machineIPs {
if dstMap, ok := aclPeerCacheMap[peerIP]; ok { if dstMap, ok := aclPeerCacheMap[machineIP]; ok {
// match source and all destination // match source and all destination
if _, dstOk := dstMap["*"]; dstOk { for _, dst := range dstMap {
peers[peer.ID] = peer if dst == "*" {
continue
}
// match return path
for _, machineIP := range machineIPs {
if _, dstOk := dstMap[machineIP]; dstOk {
peers[peer.ID] = peer peers[peer.ID] = peer
continue continue
} }
} }
// match source and destination
for _, peerIP := range peerIPs {
for _, dst := range dstMap {
_, cdr, _ := net.ParseCIDR(dst)
ip := net.ParseIP(peerIP)
if dst == peerIP || (cdr != nil && ip != nil && cdr.Contains(ip)) {
peers[peer.ID] = peer
continue
}
}
}
}
}
for _, peerIP := range peerIPs {
if dstMap, ok := aclPeerCacheMap[peerIP]; ok {
// match source and all destination
for _, dst := range dstMap {
if dst == "*" {
peers[peer.ID] = peer
continue
}
}
// match return path
for _, machineIP := range machineIPs {
for _, dst := range dstMap {
_, cdr, _ := net.ParseCIDR(dst)
ip := net.ParseIP(machineIP)
if dst == machineIP || (cdr != nil && ip != nil && cdr.Contains(ip)) {
peers[peer.ID] = peer
continue
}
}
}
} }
} }
} }