Extend protocol and firewall manager to handle old management (#915)

* Extend protocol and firewall manager to handle old management

* Send correct empty firewall rules list when delete peer

* Add extra tests for firewall manager and uspfilter

* Work with inconsistent state

* Review note

* Update comment
This commit is contained in:
Givi Khojanashvili
2023-05-31 21:04:38 +04:00
committed by GitHub
parent 45a6263adc
commit 293499c3c0
13 changed files with 362 additions and 220 deletions

View File

@@ -22,7 +22,7 @@ type iFaceMapper interface {
// Manager is a ACL rules manager
type Manager interface {
ApplyFiltering(rules []*mgmProto.FirewallRule)
ApplyFiltering(rules []*mgmProto.FirewallRule, allowByDefault bool)
Stop()
}
@@ -34,7 +34,9 @@ type DefaultManager struct {
}
// ApplyFiltering firewall rules to the local firewall manager processed by ACL policy.
func (d *DefaultManager) ApplyFiltering(rules []*mgmProto.FirewallRule) {
//
// If allowByDefault is ture it appends allow ALL traffic rules to input and output chains.
func (d *DefaultManager) ApplyFiltering(rules []*mgmProto.FirewallRule, allowByDefault bool) {
d.mutex.Lock()
defer d.mutex.Unlock()
@@ -47,6 +49,22 @@ func (d *DefaultManager) ApplyFiltering(rules []*mgmProto.FirewallRule) {
applyFailed bool
newRulePairs = make(map[string][]firewall.Rule)
)
if allowByDefault {
rules = append(rules,
&mgmProto.FirewallRule{
PeerIP: "0.0.0.0",
Direction: mgmProto.FirewallRule_IN,
Action: mgmProto.FirewallRule_ACCEPT,
Protocol: mgmProto.FirewallRule_ALL,
},
&mgmProto.FirewallRule{
PeerIP: "0.0.0.0",
Direction: mgmProto.FirewallRule_OUT,
Action: mgmProto.FirewallRule_ACCEPT,
Protocol: mgmProto.FirewallRule_ALL,
},
)
}
for _, r := range rules {
rules, err := d.protoRuleToFirewallRule(r)
if err != nil {

View File

@@ -1,7 +1,6 @@
package acl
import (
"runtime"
"testing"
"github.com/golang/mock/gomock"
@@ -11,12 +10,6 @@ import (
)
func TestDefaultManager(t *testing.T) {
// TODO: enable when other platform will be added
if runtime.GOOS != "linux" {
t.Skipf("ACL manager not supported in the: %s", runtime.GOOS)
return
}
fwRules := []*mgmProto.FirewallRule{
{
PeerIP: "10.93.0.1",
@@ -38,8 +31,9 @@ func TestDefaultManager(t *testing.T) {
defer ctrl.Finish()
iface := mocks.NewMockIFaceMapper(ctrl)
iface.EXPECT().IsUserspaceBind().Return(false)
iface.EXPECT().Name().Return("lo")
iface.EXPECT().IsUserspaceBind().Return(true)
// iface.EXPECT().Name().Return("lo")
iface.EXPECT().SetFiltering(gomock.Any())
// we receive one rule from the management so for testing purposes ignore it
acl, err := Create(iface)
@@ -50,7 +44,7 @@ func TestDefaultManager(t *testing.T) {
defer acl.Stop()
t.Run("apply firewall rules", func(t *testing.T) {
acl.ApplyFiltering(fwRules)
acl.ApplyFiltering(fwRules, false)
if len(acl.rulesPairs) != 2 {
t.Errorf("firewall rules not applied: %v", acl.rulesPairs)
@@ -73,7 +67,7 @@ func TestDefaultManager(t *testing.T) {
existedRulesID[id] = struct{}{}
}
acl.ApplyFiltering(fwRules)
acl.ApplyFiltering(fwRules, false)
// we should have one old and one new rule in the existed rules
if len(acl.rulesPairs) != 2 {
@@ -89,4 +83,18 @@ func TestDefaultManager(t *testing.T) {
}
}
})
t.Run("handle default rules", func(t *testing.T) {
acl.ApplyFiltering(nil, false)
if len(acl.rulesPairs) != 0 {
t.Errorf("rules should be empty if default not allowed, got: %v rules", len(acl.rulesPairs))
return
}
acl.ApplyFiltering(nil, true)
if len(acl.rulesPairs) != 2 {
t.Errorf("two default rules should be set if default is allowed, got: %v rules", len(acl.rulesPairs))
return
}
})
}

View File

@@ -637,7 +637,13 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap) error {
}
if e.acl != nil {
e.acl.ApplyFiltering(networkMap.FirewallRules)
// if we got empty rules list but management not set networkMap.FirewallRulesIsEmpty flag
// we have old version of management without rules handling, we should allow all traffic
allowByDefault := len(networkMap.FirewallRules) == 0 && !networkMap.FirewallRulesIsEmpty
if allowByDefault {
log.Warn("this peer is connected to a NetBird Management service with an older version. Allowing all traffic from connected peers")
}
e.acl.ApplyFiltering(networkMap.FirewallRules, allowByDefault)
}
e.networkSerial = serial
return nil