Skip to content

Commit 3cdb10c

Browse files
authored
[client] Remove rule squashing (#4653)
1 parent af95aab commit 3cdb10c

File tree

3 files changed

+3
-641
lines changed

3 files changed

+3
-641
lines changed

client/firewall/iptables/acl_linux.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,6 @@ func transformIPsetName(ipsetName string, sPort, dPort *firewall.Port, action fi
400400
return ""
401401
}
402402

403-
// Include action in the ipset name to prevent squashing rules with different actions
404403
actionSuffix := ""
405404
if action == firewall.ActionDrop {
406405
actionSuffix = "-drop"

client/internal/acl/manager.go

Lines changed: 3 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ type Manager interface {
2929
ApplyFiltering(networkMap *mgmProto.NetworkMap, dnsRouteFeatureFlag bool)
3030
}
3131

32-
type protoMatch struct {
33-
ips map[string]int
34-
policyID []byte
35-
}
36-
3732
// DefaultManager uses firewall manager to handle
3833
type DefaultManager struct {
3934
firewall firewall.Manager
@@ -86,21 +81,14 @@ func (d *DefaultManager) ApplyFiltering(networkMap *mgmProto.NetworkMap, dnsRout
8681
}
8782

8883
func (d *DefaultManager) applyPeerACLs(networkMap *mgmProto.NetworkMap) {
89-
rules, squashedProtocols := d.squashAcceptRules(networkMap)
84+
rules := networkMap.FirewallRules
9085

9186
enableSSH := networkMap.PeerConfig != nil &&
9287
networkMap.PeerConfig.SshConfig != nil &&
9388
networkMap.PeerConfig.SshConfig.SshEnabled
94-
if _, ok := squashedProtocols[mgmProto.RuleProtocol_ALL]; ok {
95-
enableSSH = enableSSH && !ok
96-
}
97-
if _, ok := squashedProtocols[mgmProto.RuleProtocol_TCP]; ok {
98-
enableSSH = enableSSH && !ok
99-
}
10089

101-
// if TCP protocol rules not squashed and SSH enabled
102-
// we add default firewall rule which accepts connection to any peer
103-
// in the network by SSH (TCP 22 port).
90+
// If SSH enabled, add default firewall rule which accepts connection to any peer
91+
// in the network by SSH (TCP port defined by ssh.DefaultSSHPort).
10492
if enableSSH {
10593
rules = append(rules, &mgmProto.FirewallRule{
10694
PeerIP: "0.0.0.0",
@@ -368,145 +356,6 @@ func (d *DefaultManager) getPeerRuleID(
368356
return id.RuleID(hex.EncodeToString(md5.New().Sum([]byte(idStr))))
369357
}
370358

371-
// squashAcceptRules does complex logic to convert many rules which allows connection by traffic type
372-
// to all peers in the network map to one rule which just accepts that type of the traffic.
373-
//
374-
// NOTE: It will not squash two rules for same protocol if one covers all peers in the network,
375-
// but other has port definitions or has drop policy.
376-
func (d *DefaultManager) squashAcceptRules(
377-
networkMap *mgmProto.NetworkMap,
378-
) ([]*mgmProto.FirewallRule, map[mgmProto.RuleProtocol]struct{}) {
379-
totalIPs := 0
380-
for _, p := range append(networkMap.RemotePeers, networkMap.OfflinePeers...) {
381-
for range p.AllowedIps {
382-
totalIPs++
383-
}
384-
}
385-
386-
in := map[mgmProto.RuleProtocol]*protoMatch{}
387-
out := map[mgmProto.RuleProtocol]*protoMatch{}
388-
389-
// trace which type of protocols was squashed
390-
squashedRules := []*mgmProto.FirewallRule{}
391-
squashedProtocols := map[mgmProto.RuleProtocol]struct{}{}
392-
393-
// this function we use to do calculation, can we squash the rules by protocol or not.
394-
// We summ amount of Peers IP for given protocol we found in original rules list.
395-
// But we zeroed the IP's for protocol if:
396-
// 1. Any of the rule has DROP action type.
397-
// 2. Any of rule contains Port.
398-
//
399-
// We zeroed this to notify squash function that this protocol can't be squashed.
400-
addRuleToCalculationMap := func(i int, r *mgmProto.FirewallRule, protocols map[mgmProto.RuleProtocol]*protoMatch) {
401-
hasPortRestrictions := r.Action == mgmProto.RuleAction_DROP ||
402-
r.Port != "" || !portInfoEmpty(r.PortInfo)
403-
404-
if hasPortRestrictions {
405-
// Don't squash rules with port restrictions
406-
protocols[r.Protocol] = &protoMatch{ips: map[string]int{}}
407-
return
408-
}
409-
410-
if _, ok := protocols[r.Protocol]; !ok {
411-
protocols[r.Protocol] = &protoMatch{
412-
ips: map[string]int{},
413-
// store the first encountered PolicyID for this protocol
414-
policyID: r.PolicyID,
415-
}
416-
}
417-
418-
// special case, when we receive this all network IP address
419-
// it means that rules for that protocol was already optimized on the
420-
// management side
421-
if r.PeerIP == "0.0.0.0" {
422-
squashedRules = append(squashedRules, r)
423-
squashedProtocols[r.Protocol] = struct{}{}
424-
return
425-
}
426-
427-
ipset := protocols[r.Protocol].ips
428-
429-
if _, ok := ipset[r.PeerIP]; ok {
430-
return
431-
}
432-
ipset[r.PeerIP] = i
433-
}
434-
435-
for i, r := range networkMap.FirewallRules {
436-
// calculate squash for different directions
437-
if r.Direction == mgmProto.RuleDirection_IN {
438-
addRuleToCalculationMap(i, r, in)
439-
} else {
440-
addRuleToCalculationMap(i, r, out)
441-
}
442-
}
443-
444-
// order of squashing by protocol is important
445-
// only for their first element ALL, it must be done first
446-
protocolOrders := []mgmProto.RuleProtocol{
447-
mgmProto.RuleProtocol_ALL,
448-
mgmProto.RuleProtocol_ICMP,
449-
mgmProto.RuleProtocol_TCP,
450-
mgmProto.RuleProtocol_UDP,
451-
}
452-
453-
squash := func(matches map[mgmProto.RuleProtocol]*protoMatch, direction mgmProto.RuleDirection) {
454-
for _, protocol := range protocolOrders {
455-
match, ok := matches[protocol]
456-
if !ok || len(match.ips) != totalIPs || len(match.ips) < 2 {
457-
// don't squash if :
458-
// 1. Rules not cover all peers in the network
459-
// 2. Rules cover only one peer in the network.
460-
continue
461-
}
462-
463-
// add special rule 0.0.0.0 which allows all IP's in our firewall implementations
464-
squashedRules = append(squashedRules, &mgmProto.FirewallRule{
465-
PeerIP: "0.0.0.0",
466-
Direction: direction,
467-
Action: mgmProto.RuleAction_ACCEPT,
468-
Protocol: protocol,
469-
PolicyID: match.policyID,
470-
})
471-
squashedProtocols[protocol] = struct{}{}
472-
473-
if protocol == mgmProto.RuleProtocol_ALL {
474-
// if we have ALL traffic type squashed rule
475-
// it allows all other type of traffic, so we can stop processing
476-
break
477-
}
478-
}
479-
}
480-
481-
squash(in, mgmProto.RuleDirection_IN)
482-
squash(out, mgmProto.RuleDirection_OUT)
483-
484-
// if all protocol was squashed everything is allow and we can ignore all other rules
485-
if _, ok := squashedProtocols[mgmProto.RuleProtocol_ALL]; ok {
486-
return squashedRules, squashedProtocols
487-
}
488-
489-
if len(squashedRules) == 0 {
490-
return networkMap.FirewallRules, squashedProtocols
491-
}
492-
493-
var rules []*mgmProto.FirewallRule
494-
// filter out rules which was squashed from final list
495-
// if we also have other not squashed rules.
496-
for i, r := range networkMap.FirewallRules {
497-
if _, ok := squashedProtocols[r.Protocol]; ok {
498-
if m, ok := in[r.Protocol]; ok && m.ips[r.PeerIP] == i {
499-
continue
500-
} else if m, ok := out[r.Protocol]; ok && m.ips[r.PeerIP] == i {
501-
continue
502-
}
503-
}
504-
rules = append(rules, r)
505-
}
506-
507-
return append(rules, squashedRules...), squashedProtocols
508-
}
509-
510359
// getRuleGroupingSelector takes all rule properties except IP address to build selector
511360
func (d *DefaultManager) getRuleGroupingSelector(rule *mgmProto.FirewallRule) string {
512361
return fmt.Sprintf("%v:%v:%v:%s:%v", strconv.Itoa(int(rule.Direction)), rule.Action, rule.Protocol, rule.Port, rule.PortInfo)

0 commit comments

Comments
 (0)