Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add routing peer support #441

Merged
merged 41 commits into from
Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
b913bdb
Add routing peer support
mlsmaycon Aug 24, 2022
115728c
Align Route changes and status new method
mlsmaycon Aug 24, 2022
f2a2fc3
add get peer status test
mlsmaycon Aug 24, 2022
4e4fc8b
Rename methods and types with network
mlsmaycon Aug 24, 2022
3df1399
reorganize code and handle context done
mlsmaycon Aug 27, 2022
aba1ad5
handle errors and make consts and global vars private
mlsmaycon Aug 27, 2022
ffc01f2
handle errors
mlsmaycon Aug 27, 2022
9e249b8
handle iptables errors and document
mlsmaycon Aug 27, 2022
a86726d
unexport consts and types and further docs
mlsmaycon Aug 27, 2022
b090e7c
handle possible default route
mlsmaycon Aug 27, 2022
817cfba
Add status peer update notification
mlsmaycon Aug 27, 2022
a56ecc0
act on peers state changes
mlsmaycon Aug 27, 2022
e11fb07
add route manager to engine
mlsmaycon Aug 27, 2022
ccd6e39
fix lint and codacy comments
mlsmaycon Aug 27, 2022
50907f2
Merge branch 'main' into feature/routing-peers-support
mlsmaycon Aug 28, 2022
1abd480
Ensure we always call UpdateRoutes
mlsmaycon Aug 28, 2022
a45498b
init route manager
mlsmaycon Aug 29, 2022
b81ae21
use protoRoutes
mlsmaycon Aug 29, 2022
ee0abef
remove chosen route if removed route id matches
mlsmaycon Aug 29, 2022
435267a
ensure update events are done in the watch client networks method
mlsmaycon Aug 30, 2022
56517bb
refactor router manager client and server updates
mlsmaycon Aug 31, 2022
b11117d
add sendUpdateToClientNetworkWatcher
mlsmaycon Aug 31, 2022
3586248
Update Readme Network Routes feature naming
braginini Aug 31, 2022
4c01231
check peer state before sending update or removing allowed IPs
mlsmaycon Aug 31, 2022
556894c
update serial in the watcher
mlsmaycon Aug 31, 2022
aa21ac3
Merge remote-tracking branch 'origin/feature/routing-peers-support' i…
mlsmaycon Aug 31, 2022
8baff38
set chosen route nil when no route is chosen
mlsmaycon Aug 31, 2022
e1f4478
clean jump rules before removing chains
mlsmaycon Sep 1, 2022
d837de9
Merge branch 'main' into feature/routing-peers-support
mlsmaycon Sep 3, 2022
f4342ad
Add manager and iptables tests
mlsmaycon Sep 4, 2022
382f631
Add nftables tests
mlsmaycon Sep 4, 2022
1d3d31e
Check if routes exists and routing tests
mlsmaycon Sep 4, 2022
f601f27
remove test sleep
mlsmaycon Sep 4, 2022
869cac8
should test against default gateway interface
mlsmaycon Sep 4, 2022
baca81a
return RouteNotFound error
mlsmaycon Sep 4, 2022
08fcee4
Test if route exist using local gateway response
mlsmaycon Sep 4, 2022
a328adc
remove replace for go-netroute
mlsmaycon Sep 4, 2022
be59748
remove unused constant and just log UpdateRoutes call in engine
mlsmaycon Sep 4, 2022
994e0c0
use route manager interface and rename struct
mlsmaycon Sep 4, 2022
dc4ec2f
Adding route update test
mlsmaycon Sep 4, 2022
e94b217
fix lint notes
mlsmaycon Sep 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ NetBird creates an overlay peer-to-peer network connecting machines automaticall
- \[x] Remote SSH access without managing SSH keys.

**Coming soon:**
- \[ ] Router nodes
- \[ ] Network Routes.
- \[ ] Private DNS.
- \[ ] Mobile clients.
- \[ ] Network Activity Monitoring.
Expand Down
36 changes: 36 additions & 0 deletions client/internal/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package internal
import (
"context"
"fmt"
"github.com/netbirdio/netbird/client/internal/routemanager"
nbssh "github.com/netbirdio/netbird/client/ssh"
nbstatus "github.com/netbirdio/netbird/client/status"
"github.com/netbirdio/netbird/route"
"math/rand"
"net"
"reflect"
Expand Down Expand Up @@ -99,6 +101,8 @@ type Engine struct {
sshServer nbssh.Server

statusRecorder *nbstatus.Status

routeManager routemanager.Manager
}

// Peer is an instance of the Connection Peer
Expand Down Expand Up @@ -182,6 +186,10 @@ func (e *Engine) Stop() error {
}
}

if e.routeManager != nil {
e.routeManager.Stop()
}

log.Infof("stopped Netbird Engine")

return nil
Expand Down Expand Up @@ -232,6 +240,8 @@ func (e *Engine) Start() error {
return err
}

e.routeManager = routemanager.NewManager(e.ctx, e.config.WgPrivateKey.PublicKey().String(), e.wgInterface, e.statusRecorder)

e.receiveSignalEvents()
e.receiveManagementEvents()

Expand Down Expand Up @@ -619,11 +629,37 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap) error {
}
}
}
protoRoutes := networkMap.GetRoutes()
if protoRoutes == nil {
protoRoutes = []*mgmProto.Route{}
}
err := e.routeManager.UpdateRoutes(serial, toRoutes(protoRoutes))
if err != nil {
log.Errorf("failed to update routes, err: %v", err)
}

e.networkSerial = serial
return nil
}

