mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-07 16:54:16 +01:00
Add SSH accept rule on the client (#924)
This commit is contained in:
parent
4cd9ccb493
commit
5507e1f7a5
@ -9,6 +9,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/firewall"
|
"github.com/netbirdio/netbird/client/firewall"
|
||||||
|
"github.com/netbirdio/netbird/client/ssh"
|
||||||
"github.com/netbirdio/netbird/iface"
|
"github.com/netbirdio/netbird/iface"
|
||||||
mgmProto "github.com/netbirdio/netbird/management/proto"
|
mgmProto "github.com/netbirdio/netbird/management/proto"
|
||||||
)
|
)
|
||||||
@ -45,7 +46,30 @@ func (d *DefaultManager) ApplyFiltering(networkMap *mgmProto.NetworkMap) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rules := d.squashAcceptRules(networkMap)
|
rules, squashedProtocols := d.squashAcceptRules(networkMap)
|
||||||
|
|
||||||
|
enableSSH := (networkMap.PeerConfig != nil &&
|
||||||
|
networkMap.PeerConfig.SshConfig != nil &&
|
||||||
|
networkMap.PeerConfig.SshConfig.SshEnabled)
|
||||||
|
if _, ok := squashedProtocols[mgmProto.FirewallRule_ALL]; ok {
|
||||||
|
enableSSH = enableSSH && !ok
|
||||||
|
}
|
||||||
|
if _, ok := squashedProtocols[mgmProto.FirewallRule_TCP]; ok {
|
||||||
|
enableSSH = enableSSH && !ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// if TCP protocol rules not squashed and SSH enabled
|
||||||
|
// we add default firewall rule which accepts connection to any peer
|
||||||
|
// in the network by SSH (TCP 22 port).
|
||||||
|
if enableSSH {
|
||||||
|
rules = append(rules, &mgmProto.FirewallRule{
|
||||||
|
PeerIP: "0.0.0.0",
|
||||||
|
Direction: mgmProto.FirewallRule_IN,
|
||||||
|
Action: mgmProto.FirewallRule_ACCEPT,
|
||||||
|
Protocol: mgmProto.FirewallRule_TCP,
|
||||||
|
Port: strconv.Itoa(ssh.DefaultSSHPort),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// if we got empty rules list but management not set networkMap.FirewallRulesIsEmpty flag
|
// 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
|
// we have old version of management without rules handling, we should allow all traffic
|
||||||
@ -202,11 +226,13 @@ func (d *DefaultManager) addOutRules(ip net.IP, protocol firewall.Protocol, port
|
|||||||
}
|
}
|
||||||
|
|
||||||
// squashAcceptRules does complex logic to convert many rules which allows connection by traffic type
|
// squashAcceptRules does complex logic to convert many rules which allows connection by traffic type
|
||||||
// to all peers in the network man to one rule which just accepts that type of the traffic.
|
// to all peers in the network map to one rule which just accepts that type of the traffic.
|
||||||
//
|
//
|
||||||
// NOTE: It will not squash two rules for same protocol if one covers all peers in the network,
|
// NOTE: It will not squash two rules for same protocol if one covers all peers in the network,
|
||||||
// but other has port definitions or has drop policy.
|
// but other has port definitions or has drop policy.
|
||||||
func (d *DefaultManager) squashAcceptRules(networkMap *mgmProto.NetworkMap) []*mgmProto.FirewallRule {
|
func (d *DefaultManager) squashAcceptRules(
|
||||||
|
networkMap *mgmProto.NetworkMap,
|
||||||
|
) ([]*mgmProto.FirewallRule, map[mgmProto.FirewallRuleProtocol]struct{}) {
|
||||||
totalIPs := 0
|
totalIPs := 0
|
||||||
for _, p := range networkMap.RemotePeers {
|
for _, p := range networkMap.RemotePeers {
|
||||||
for range p.AllowedIps {
|
for range p.AllowedIps {
|
||||||
@ -293,13 +319,13 @@ func (d *DefaultManager) squashAcceptRules(networkMap *mgmProto.NetworkMap) []*m
|
|||||||
squash(in, mgmProto.FirewallRule_IN)
|
squash(in, mgmProto.FirewallRule_IN)
|
||||||
squash(out, mgmProto.FirewallRule_OUT)
|
squash(out, mgmProto.FirewallRule_OUT)
|
||||||
|
|
||||||
if len(squashedRules) == 0 {
|
|
||||||
return networkMap.FirewallRules
|
|
||||||
}
|
|
||||||
|
|
||||||
// if all protocol was squashed everything is allow and we can ignore all other rules
|
// if all protocol was squashed everything is allow and we can ignore all other rules
|
||||||
if _, ok := squashedProtocols[mgmProto.FirewallRule_ALL]; ok {
|
if _, ok := squashedProtocols[mgmProto.FirewallRule_ALL]; ok {
|
||||||
return squashedRules
|
return squashedRules, squashedProtocols
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(squashedRules) == 0 {
|
||||||
|
return networkMap.FirewallRules, squashedProtocols
|
||||||
}
|
}
|
||||||
|
|
||||||
var rules []*mgmProto.FirewallRule
|
var rules []*mgmProto.FirewallRule
|
||||||
@ -316,7 +342,7 @@ func (d *DefaultManager) squashAcceptRules(networkMap *mgmProto.NetworkMap) []*m
|
|||||||
rules = append(rules, r)
|
rules = append(rules, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(rules, squashedRules...)
|
return append(rules, squashedRules...), squashedProtocols
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertToFirewallProtocol(protocol mgmProto.FirewallRuleProtocol) firewall.Protocol {
|
func convertToFirewallProtocol(protocol mgmProto.FirewallRuleProtocol) firewall.Protocol {
|
||||||
|
@ -168,7 +168,7 @@ func TestDefaultManagerSquashRules(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
manager := &DefaultManager{}
|
manager := &DefaultManager{}
|
||||||
rules := manager.squashAcceptRules(networkMap)
|
rules, _ := manager.squashAcceptRules(networkMap)
|
||||||
if len(rules) != 2 {
|
if len(rules) != 2 {
|
||||||
t.Errorf("rules should contain 2, got: %v", rules)
|
t.Errorf("rules should contain 2, got: %v", rules)
|
||||||
return
|
return
|
||||||
@ -266,7 +266,65 @@ func TestDefaultManagerSquashRulesNoAffect(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
manager := &DefaultManager{}
|
manager := &DefaultManager{}
|
||||||
if rules := manager.squashAcceptRules(networkMap); len(rules) != len(networkMap.FirewallRules) {
|
if rules, _ := manager.squashAcceptRules(networkMap); len(rules) != len(networkMap.FirewallRules) {
|
||||||
t.Errorf("we should got same amount of rules as intput, got %v", len(rules))
|
t.Errorf("we should got same amount of rules as intput, got %v", len(rules))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDefaultManagerEnableSSHRules(t *testing.T) {
|
||||||
|
networkMap := &mgmProto.NetworkMap{
|
||||||
|
PeerConfig: &mgmProto.PeerConfig{
|
||||||
|
SshConfig: &mgmProto.SSHConfig{
|
||||||
|
SshEnabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RemotePeers: []*mgmProto.RemotePeerConfig{
|
||||||
|
{AllowedIps: []string{"10.93.0.1"}},
|
||||||
|
{AllowedIps: []string{"10.93.0.2"}},
|
||||||
|
{AllowedIps: []string{"10.93.0.3"}},
|
||||||
|
},
|
||||||
|
FirewallRules: []*mgmProto.FirewallRule{
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.1",
|
||||||
|
Direction: mgmProto.FirewallRule_IN,
|
||||||
|
Action: mgmProto.FirewallRule_ACCEPT,
|
||||||
|
Protocol: mgmProto.FirewallRule_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.2",
|
||||||
|
Direction: mgmProto.FirewallRule_IN,
|
||||||
|
Action: mgmProto.FirewallRule_ACCEPT,
|
||||||
|
Protocol: mgmProto.FirewallRule_TCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PeerIP: "10.93.0.3",
|
||||||
|
Direction: mgmProto.FirewallRule_OUT,
|
||||||
|
Action: mgmProto.FirewallRule_ACCEPT,
|
||||||
|
Protocol: mgmProto.FirewallRule_UDP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
iface := mocks.NewMockIFaceMapper(ctrl)
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("create ACL manager: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer acl.Stop()
|
||||||
|
|
||||||
|
acl.ApplyFiltering(networkMap)
|
||||||
|
|
||||||
|
if len(acl.rulesPairs) != 4 {
|
||||||
|
t.Errorf("expect 4 rules (last must be SSH), got: %d", len(acl.rulesPairs))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user