handshake_manager_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package nebula
  2. import (
  3. "net"
  4. "testing"
  5. "time"
  6. "github.com/slackhq/nebula/header"
  7. "github.com/slackhq/nebula/iputil"
  8. "github.com/slackhq/nebula/test"
  9. "github.com/slackhq/nebula/udp"
  10. "github.com/stretchr/testify/assert"
  11. )
  12. func Test_NewHandshakeManagerVpnIp(t *testing.T) {
  13. l := test.NewLogger()
  14. _, tuncidr, _ := net.ParseCIDR("172.1.1.1/24")
  15. _, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
  16. _, localrange, _ := net.ParseCIDR("10.1.1.1/24")
  17. ip := iputil.Ip2VpnIp(net.ParseIP("172.1.1.2"))
  18. preferredRanges := []*net.IPNet{localrange}
  19. mw := &mockEncWriter{}
  20. mainHM := NewHostMap(l, "test", vpncidr, preferredRanges)
  21. lh := &LightHouse{
  22. atomicStaticList: make(map[iputil.VpnIp]struct{}),
  23. atomicLighthouses: make(map[iputil.VpnIp]struct{}),
  24. addrMap: make(map[iputil.VpnIp]*RemoteList),
  25. }
  26. blah := NewHandshakeManager(l, tuncidr, preferredRanges, mainHM, lh, &udp.Conn{}, defaultHandshakeConfig)
  27. now := time.Now()
  28. blah.NextOutboundHandshakeTimerTick(now, mw)
  29. var initCalled bool
  30. initFunc := func(*HostInfo) {
  31. initCalled = true
  32. }
  33. i := blah.AddVpnIp(ip, initFunc)
  34. assert.True(t, initCalled)
  35. initCalled = false
  36. i2 := blah.AddVpnIp(ip, initFunc)
  37. assert.False(t, initCalled)
  38. assert.Same(t, i, i2)
  39. i.remotes = NewRemoteList()
  40. i.HandshakeReady = true
  41. // Adding something to pending should not affect the main hostmap
  42. assert.Len(t, mainHM.Hosts, 0)
  43. // Confirm they are in the pending index list
  44. assert.Contains(t, blah.pendingHostMap.Hosts, ip)
  45. // Jump ahead `HandshakeRetries` ticks, offset by one to get the sleep logic right
  46. for i := 1; i <= DefaultHandshakeRetries+1; i++ {
  47. now = now.Add(time.Duration(i) * DefaultHandshakeTryInterval)
  48. blah.NextOutboundHandshakeTimerTick(now, mw)
  49. }
  50. // Confirm they are still in the pending index list
  51. assert.Contains(t, blah.pendingHostMap.Hosts, ip)
  52. // Tick 1 more time, a minute will certainly flush it out
  53. blah.NextOutboundHandshakeTimerTick(now.Add(time.Minute), mw)
  54. // Confirm they have been removed
  55. assert.NotContains(t, blah.pendingHostMap.Hosts, ip)
  56. }
  57. func Test_NewHandshakeManagerTrigger(t *testing.T) {
  58. l := test.NewLogger()
  59. _, tuncidr, _ := net.ParseCIDR("172.1.1.1/24")
  60. _, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
  61. _, localrange, _ := net.ParseCIDR("10.1.1.1/24")
  62. ip := iputil.Ip2VpnIp(net.ParseIP("172.1.1.2"))
  63. preferredRanges := []*net.IPNet{localrange}
  64. mw := &mockEncWriter{}
  65. mainHM := NewHostMap(l, "test", vpncidr, preferredRanges)
  66. lh := &LightHouse{
  67. addrMap: make(map[iputil.VpnIp]*RemoteList),
  68. l: l,
  69. atomicStaticList: make(map[iputil.VpnIp]struct{}),
  70. atomicLighthouses: make(map[iputil.VpnIp]struct{}),
  71. }
  72. blah := NewHandshakeManager(l, tuncidr, preferredRanges, mainHM, lh, &udp.Conn{}, defaultHandshakeConfig)
  73. now := time.Now()
  74. blah.NextOutboundHandshakeTimerTick(now, mw)
  75. assert.Equal(t, 0, testCountTimerWheelEntries(blah.OutboundHandshakeTimer))
  76. hi := blah.AddVpnIp(ip, nil)
  77. hi.HandshakeReady = true
  78. assert.Equal(t, 1, testCountTimerWheelEntries(blah.OutboundHandshakeTimer))
  79. assert.Equal(t, 0, hi.HandshakeCounter, "Should not have attempted a handshake yet")
  80. // Trigger the same method the channel will but, this should set our remotes pointer
  81. blah.handleOutbound(ip, mw, true)
  82. assert.Equal(t, 1, hi.HandshakeCounter, "Trigger should have done a handshake attempt")
  83. assert.NotNil(t, hi.remotes, "Manager should have set my remotes pointer")
  84. // Make sure the trigger doesn't double schedule the timer entry
  85. assert.Equal(t, 1, testCountTimerWheelEntries(blah.OutboundHandshakeTimer))
  86. uaddr := udp.NewAddrFromString("10.1.1.1:4242")
  87. hi.remotes.unlockedPrependV4(ip, NewIp4AndPort(uaddr.IP, uint32(uaddr.Port)))
  88. // We now have remotes but only the first trigger should have pushed things forward
  89. blah.handleOutbound(ip, mw, true)
  90. assert.Equal(t, 1, hi.HandshakeCounter, "Trigger should have not done a handshake attempt")
  91. assert.Equal(t, 1, testCountTimerWheelEntries(blah.OutboundHandshakeTimer))
  92. }
  93. func testCountTimerWheelEntries(tw *SystemTimerWheel) (c int) {
  94. for _, i := range tw.wheel {
  95. n := i.Head
  96. for n != nil {
  97. c++
  98. n = n.Next
  99. }
  100. }
  101. return c
  102. }
  103. type mockEncWriter struct {
  104. }
  105. func (mw *mockEncWriter) SendMessageToVpnIp(t header.MessageType, st header.MessageSubType, vpnIp iputil.VpnIp, p, nb, out []byte) {
  106. return
  107. }
  108. func (mw *mockEncWriter) SendVia(via interface{}, relay interface{}, ad, nb, out []byte, nocopy bool) {
  109. return
  110. }
  111. func (mw *mockEncWriter) Handshake(vpnIP iputil.VpnIp) {}