File: handshake_manager_test.go

package info (click to toggle)
nebula 1.6.1%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,376 kB
  • sloc: makefile: 149; sh: 100; python: 16
file content (140 lines) | stat: -rw-r--r-- 4,514 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package nebula

import (
	"net"
	"testing"
	"time"

	"github.com/slackhq/nebula/header"
	"github.com/slackhq/nebula/iputil"
	"github.com/slackhq/nebula/test"
	"github.com/slackhq/nebula/udp"
	"github.com/stretchr/testify/assert"
)

func Test_NewHandshakeManagerVpnIp(t *testing.T) {
	l := test.NewLogger()
	_, tuncidr, _ := net.ParseCIDR("172.1.1.1/24")
	_, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
	_, localrange, _ := net.ParseCIDR("10.1.1.1/24")
	ip := iputil.Ip2VpnIp(net.ParseIP("172.1.1.2"))
	preferredRanges := []*net.IPNet{localrange}
	mw := &mockEncWriter{}
	mainHM := NewHostMap(l, "test", vpncidr, preferredRanges)
	lh := &LightHouse{
		atomicStaticList:  make(map[iputil.VpnIp]struct{}),
		atomicLighthouses: make(map[iputil.VpnIp]struct{}),
		addrMap:           make(map[iputil.VpnIp]*RemoteList),
	}

	blah := NewHandshakeManager(l, tuncidr, preferredRanges, mainHM, lh, &udp.Conn{}, defaultHandshakeConfig)

	now := time.Now()
	blah.NextOutboundHandshakeTimerTick(now, mw)

	var initCalled bool
	initFunc := func(*HostInfo) {
		initCalled = true
	}

	i := blah.AddVpnIp(ip, initFunc)
	assert.True(t, initCalled)

	initCalled = false
	i2 := blah.AddVpnIp(ip, initFunc)
	assert.False(t, initCalled)
	assert.Same(t, i, i2)

	i.remotes = NewRemoteList()
	i.HandshakeReady = true

	// Adding something to pending should not affect the main hostmap
	assert.Len(t, mainHM.Hosts, 0)

	// Confirm they are in the pending index list
	assert.Contains(t, blah.pendingHostMap.Hosts, ip)

	// Jump ahead `HandshakeRetries` ticks, offset by one to get the sleep logic right
	for i := 1; i <= DefaultHandshakeRetries+1; i++ {
		now = now.Add(time.Duration(i) * DefaultHandshakeTryInterval)
		blah.NextOutboundHandshakeTimerTick(now, mw)
	}

	// Confirm they are still in the pending index list
	assert.Contains(t, blah.pendingHostMap.Hosts, ip)

	// Tick 1 more time, a minute will certainly flush it out
	blah.NextOutboundHandshakeTimerTick(now.Add(time.Minute), mw)

	// Confirm they have been removed
	assert.NotContains(t, blah.pendingHostMap.Hosts, ip)
}

func Test_NewHandshakeManagerTrigger(t *testing.T) {
	l := test.NewLogger()
	_, tuncidr, _ := net.ParseCIDR("172.1.1.1/24")
	_, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
	_, localrange, _ := net.ParseCIDR("10.1.1.1/24")
	ip := iputil.Ip2VpnIp(net.ParseIP("172.1.1.2"))
	preferredRanges := []*net.IPNet{localrange}
	mw := &mockEncWriter{}
	mainHM := NewHostMap(l, "test", vpncidr, preferredRanges)
	lh := &LightHouse{
		addrMap:           make(map[iputil.VpnIp]*RemoteList),
		l:                 l,
		atomicStaticList:  make(map[iputil.VpnIp]struct{}),
		atomicLighthouses: make(map[iputil.VpnIp]struct{}),
	}

	blah := NewHandshakeManager(l, tuncidr, preferredRanges, mainHM, lh, &udp.Conn{}, defaultHandshakeConfig)

	now := time.Now()
	blah.NextOutboundHandshakeTimerTick(now, mw)

	assert.Equal(t, 0, testCountTimerWheelEntries(blah.OutboundHandshakeTimer))

	hi := blah.AddVpnIp(ip, nil)
	hi.HandshakeReady = true
	assert.Equal(t, 1, testCountTimerWheelEntries(blah.OutboundHandshakeTimer))
	assert.Equal(t, 0, hi.HandshakeCounter, "Should not have attempted a handshake yet")

	// Trigger the same method the channel will but, this should set our remotes pointer
	blah.handleOutbound(ip, mw, true)
	assert.Equal(t, 1, hi.HandshakeCounter, "Trigger should have done a handshake attempt")
	assert.NotNil(t, hi.remotes, "Manager should have set my remotes pointer")

	// Make sure the trigger doesn't double schedule the timer entry
	assert.Equal(t, 1, testCountTimerWheelEntries(blah.OutboundHandshakeTimer))

	uaddr := udp.NewAddrFromString("10.1.1.1:4242")
	hi.remotes.unlockedPrependV4(ip, NewIp4AndPort(uaddr.IP, uint32(uaddr.Port)))

	// We now have remotes but only the first trigger should have pushed things forward
	blah.handleOutbound(ip, mw, true)
	assert.Equal(t, 1, hi.HandshakeCounter, "Trigger should have not done a handshake attempt")
	assert.Equal(t, 1, testCountTimerWheelEntries(blah.OutboundHandshakeTimer))
}

func testCountTimerWheelEntries(tw *SystemTimerWheel) (c int) {
	for _, i := range tw.wheel {
		n := i.Head
		for n != nil {
			c++
			n = n.Next
		}
	}
	return c
}

type mockEncWriter struct {
}

func (mw *mockEncWriter) SendMessageToVpnIp(t header.MessageType, st header.MessageSubType, vpnIp iputil.VpnIp, p, nb, out []byte) {
	return
}

func (mw *mockEncWriter) SendVia(via interface{}, relay interface{}, ad, nb, out []byte, nocopy bool) {
	return
}

func (mw *mockEncWriter) Handshake(vpnIP iputil.VpnIp) {}