mirror of
https://github.com/netbirdio/netbird.git
synced 2024-12-26 16:49:10 +01:00
1012172f04
Handle routes updates from management Manage routing firewall rules Manage peer RIB table Add get peer and get notification channel from the status recorder Update interface peers allowed IPs
248 lines
10 KiB
Go
248 lines
10 KiB
Go
package routemanager
|
|
|
|
import (
|
|
"context"
|
|
"github.com/coreos/go-iptables/iptables"
|
|
"github.com/stretchr/testify/require"
|
|
"testing"
|
|
)
|
|
|
|
func TestIptablesManager_RestoreOrCreateContainers(t *testing.T) {
|
|
|
|
if !isIptablesSupported() {
|
|
t.SkipNow()
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.TODO())
|
|
ipv4Client, _ := iptables.NewWithProtocol(iptables.ProtocolIPv4)
|
|
ipv6Client, _ := iptables.NewWithProtocol(iptables.ProtocolIPv6)
|
|
|
|
manager := &iptablesManager{
|
|
ctx: ctx,
|
|
stop: cancel,
|
|
ipv4Client: ipv4Client,
|
|
ipv6Client: ipv6Client,
|
|
rules: make(map[string]map[string][]string),
|
|
}
|
|
|
|
defer manager.CleanRoutingRules()
|
|
|
|
err := manager.RestoreOrCreateContainers()
|
|
require.NoError(t, err, "shouldn't return error")
|
|
|
|
require.Len(t, manager.rules, 2, "should have created maps for ipv4 and ipv6")
|
|
|
|
require.Len(t, manager.rules[ipv4], 2, "should have created minimal rules for ipv4")
|
|
|
|
exists, err := ipv4Client.Exists(iptablesFilterTable, iptablesForwardChain, manager.rules[ipv4][ipv4Forwarding]...)
|
|
require.NoError(t, err, "should be able to query the iptables %s %s table and %s chain", ipv4, iptablesFilterTable, iptablesForwardChain)
|
|
require.True(t, exists, "forwarding rule should exist")
|
|
|
|
exists, err = ipv4Client.Exists(iptablesNatTable, iptablesPostRoutingChain, manager.rules[ipv4][ipv4Nat]...)
|
|
require.NoError(t, err, "should be able to query the iptables %s %s table and %s chain", ipv4, iptablesNatTable, iptablesPostRoutingChain)
|
|
require.True(t, exists, "postrouting rule should exist")
|
|
|
|
require.Len(t, manager.rules[ipv6], 2, "should have created minimal rules for ipv6")
|
|
|
|
exists, err = ipv6Client.Exists(iptablesFilterTable, iptablesForwardChain, manager.rules[ipv6][ipv6Forwarding]...)
|
|
require.NoError(t, err, "should be able to query the iptables %s %s table and %s chain", ipv6, iptablesFilterTable, iptablesForwardChain)
|
|
require.True(t, exists, "forwarding rule should exist")
|
|
|
|
exists, err = ipv6Client.Exists(iptablesNatTable, iptablesPostRoutingChain, manager.rules[ipv6][ipv6Nat]...)
|
|
require.NoError(t, err, "should be able to query the iptables %s %s table and %s chain", ipv6, iptablesNatTable, iptablesPostRoutingChain)
|
|
require.True(t, exists, "postrouting rule should exist")
|
|
|
|
pair := routerPair{
|
|
ID: "abc",
|
|
source: "100.100.100.1/32",
|
|
destination: "100.100.100.0/24",
|
|
masquerade: true,
|
|
}
|
|
forward4RuleKey := genKey(forwardingFormat, pair.ID)
|
|
forward4Rule := genRuleSpec(routingFinalForwardJump, forward4RuleKey, pair.source, pair.destination)
|
|
|
|
err = ipv4Client.Insert(iptablesFilterTable, iptablesRoutingForwardingChain, 1, forward4Rule...)
|
|
require.NoError(t, err, "inserting rule should not return error")
|
|
|
|
nat4RuleKey := genKey(natFormat, pair.ID)
|
|
nat4Rule := genRuleSpec(routingFinalNatJump, nat4RuleKey, pair.source, pair.destination)
|
|
|
|
err = ipv4Client.Insert(iptablesNatTable, iptablesRoutingNatChain, 1, nat4Rule...)
|
|
require.NoError(t, err, "inserting rule should not return error")
|
|
|
|
pair = routerPair{
|
|
ID: "abc",
|
|
source: "fc00::1/128",
|
|
destination: "fc11::/64",
|
|
masquerade: true,
|
|
}
|
|
|
|
forward6RuleKey := genKey(forwardingFormat, pair.ID)
|
|
forward6Rule := genRuleSpec(routingFinalForwardJump, forward6RuleKey, pair.source, pair.destination)
|
|
|
|
err = ipv6Client.Insert(iptablesFilterTable, iptablesRoutingForwardingChain, 1, forward6Rule...)
|
|
require.NoError(t, err, "inserting rule should not return error")
|
|
|
|
nat6RuleKey := genKey(natFormat, pair.ID)
|
|
nat6Rule := genRuleSpec(routingFinalNatJump, nat6RuleKey, pair.source, pair.destination)
|
|
|
|
err = ipv6Client.Insert(iptablesNatTable, iptablesRoutingNatChain, 1, nat6Rule...)
|
|
require.NoError(t, err, "inserting rule should not return error")
|
|
|
|
delete(manager.rules, ipv4)
|
|
delete(manager.rules, ipv6)
|
|
|
|
err = manager.RestoreOrCreateContainers()
|
|
require.NoError(t, err, "shouldn't return error")
|
|
|
|
require.Len(t, manager.rules[ipv4], 4, "should have restored all rules for ipv4")
|
|
|
|
foundRule, found := manager.rules[ipv4][forward4RuleKey]
|
|
require.True(t, found, "forwarding rule should exist in the map")
|
|
require.Equal(t, forward4Rule[:4], foundRule[:4], "stored forwarding rule should match")
|
|
|
|
foundRule, found = manager.rules[ipv4][nat4RuleKey]
|
|
require.True(t, found, "nat rule should exist in the map")
|
|
require.Equal(t, nat4Rule[:4], foundRule[:4], "stored nat rule should match")
|
|
|
|
require.Len(t, manager.rules[ipv6], 4, "should have restored all rules for ipv6")
|
|
|
|
foundRule, found = manager.rules[ipv6][forward6RuleKey]
|
|
require.True(t, found, "forwarding rule should exist in the map")
|
|
require.Equal(t, forward6Rule[:4], foundRule[:4], "stored forward rule should match")
|
|
|
|
foundRule, found = manager.rules[ipv6][nat6RuleKey]
|
|
require.True(t, found, "nat rule should exist in the map")
|
|
require.Equal(t, nat6Rule[:4], foundRule[:4], "stored nat rule should match")
|
|
}
|
|
|
|
func TestIptablesManager_InsertRoutingRules(t *testing.T) {
|
|
|
|
if !isIptablesSupported() {
|
|
t.SkipNow()
|
|
}
|
|
|
|
for _, testCase := range insertRuleTestCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.TODO())
|
|
ipv4Client, _ := iptables.NewWithProtocol(iptables.ProtocolIPv4)
|
|
ipv6Client, _ := iptables.NewWithProtocol(iptables.ProtocolIPv6)
|
|
iptablesClient := ipv4Client
|
|
if testCase.ipVersion == ipv6 {
|
|
iptablesClient = ipv6Client
|
|
}
|
|
|
|
manager := &iptablesManager{
|
|
ctx: ctx,
|
|
stop: cancel,
|
|
ipv4Client: ipv4Client,
|
|
ipv6Client: ipv6Client,
|
|
rules: make(map[string]map[string][]string),
|
|
}
|
|
|
|
defer manager.CleanRoutingRules()
|
|
|
|
err := manager.RestoreOrCreateContainers()
|
|
require.NoError(t, err, "shouldn't return error")
|
|
|
|
err = manager.InsertRoutingRules(testCase.inputPair)
|
|
require.NoError(t, err, "forwarding pair should be inserted")
|
|
|
|
forwardRuleKey := genKey(forwardingFormat, testCase.inputPair.ID)
|
|
forwardRule := genRuleSpec(routingFinalForwardJump, forwardRuleKey, testCase.inputPair.source, testCase.inputPair.destination)
|
|
|
|
exists, err := iptablesClient.Exists(iptablesFilterTable, iptablesRoutingForwardingChain, forwardRule...)
|
|
require.NoError(t, err, "should be able to query the iptables %s %s table and %s chain", testCase.ipVersion, iptablesFilterTable, iptablesRoutingForwardingChain)
|
|
require.True(t, exists, "forwarding rule should exist")
|
|
|
|
foundRule, found := manager.rules[testCase.ipVersion][forwardRuleKey]
|
|
require.True(t, found, "forwarding rule should exist in the manager map")
|
|
require.Equal(t, forwardRule[:4], foundRule[:4], "stored forwarding rule should match")
|
|
|
|
natRuleKey := genKey(natFormat, testCase.inputPair.ID)
|
|
natRule := genRuleSpec(routingFinalNatJump, natRuleKey, testCase.inputPair.source, testCase.inputPair.destination)
|
|
|
|
exists, err = iptablesClient.Exists(iptablesNatTable, iptablesRoutingNatChain, natRule...)
|
|
require.NoError(t, err, "should be able to query the iptables %s %s table and %s chain", testCase.ipVersion, iptablesNatTable, iptablesRoutingNatChain)
|
|
if testCase.inputPair.masquerade {
|
|
require.True(t, exists, "nat rule should be created")
|
|
foundNatRule, foundNat := manager.rules[testCase.ipVersion][natRuleKey]
|
|
require.True(t, foundNat, "nat rule should exist in the map")
|
|
require.Equal(t, natRule[:4], foundNatRule[:4], "stored nat rule should match")
|
|
} else {
|
|
require.False(t, exists, "nat rule should not be created")
|
|
_, foundNat := manager.rules[testCase.ipVersion][natRuleKey]
|
|
require.False(t, foundNat, "nat rule should exist in the map")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIptablesManager_RemoveRoutingRules(t *testing.T) {
|
|
|
|
if !isIptablesSupported() {
|
|
t.SkipNow()
|
|
}
|
|
|
|
for _, testCase := range removeRuleTestCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.TODO())
|
|
ipv4Client, _ := iptables.NewWithProtocol(iptables.ProtocolIPv4)
|
|
ipv6Client, _ := iptables.NewWithProtocol(iptables.ProtocolIPv6)
|
|
iptablesClient := ipv4Client
|
|
if testCase.ipVersion == ipv6 {
|
|
iptablesClient = ipv6Client
|
|
}
|
|
|
|
manager := &iptablesManager{
|
|
ctx: ctx,
|
|
stop: cancel,
|
|
ipv4Client: ipv4Client,
|
|
ipv6Client: ipv6Client,
|
|
rules: make(map[string]map[string][]string),
|
|
}
|
|
|
|
defer manager.CleanRoutingRules()
|
|
|
|
err := manager.RestoreOrCreateContainers()
|
|
require.NoError(t, err, "shouldn't return error")
|
|
|
|
forwardRuleKey := genKey(forwardingFormat, testCase.inputPair.ID)
|
|
forwardRule := genRuleSpec(routingFinalForwardJump, forwardRuleKey, testCase.inputPair.source, testCase.inputPair.destination)
|
|
|
|
err = iptablesClient.Insert(iptablesFilterTable, iptablesRoutingForwardingChain, 1, forwardRule...)
|
|
require.NoError(t, err, "inserting rule should not return error")
|
|
|
|
natRuleKey := genKey(natFormat, testCase.inputPair.ID)
|
|
natRule := genRuleSpec(routingFinalNatJump, natRuleKey, testCase.inputPair.source, testCase.inputPair.destination)
|
|
|
|
err = iptablesClient.Insert(iptablesNatTable, iptablesRoutingNatChain, 1, natRule...)
|
|
require.NoError(t, err, "inserting rule should not return error")
|
|
|
|
delete(manager.rules, ipv4)
|
|
delete(manager.rules, ipv6)
|
|
|
|
err = manager.RestoreOrCreateContainers()
|
|
require.NoError(t, err, "shouldn't return error")
|
|
|
|
err = manager.RemoveRoutingRules(testCase.inputPair)
|
|
require.NoError(t, err, "shouldn't return error")
|
|
|
|
exists, err := iptablesClient.Exists(iptablesFilterTable, iptablesRoutingForwardingChain, forwardRule...)
|
|
require.NoError(t, err, "should be able to query the iptables %s %s table and %s chain", testCase.ipVersion, iptablesFilterTable, iptablesRoutingForwardingChain)
|
|
require.False(t, exists, "forwarding rule should not exist")
|
|
|
|
_, found := manager.rules[testCase.ipVersion][forwardRuleKey]
|
|
require.False(t, found, "forwarding rule should exist in the manager map")
|
|
|
|
exists, err = iptablesClient.Exists(iptablesNatTable, iptablesRoutingNatChain, natRule...)
|
|
require.NoError(t, err, "should be able to query the iptables %s %s table and %s chain", testCase.ipVersion, iptablesNatTable, iptablesRoutingNatChain)
|
|
require.False(t, exists, "nat rule should not exist")
|
|
|
|
_, found = manager.rules[testCase.ipVersion][natRuleKey]
|
|
require.False(t, found, "forwarding rule should exist in the manager map")
|
|
|
|
})
|
|
}
|
|
}
|