func toRoutes(protoRoutes []*mgmProto.Route) []*route.Route {
routes := make([]*route.Route, 0)
for _, protoRoute := range protoRoutes {
_, prefix, _ := route.ParseNetwork(protoRoute.Network)
convertedRoute := &route.Route{
ID: protoRoute.ID,
Network: prefix,
NetID: protoRoute.NetID,
NetworkType: route.NetworkType(protoRoute.NetworkType),
Peer: protoRoute.Peer,
Metric: int(protoRoute.Metric),
Masquerade: protoRoute.Masquerade,
}
routes = append(routes, convertedRoute)
}
return routes
}

// addNewPeers adds peers that were not know before but arrived from the Management service with the update
func (e *Engine) addNewPeers(peersUpdate []*mgmProto.RemotePeerConfig) error {
for _, p := range peersUpdate {
Expand Down
140 changes: 140 additions & 0 deletions client/internal/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package internal
import (
"context"
"fmt"
"github.com/netbirdio/netbird/client/internal/routemanager"
"github.com/netbirdio/netbird/client/ssh"
nbstatus "github.com/netbirdio/netbird/client/status"
"github.com/netbirdio/netbird/iface"
"github.com/netbirdio/netbird/route"
"github.com/stretchr/testify/assert"
"net"
"net/netip"
"os"
"path/filepath"
"runtime"
Expand Down Expand Up @@ -196,6 +199,7 @@ func TestEngine_UpdateNetworkMap(t *testing.T) {
WgPort: 33100,
}, nbstatus.NewRecorder())
engine.wgInterface, err = iface.NewWGIFace("utun102", "100.64.0.1/24", iface.DefaultMTU)
engine.routeManager = routemanager.NewManager(ctx, key.PublicKey().String(), engine.wgInterface, engine.statusRecorder)
mlsmaycon marked this conversation as resolved.
Show resolved Hide resolved

type testCase struct {
name string
Expand Down Expand Up @@ -426,6 +430,142 @@ func TestEngine_Sync(t *testing.T) {
}
}

func TestEngine_UpdateNetworkMapWithRoutes(t *testing.T) {
testCases := []struct {
name string
inputErr error
networkMap *mgmtProto.NetworkMap
expectedLen int
expectedRoutes []*route.Route
expectedSerial uint64
}{
{
name: "Routes Update Should Be Passed To Manager",
networkMap: &mgmtProto.NetworkMap{
Serial: 1,
PeerConfig: nil,
RemotePeersIsEmpty: false,
Routes: []*mgmtProto.Route{
{
ID: "a",
Network: "192.168.0.0/24",
NetID: "n1",
Peer: "p1",
NetworkType: 1,
Masquerade: false,
},
{
ID: "b",
Network: "192.168.1.0/24",
NetID: "n2",
Peer: "p1",
NetworkType: 1,
Masquerade: false,
},
},
},
expectedLen: 2,
expectedRoutes: []*route.Route{
{
ID: "a",
Network: netip.MustParsePrefix("192.168.0.0/24"),
NetID: "n1",
Peer: "p1",
NetworkType: 1,
Masquerade: false,
},
{
ID: "b",
Network: netip.MustParsePrefix("192.168.1.0/24"),
NetID: "n2",
Peer: "p1",
NetworkType: 1,
Masquerade: false,
},
},
expectedSerial: 1,
},
{
name: "Empty Routes Update Should Be Passed",
networkMap: &mgmtProto.NetworkMap{
Serial: 1,
PeerConfig: nil,
RemotePeersIsEmpty: false,
Routes: nil,
},
expectedLen: 0,
expectedRoutes: []*route.Route{},
expectedSerial: 1,
},
{
name: "Error Shouldn't Break Engine",
inputErr: fmt.Errorf("mocking error"),
networkMap: &mgmtProto.NetworkMap{
Serial: 1,
PeerConfig: nil,
RemotePeersIsEmpty: false,
Routes: nil,
},
expectedLen: 0,
expectedRoutes: []*route.Route{},
expectedSerial: 1,
},
}

for n, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
// test setup
key, err := wgtypes.GeneratePrivateKey()
if err != nil {
t.Fatal(err)
return
}

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

wgIfaceName := fmt.Sprintf("utun%d", 104+n)
wgAddr := fmt.Sprintf("100.66.%d.1/24", n)

engine := NewEngine(ctx, cancel, &signal.MockClient{}, &mgmt.MockClient{}, &EngineConfig{
WgIfaceName: wgIfaceName,
WgAddr: wgAddr,
WgPrivateKey: key,
WgPort: 33100,
}, nbstatus.NewRecorder())
engine.wgInterface, err = iface.NewWGIFace(wgIfaceName, wgAddr, iface.DefaultMTU)
assert.NoError(t, err, "shouldn't return error")
input := struct {
inputSerial uint64
inputRoutes []*route.Route
}{}

mockRouteManager := &routemanager.MockManager{
UpdateRoutesFunc: func(updateSerial uint64, newRoutes []*route.Route) error {
input.inputSerial = updateSerial
input.inputRoutes = newRoutes
return testCase.inputErr
},
}

engine.routeManager = mockRouteManager

defer func() {
exitErr := engine.Stop()
if exitErr != nil {
return
}
}()

err = engine.updateNetworkMap(testCase.networkMap)
assert.NoError(t, err, "shouldn't return error")
assert.Equal(t, testCase.expectedSerial, input.inputSerial, "serial should match")
assert.Len(t, input.inputRoutes, testCase.expectedLen, "routes len should match")
assert.Equal(t, testCase.expectedRoutes, input.inputRoutes, "routes should match")
})
}
}

func TestEngine_MultiplePeers(t *testing.T) {
// log.SetLevel(log.DebugLevel)

Expand Down
Loading