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

[client, management] Add new network concept #3047

Merged
merged 63 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
623fcb0
[management] Add structs for new networks concept (#3006)
pascal-fischer Dec 9, 2024
eb5798e
Migrate networks, network routers and network resource tables
bcmmbaga Dec 9, 2024
0812cc6
[management] Add name attr to network resource (#3011)
pascal-fischer Dec 10, 2024
21eca7e
Merge branch 'feature/new-networks-concept' into add-networks-db-support
bcmmbaga Dec 10, 2024
6a1eda1
Add account networks
bcmmbaga Dec 10, 2024
f9be8f8
Add networks store implementation and tests
bcmmbaga Dec 10, 2024
21586ac
Add network routers in account object
bcmmbaga Dec 10, 2024
6dd6992
Add network routers store implementation
bcmmbaga Dec 10, 2024
3e621b0
Merge branch 'main' into feature/new-networks-concept
pascal-fischer Dec 10, 2024
382dba4
Add network resources store implementation
bcmmbaga Dec 10, 2024
a52ef1a
Add missing network resource in account copy
bcmmbaga Dec 10, 2024
7146fd0
Refactor
bcmmbaga Dec 10, 2024
c7f7908
Fix tests
bcmmbaga Dec 10, 2024
9f859a2
Merge pull request #3015 from netbirdio/add-networks-db-support
bcmmbaga Dec 11, 2024
60ee31d
[management] Add API of new network concept (#3012)
pascal-fischer Dec 11, 2024
ac06f17
Add policy rule source and destination resource
bcmmbaga Dec 11, 2024
9fae103
Extends policy rule API with source and destination resource
bcmmbaga Dec 11, 2024
bde334e
Refactor
bcmmbaga Dec 11, 2024
e5a6f9e
Fix tests
bcmmbaga Dec 11, 2024
9322a92
Refactor the resource and add api helper functions
bcmmbaga Dec 11, 2024
7944b8e
Merge pull request #3025 from netbirdio/feature/add-policy-network-re…
bcmmbaga Dec 11, 2024
d1d6875
[management] Add managers to link networks API with store (#3022)
pascal-fischer Dec 12, 2024
4db4494
Rename CLI commands and status output with the new network concept. (…
mlsmaycon Dec 12, 2024
6bd9352
[management] Allow resources in groups (#3030)
pascal-fischer Dec 12, 2024
86352f0
Rename GUI menu options and route selection with new network concept …
mlsmaycon Dec 12, 2024
e436c39
[management] Add routing peer counter (#3036)
pascal-fischer Dec 13, 2024
a145f0b
[management] Add settings for routing peer dns resolution (#3040)
pascal-fischer Dec 13, 2024
c91d780
Add dns interceptor based domain route functionality (#3032)
pappz Dec 13, 2024
2fa1433
Use DNS route feature flag (#3048)
pappz Dec 14, 2024
958650c
Merge branch 'main' into feature/new-networks-concept
lixmal Dec 14, 2024
4aa13c6
Merge branch 'main' into feature/new-networks-concept
pascal-fischer Dec 16, 2024
ffe0a11
[management] Add tests for networks managers (#3049)
pascal-fischer Dec 17, 2024
12ae7ff
[management] Remove resource from groups when resource deleted (#3059)
pascal-fischer Dec 17, 2024
712341e
[management] add update account peers hook (#3060)
pascal-fischer Dec 17, 2024
228672a
[management] Parse resource addr before db write (#3061)
pascal-fischer Dec 17, 2024
21ba6ad
Improve dns forwarder errors and improve domain anonymization (#3052)
lixmal Dec 17, 2024
cbd333a
[management] Revert to using address field in api (#3064)
pascal-fischer Dec 17, 2024
bcf32f2
[management] Generate network map for new network concept (#3044)
bcmmbaga Dec 17, 2024
e8f7b7f
Refactor router peer validation
bcmmbaga Dec 17, 2024
b539350
[management] properly add and remove resources from groups (#3067)
pascal-fischer Dec 18, 2024
e40eb91
[management] add activity events for networks (#3069)
pascal-fischer Dec 18, 2024
3467670
[management] Include related policies into networks (#3070)
pascal-fischer Dec 18, 2024
49c32e2
Fix dns forwarder update (#3068)
lixmal Dec 18, 2024
be341db
Merge branch 'feature/new-networks-concept' into refactor/new-concept…
bcmmbaga Dec 18, 2024
dfa453a
convert resource to route if resource has policy
bcmmbaga Dec 18, 2024
57eac88
wip: generate routes for resource with no policy
bcmmbaga Dec 18, 2024
400a138
wip: add missing routers
mlsmaycon Dec 18, 2024
7ba6634
fix tests
bcmmbaga Dec 18, 2024
a9360dc
Removed unused code and filter network resources HA routes
bcmmbaga Dec 18, 2024
9faf672
Add tests
bcmmbaga Dec 18, 2024
a1c0e54
using policy for network resource
mlsmaycon Dec 18, 2024
2b12560
set -p 1
mlsmaycon Dec 18, 2024
d5e4d0c
[management] fix group resource events (#3075)
pascal-fischer Dec 18, 2024
e302ce9
[management] increase network serial on change of networks (#3077)
pascal-fischer Dec 18, 2024
858bb8b
Pass an account map of resource policies (#3078)
mlsmaycon Dec 19, 2024
b71eb4c
Update domains on startup (#3079)
lixmal Dec 19, 2024
eecf763
Merge branch 'feature/new-networks-concept' into refactor/new-concept…
bcmmbaga Dec 19, 2024
2714433
Merge pull request #3066 from netbirdio/refactor/new-concept-netmap-gen
bcmmbaga Dec 19, 2024
20a5147
[management] fix deadlock in networks concept (#3083)
pascal-fischer Dec 19, 2024
b7fea2c
fix routing peer lookup
pascal-fischer Dec 19, 2024
394c439
fix router map generation
pascal-fischer Dec 19, 2024
7972e25
[management] Fix event meta (#3086)
pascal-fischer Dec 20, 2024
d80500e
[management] Account for routing source peers (#3088)
pascal-fischer Dec 20, 2024
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 .github/workflows/golang-test-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ jobs:
run: git --no-pager diff --exit-code

- name: Test
run: CGO_ENABLED=1 GOARCH=${{ matrix.arch }} NETBIRD_STORE_ENGINE=${{ matrix.store }} CI=true go test -run=^$ -bench=. -exec 'sudo --preserve-env=CI,NETBIRD_STORE_ENGINE' -timeout 10m ./...
run: CGO_ENABLED=1 GOARCH=${{ matrix.arch }} NETBIRD_STORE_ENGINE=${{ matrix.store }} CI=true go test -run=^$ -bench=. -exec 'sudo --preserve-env=CI,NETBIRD_STORE_ENGINE' -timeout 10m -p 1 ./...

test_client_on_docker:
needs: [ build-cache ]
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: sudo apt update && sudo apt install -y -q libgtk-3-dev libayatana-appindicator3-dev libgl1-mesa-dev xorg-dev libpcap-dev
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v4
with:
version: latest
args: --timeout=12m
args: --timeout=12m --out-format colored-line-number
15 changes: 7 additions & 8 deletions client/anonymize/anonymize.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type Anonymizer struct {
currentAnonIPv6 netip.Addr
startAnonIPv4 netip.Addr
startAnonIPv6 netip.Addr

domainKeyRegex *regexp.Regexp
}

func DefaultAddresses() (netip.Addr, netip.Addr) {
Expand All @@ -36,6 +38,8 @@ func NewAnonymizer(startIPv4, startIPv6 netip.Addr) *Anonymizer {
currentAnonIPv6: startIPv6,
startAnonIPv4: startIPv4,
startAnonIPv6: startIPv6,

domainKeyRegex: regexp.MustCompile(`\bdomain=([^\s,:"]+)`),
}
}

Expand Down Expand Up @@ -171,20 +175,15 @@ func (a *Anonymizer) AnonymizeSchemeURI(text string) string {
return re.ReplaceAllStringFunc(text, a.AnonymizeURI)
}

// AnonymizeDNSLogLine anonymizes domain names in DNS log entries by replacing them with a random string.
func (a *Anonymizer) AnonymizeDNSLogLine(logEntry string) string {
domainPattern := `dns\.Question{Name:"([^"]+)",`
domainRegex := regexp.MustCompile(domainPattern)

return domainRegex.ReplaceAllStringFunc(logEntry, func(match string) string {
parts := strings.Split(match, `"`)
return a.domainKeyRegex.ReplaceAllStringFunc(logEntry, func(match string) string {
parts := strings.SplitN(match, "=", 2)
if len(parts) >= 2 {
domain := parts[1]
if strings.HasSuffix(domain, anonTLD) {
return match
}
randomDomain := generateRandomString(10) + anonTLD
return strings.Replace(match, domain, randomDomain, 1)
return "domain=" + a.AnonymizeDomain(domain)
}
return match
})
Expand Down
56 changes: 52 additions & 4 deletions client/anonymize/anonymize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,59 @@ func TestAnonymizeIP(t *testing.T) {

func TestAnonymizeDNSLogLine(t *testing.T) {
anonymizer := anonymize.NewAnonymizer(netip.Addr{}, netip.Addr{})
testLog := `2024-04-23T20:01:11+02:00 TRAC client/internal/dns/local.go:25: received question: dns.Question{Name:"example.com", Qtype:0x1c, Qclass:0x1}`
tests := []struct {
name string
input string
original string
expect string
}{
{
name: "Basic domain with trailing content",
input: "received DNS request for DNS forwarder: domain=example.com: something happened with code=123",
original: "example.com",
expect: `received DNS request for DNS forwarder: domain=anon-[a-zA-Z0-9]+\.domain: something happened with code=123`,
},
{
name: "Domain with trailing dot",
input: "domain=example.com. processing request with status=pending",
original: "example.com",
expect: `domain=anon-[a-zA-Z0-9]+\.domain\. processing request with status=pending`,
},
{
name: "Multiple domains in log",
input: "forward domain=first.com status=ok, redirect to domain=second.com port=443",
original: "first.com", // testing just one is sufficient as AnonymizeDomain is tested separately
expect: `forward domain=anon-[a-zA-Z0-9]+\.domain status=ok, redirect to domain=anon-[a-zA-Z0-9]+\.domain port=443`,
},
{
name: "Already anonymized domain",
input: "got request domain=anon-xyz123.domain from=client1 to=server2",
original: "", // nothing should be anonymized
expect: `got request domain=anon-xyz123\.domain from=client1 to=server2`,
},
{
name: "Subdomain with trailing dot",
input: "domain=sub.example.com. next_hop=10.0.0.1 proto=udp",
original: "example.com",
expect: `domain=sub\.anon-[a-zA-Z0-9]+\.domain\. next_hop=10\.0\.0\.1 proto=udp`,
},
{
name: "Handler chain pattern log",
input: "pattern: domain=example.com. original: domain=*.example.com. wildcard=true priority=100",
original: "example.com",
expect: `pattern: domain=anon-[a-zA-Z0-9]+\.domain\. original: domain=\*\.anon-[a-zA-Z0-9]+\.domain\. wildcard=true priority=100`,
},
}

result := anonymizer.AnonymizeDNSLogLine(testLog)
require.NotEqual(t, testLog, result)
assert.NotContains(t, result, "example.com")
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result := anonymizer.AnonymizeDNSLogLine(tc.input)
if tc.original != "" {
assert.NotContains(t, result, tc.original)
}
assert.Regexp(t, tc.expect, result)
})
}
}

func TestAnonymizeDomain(t *testing.T) {
Expand Down
173 changes: 173 additions & 0 deletions client/cmd/networks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package cmd

import (
"fmt"
"strings"

"github.com/spf13/cobra"
"google.golang.org/grpc/status"

"github.com/netbirdio/netbird/client/proto"
)

var appendFlag bool

var networksCMD = &cobra.Command{
Use: "networks",
Aliases: []string{"routes"},
Short: "Manage networks",
Long: `Commands to list, select, or deselect networks. Replaces the "routes" command.`,
}

var routesListCmd = &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List networks",
Example: " netbird networks list",
Long: "List all available network routes.",
RunE: networksList,
}

var routesSelectCmd = &cobra.Command{
Use: "select network...|all",
Short: "Select network",
Long: "Select a list of networks by identifiers or 'all' to clear all selections and to accept all (including new) networks.\nDefault mode is replace, use -a to append to already selected networks.",
Example: " netbird networks select all\n netbird networks select route1 route2\n netbird routes select -a route3",
Args: cobra.MinimumNArgs(1),
RunE: networksSelect,
}

var routesDeselectCmd = &cobra.Command{
Use: "deselect network...|all",
Short: "Deselect networks",
Long: "Deselect previously selected networks by identifiers or 'all' to disable accepting any networks.",
Example: " netbird networks deselect all\n netbird networks deselect route1 route2",
Args: cobra.MinimumNArgs(1),
RunE: networksDeselect,
}

func init() {
routesSelectCmd.PersistentFlags().BoolVarP(&appendFlag, "append", "a", false, "Append to current network selection instead of replacing")
}

func networksList(cmd *cobra.Command, _ []string) error {
conn, err := getClient(cmd)
if err != nil {
return err
}
defer conn.Close()

client := proto.NewDaemonServiceClient(conn)
resp, err := client.ListNetworks(cmd.Context(), &proto.ListNetworksRequest{})
if err != nil {
return fmt.Errorf("failed to list network: %v", status.Convert(err).Message())
}

if len(resp.Routes) == 0 {
cmd.Println("No networks available.")
return nil
}

printNetworks(cmd, resp)

return nil
}

func printNetworks(cmd *cobra.Command, resp *proto.ListNetworksResponse) {
cmd.Println("Available Networks:")
for _, route := range resp.Routes {
printNetwork(cmd, route)
}
}

func printNetwork(cmd *cobra.Command, route *proto.Network) {
selectedStatus := getSelectedStatus(route)
domains := route.GetDomains()

if len(domains) > 0 {
printDomainRoute(cmd, route, domains, selectedStatus)
} else {
printNetworkRoute(cmd, route, selectedStatus)
}
}

func getSelectedStatus(route *proto.Network) string {
if route.GetSelected() {
return "Selected"
}
return "Not Selected"
}

func printDomainRoute(cmd *cobra.Command, route *proto.Network, domains []string, selectedStatus string) {
cmd.Printf("\n - ID: %s\n Domains: %s\n Status: %s\n", route.GetID(), strings.Join(domains, ", "), selectedStatus)
resolvedIPs := route.GetResolvedIPs()

if len(resolvedIPs) > 0 {
printResolvedIPs(cmd, domains, resolvedIPs)
} else {
cmd.Printf(" Resolved IPs: -\n")
}
}

func printNetworkRoute(cmd *cobra.Command, route *proto.Network, selectedStatus string) {
cmd.Printf("\n - ID: %s\n Network: %s\n Status: %s\n", route.GetID(), route.GetRange(), selectedStatus)
}

func printResolvedIPs(cmd *cobra.Command, _ []string, resolvedIPs map[string]*proto.IPList) {
cmd.Printf(" Resolved IPs:\n")
for resolvedDomain, ipList := range resolvedIPs {
cmd.Printf(" [%s]: %s\n", resolvedDomain, strings.Join(ipList.GetIps(), ", "))
}
}

func networksSelect(cmd *cobra.Command, args []string) error {
conn, err := getClient(cmd)
if err != nil {
return err
}
defer conn.Close()

client := proto.NewDaemonServiceClient(conn)
req := &proto.SelectNetworksRequest{
NetworkIDs: args,
}

if len(args) == 1 && args[0] == "all" {
req.All = true
} else if appendFlag {
req.Append = true
}

if _, err := client.SelectNetworks(cmd.Context(), req); err != nil {
return fmt.Errorf("failed to select networks: %v", status.Convert(err).Message())
}

cmd.Println("Networks selected successfully.")

return nil
}

func networksDeselect(cmd *cobra.Command, args []string) error {
conn, err := getClient(cmd)
if err != nil {
return err
}
defer conn.Close()

client := proto.NewDaemonServiceClient(conn)
req := &proto.SelectNetworksRequest{
NetworkIDs: args,
}

if len(args) == 1 && args[0] == "all" {
req.All = true
}

if _, err := client.DeselectNetworks(cmd.Context(), req); err != nil {
return fmt.Errorf("failed to deselect networks: %v", status.Convert(err).Message())
}

cmd.Println("Networks deselected successfully.")

return nil
}
6 changes: 3 additions & 3 deletions client/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@ func init() {
rootCmd.AddCommand(loginCmd)
rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(sshCmd)
rootCmd.AddCommand(routesCmd)
rootCmd.AddCommand(networksCMD)
rootCmd.AddCommand(debugCmd)

serviceCmd.AddCommand(runCmd, startCmd, stopCmd, restartCmd) // service control commands are subcommands of service
serviceCmd.AddCommand(installCmd, uninstallCmd) // service installer commands are subcommands of service

routesCmd.AddCommand(routesListCmd)
routesCmd.AddCommand(routesSelectCmd, routesDeselectCmd)
networksCMD.AddCommand(routesListCmd)
networksCMD.AddCommand(routesSelectCmd, routesDeselectCmd)

debugCmd.AddCommand(debugBundleCmd)
debugCmd.AddCommand(logCmd)
Expand Down
Loading
Loading