Browse Source

add configuration options for HandshakeManager (#179)

This change exposes the current constants we have defined for the handshake
manager as configuration options. This will allow us to test and tweak
with different intervals and wait rotations.

    # Handshake Manger Settings
    handshakes:
      # Total time to try a handshake = sequence of `try_interval * retries`
      # With 100ms interval and 20 retries it is 23.5 seconds
      try_interval: 100ms
      retries: 20

      # wait_rotation is the number of handshake attempts to do before starting to try non-local IP addresses
      wait_rotation: 5
Wade Simmons 5 năm trước cách đây
mục cha
commit
179a369130

+ 2 - 2
connection_manager_test.go

@@ -36,7 +36,7 @@ func Test_NewConnectionManagerTest(t *testing.T) {
 		certState:        cs,
 		certState:        cs,
 		firewall:         &Firewall{},
 		firewall:         &Firewall{},
 		lightHouse:       lh,
 		lightHouse:       lh,
-		handshakeManager: NewHandshakeManager(vpncidr, preferredRanges, hostMap, lh, &udpConn{}),
+		handshakeManager: NewHandshakeManager(vpncidr, preferredRanges, hostMap, lh, &udpConn{}, defaultHandshakeConfig),
 	}
 	}
 	now := time.Now()
 	now := time.Now()
 
 
@@ -99,7 +99,7 @@ func Test_NewConnectionManagerTest2(t *testing.T) {
 		certState:        cs,
 		certState:        cs,
 		firewall:         &Firewall{},
 		firewall:         &Firewall{},
 		lightHouse:       lh,
 		lightHouse:       lh,
-		handshakeManager: NewHandshakeManager(vpncidr, preferredRanges, hostMap, lh, &udpConn{}),
+		handshakeManager: NewHandshakeManager(vpncidr, preferredRanges, hostMap, lh, &udpConn{}, defaultHandshakeConfig),
 	}
 	}
 	now := time.Now()
 	now := time.Now()
 
 

+ 9 - 0
examples/config.yml

@@ -139,6 +139,15 @@ logging:
   #subsystem: nebula
   #subsystem: nebula
   #interval: 10s
   #interval: 10s
 
 
+# Handshake Manger Settings
+#handshakes:
+  # Total time to try a handshake = sequence of `try_interval * retries`
+  # With 100ms interval and 20 retries it is 23.5 seconds
+  #try_interval: 100ms
+  #retries: 20
+  # wait_rotation is the number of handshake attempts to do before starting to try non-local IP addresses
+  #wait_rotation: 5
+
 # Nebula security group configuration
 # Nebula security group configuration
 firewall:
 firewall:
   conntrack:
   conntrack:

+ 29 - 12
handshake_manager.go

@@ -13,36 +13,53 @@ import (
 const (
 const (
 	// Total time to try a handshake = sequence of HandshakeTryInterval * HandshakeRetries
 	// Total time to try a handshake = sequence of HandshakeTryInterval * HandshakeRetries
 	// With 100ms interval and 20 retries is 23.5 seconds
 	// With 100ms interval and 20 retries is 23.5 seconds
-	HandshakeTryInterval = time.Millisecond * 100
-	HandshakeRetries     = 20
-	// HandshakeWaitRotation is the number of handshake attempts to do before starting to use other ips addresses
-	HandshakeWaitRotation = 5
+	DefaultHandshakeTryInterval = time.Millisecond * 100
+	DefaultHandshakeRetries     = 20
+	// DefaultHandshakeWaitRotation is the number of handshake attempts to do before starting to use other ips addresses
+	DefaultHandshakeWaitRotation = 5
 )
 )
 
 
+var (
+	defaultHandshakeConfig = HandshakeConfig{
+		tryInterval:  DefaultHandshakeTryInterval,
+		retries:      DefaultHandshakeRetries,
+		waitRotation: DefaultHandshakeWaitRotation,
+	}
+)
+
+type HandshakeConfig struct {
+	tryInterval  time.Duration
+	retries      int
+	waitRotation int
+}
+
 type HandshakeManager struct {
 type HandshakeManager struct {
 	pendingHostMap *HostMap
 	pendingHostMap *HostMap
 	mainHostMap    *HostMap
 	mainHostMap    *HostMap
 	lightHouse     *LightHouse
 	lightHouse     *LightHouse
 	outside        *udpConn
 	outside        *udpConn
+	config         HandshakeConfig
 
 
 	OutboundHandshakeTimer *SystemTimerWheel
 	OutboundHandshakeTimer *SystemTimerWheel
 	InboundHandshakeTimer  *SystemTimerWheel
 	InboundHandshakeTimer  *SystemTimerWheel
 }
 }
 
 
-func NewHandshakeManager(tunCidr *net.IPNet, preferredRanges []*net.IPNet, mainHostMap *HostMap, lightHouse *LightHouse, outside *udpConn) *HandshakeManager {
+func NewHandshakeManager(tunCidr *net.IPNet, preferredRanges []*net.IPNet, mainHostMap *HostMap, lightHouse *LightHouse, outside *udpConn, config HandshakeConfig) *HandshakeManager {
 	return &HandshakeManager{
 	return &HandshakeManager{
 		pendingHostMap: NewHostMap("pending", tunCidr, preferredRanges),
 		pendingHostMap: NewHostMap("pending", tunCidr, preferredRanges),
 		mainHostMap:    mainHostMap,
 		mainHostMap:    mainHostMap,
 		lightHouse:     lightHouse,
 		lightHouse:     lightHouse,
 		outside:        outside,
 		outside:        outside,
 
 
-		OutboundHandshakeTimer: NewSystemTimerWheel(HandshakeTryInterval, HandshakeTryInterval*HandshakeRetries),
-		InboundHandshakeTimer:  NewSystemTimerWheel(HandshakeTryInterval, HandshakeTryInterval*HandshakeRetries),
+		config: config,
+
+		OutboundHandshakeTimer: NewSystemTimerWheel(config.tryInterval, config.tryInterval*time.Duration(config.retries)),
+		InboundHandshakeTimer:  NewSystemTimerWheel(config.tryInterval, config.tryInterval*time.Duration(config.retries)),
 	}
 	}
 }
 }
 
 
 func (c *HandshakeManager) Run(f EncWriter) {
 func (c *HandshakeManager) Run(f EncWriter) {
-	clockSource := time.Tick(HandshakeTryInterval)
+	clockSource := time.Tick(c.config.tryInterval)
 	for now := range clockSource {
 	for now := range clockSource {
 		c.NextOutboundHandshakeTimerTick(now, f)
 		c.NextOutboundHandshakeTimerTick(now, f)
 		c.NextInboundHandshakeTimerTick(now)
 		c.NextInboundHandshakeTimerTick(now)
@@ -70,7 +87,7 @@ func (c *HandshakeManager) NextOutboundHandshakeTimerTick(now time.Time, f EncWr
 
 
 		// If we haven't finished the handshake and we haven't hit max retries, query
 		// If we haven't finished the handshake and we haven't hit max retries, query
 		// lighthouse and then send the handshake packet again.
 		// lighthouse and then send the handshake packet again.
-		if hostinfo.HandshakeCounter < HandshakeRetries && !hostinfo.HandshakeComplete {
+		if hostinfo.HandshakeCounter < c.config.retries && !hostinfo.HandshakeComplete {
 			if hostinfo.remote == nil {
 			if hostinfo.remote == nil {
 				// We continue to query the lighthouse because hosts may
 				// We continue to query the lighthouse because hosts may
 				// come online during handshake retries. If the query
 				// come online during handshake retries. If the query
@@ -88,7 +105,7 @@ func (c *HandshakeManager) NextOutboundHandshakeTimerTick(now time.Time, f EncWr
 
 
 			// We want to use the "best" calculated ip for the first 5 attempts, after that we just blindly rotate through
 			// We want to use the "best" calculated ip for the first 5 attempts, after that we just blindly rotate through
 			// all the others until we can stand up a connection.
 			// all the others until we can stand up a connection.
-			if hostinfo.HandshakeCounter > HandshakeWaitRotation {
+			if hostinfo.HandshakeCounter > c.config.waitRotation {
 				hostinfo.rotateRemote()
 				hostinfo.rotateRemote()
 			}
 			}
 
 
@@ -114,7 +131,7 @@ func (c *HandshakeManager) NextOutboundHandshakeTimerTick(now time.Time, f EncWr
 
 
 			// Readd to the timer wheel so we continue trying wait HandshakeTryInterval * counter longer for next try
 			// Readd to the timer wheel so we continue trying wait HandshakeTryInterval * counter longer for next try
 			//l.Infoln("Interval: ", HandshakeTryInterval*time.Duration(hostinfo.HandshakeCounter))
 			//l.Infoln("Interval: ", HandshakeTryInterval*time.Duration(hostinfo.HandshakeCounter))
-			c.OutboundHandshakeTimer.Add(vpnIP, HandshakeTryInterval*time.Duration(hostinfo.HandshakeCounter))
+			c.OutboundHandshakeTimer.Add(vpnIP, c.config.tryInterval*time.Duration(hostinfo.HandshakeCounter))
 		} else {
 		} else {
 			c.pendingHostMap.DeleteVpnIP(vpnIP)
 			c.pendingHostMap.DeleteVpnIP(vpnIP)
 			c.pendingHostMap.DeleteIndex(index)
 			c.pendingHostMap.DeleteIndex(index)
@@ -144,7 +161,7 @@ func (c *HandshakeManager) AddVpnIP(vpnIP uint32) *HostInfo {
 	hostinfo := c.pendingHostMap.AddVpnIP(vpnIP)
 	hostinfo := c.pendingHostMap.AddVpnIP(vpnIP)
 	// We lock here and use an array to insert items to prevent locking the
 	// We lock here and use an array to insert items to prevent locking the
 	// main receive thread for very long by waiting to add items to the pending map
 	// main receive thread for very long by waiting to add items to the pending map
-	c.OutboundHandshakeTimer.Add(vpnIP, HandshakeTryInterval)
+	c.OutboundHandshakeTimer.Add(vpnIP, c.config.tryInterval)
 	return hostinfo
 	return hostinfo
 }
 }
 
 

+ 14 - 14
handshake_manager_test.go

@@ -21,7 +21,7 @@ func Test_NewHandshakeManagerIndex(t *testing.T) {
 	preferredRanges := []*net.IPNet{localrange}
 	preferredRanges := []*net.IPNet{localrange}
 	mainHM := NewHostMap("test", vpncidr, preferredRanges)
 	mainHM := NewHostMap("test", vpncidr, preferredRanges)
 
 
-	blah := NewHandshakeManager(tuncidr, preferredRanges, mainHM, &LightHouse{}, &udpConn{})
+	blah := NewHandshakeManager(tuncidr, preferredRanges, mainHM, &LightHouse{}, &udpConn{}, defaultHandshakeConfig)
 
 
 	now := time.Now()
 	now := time.Now()
 	blah.NextInboundHandshakeTimerTick(now)
 	blah.NextInboundHandshakeTimerTick(now)
@@ -37,8 +37,8 @@ func Test_NewHandshakeManagerIndex(t *testing.T) {
 	// Adding something to pending should not affect the main hostmap
 	// Adding something to pending should not affect the main hostmap
 	assert.Len(t, mainHM.Indexes, 0)
 	assert.Len(t, mainHM.Indexes, 0)
 	// Jump ahead 8 seconds
 	// Jump ahead 8 seconds
-	for i := 1; i <= HandshakeRetries; i++ {
-		next_tick := now.Add(HandshakeTryInterval * time.Duration(i))
+	for i := 1; i <= DefaultHandshakeRetries; i++ {
+		next_tick := now.Add(DefaultHandshakeTryInterval * time.Duration(i))
 		blah.NextInboundHandshakeTimerTick(next_tick)
 		blah.NextInboundHandshakeTimerTick(next_tick)
 	}
 	}
 	// Confirm they are still in the pending index list
 	// Confirm they are still in the pending index list
@@ -63,7 +63,7 @@ func Test_NewHandshakeManagerVpnIP(t *testing.T) {
 	mw := &mockEncWriter{}
 	mw := &mockEncWriter{}
 	mainHM := NewHostMap("test", vpncidr, preferredRanges)
 	mainHM := NewHostMap("test", vpncidr, preferredRanges)
 
 
-	blah := NewHandshakeManager(tuncidr, preferredRanges, mainHM, &LightHouse{}, &udpConn{})
+	blah := NewHandshakeManager(tuncidr, preferredRanges, mainHM, &LightHouse{}, &udpConn{}, defaultHandshakeConfig)
 
 
 	now := time.Now()
 	now := time.Now()
 	blah.NextOutboundHandshakeTimerTick(now, mw)
 	blah.NextOutboundHandshakeTimerTick(now, mw)
@@ -81,8 +81,8 @@ func Test_NewHandshakeManagerVpnIP(t *testing.T) {
 
 
 	// Jump ahead `HandshakeRetries` ticks
 	// Jump ahead `HandshakeRetries` ticks
 	cumulative := time.Duration(0)
 	cumulative := time.Duration(0)
-	for i := 0; i <= HandshakeRetries+1; i++ {
-		cumulative += time.Duration(i)*HandshakeTryInterval + 1
+	for i := 0; i <= DefaultHandshakeRetries+1; i++ {
+		cumulative += time.Duration(i)*DefaultHandshakeTryInterval + 1
 		next_tick := now.Add(cumulative)
 		next_tick := now.Add(cumulative)
 		//l.Infoln(next_tick)
 		//l.Infoln(next_tick)
 		blah.NextOutboundHandshakeTimerTick(next_tick, mw)
 		blah.NextOutboundHandshakeTimerTick(next_tick, mw)
@@ -93,7 +93,7 @@ func Test_NewHandshakeManagerVpnIP(t *testing.T) {
 		assert.Contains(t, blah.pendingHostMap.Hosts, uint32(v))
 		assert.Contains(t, blah.pendingHostMap.Hosts, uint32(v))
 	}
 	}
 	// Jump ahead 1 more second
 	// Jump ahead 1 more second
-	cumulative += time.Duration(HandshakeRetries+1) * HandshakeTryInterval
+	cumulative += time.Duration(DefaultHandshakeRetries+1) * DefaultHandshakeTryInterval
 	next_tick := now.Add(cumulative)
 	next_tick := now.Add(cumulative)
 	//l.Infoln(next_tick)
 	//l.Infoln(next_tick)
 	blah.NextOutboundHandshakeTimerTick(next_tick, mw)
 	blah.NextOutboundHandshakeTimerTick(next_tick, mw)
@@ -112,7 +112,7 @@ func Test_NewHandshakeManagerVpnIPcleanup(t *testing.T) {
 	mw := &mockEncWriter{}
 	mw := &mockEncWriter{}
 	mainHM := NewHostMap("test", vpncidr, preferredRanges)
 	mainHM := NewHostMap("test", vpncidr, preferredRanges)
 
 
-	blah := NewHandshakeManager(tuncidr, preferredRanges, mainHM, &LightHouse{}, &udpConn{})
+	blah := NewHandshakeManager(tuncidr, preferredRanges, mainHM, &LightHouse{}, &udpConn{}, defaultHandshakeConfig)
 
 
 	now := time.Now()
 	now := time.Now()
 	blah.NextOutboundHandshakeTimerTick(now, mw)
 	blah.NextOutboundHandshakeTimerTick(now, mw)
@@ -125,8 +125,8 @@ func Test_NewHandshakeManagerVpnIPcleanup(t *testing.T) {
 	// Jump ahead `HandshakeRetries` ticks. Eviction should happen in pending
 	// Jump ahead `HandshakeRetries` ticks. Eviction should happen in pending
 	// but not main hostmap
 	// but not main hostmap
 	cumulative := time.Duration(0)
 	cumulative := time.Duration(0)
-	for i := 1; i <= HandshakeRetries+2; i++ {
-		cumulative += HandshakeTryInterval * time.Duration(i)
+	for i := 1; i <= DefaultHandshakeRetries+2; i++ {
+		cumulative += DefaultHandshakeTryInterval * time.Duration(i)
 		next_tick := now.Add(cumulative)
 		next_tick := now.Add(cumulative)
 		blah.NextOutboundHandshakeTimerTick(next_tick, mw)
 		blah.NextOutboundHandshakeTimerTick(next_tick, mw)
 	}
 	}
@@ -161,7 +161,7 @@ func Test_NewHandshakeManagerIndexcleanup(t *testing.T) {
 	preferredRanges := []*net.IPNet{localrange}
 	preferredRanges := []*net.IPNet{localrange}
 	mainHM := NewHostMap("test", vpncidr, preferredRanges)
 	mainHM := NewHostMap("test", vpncidr, preferredRanges)
 
 
-	blah := NewHandshakeManager(tuncidr, preferredRanges, mainHM, &LightHouse{}, &udpConn{})
+	blah := NewHandshakeManager(tuncidr, preferredRanges, mainHM, &LightHouse{}, &udpConn{}, defaultHandshakeConfig)
 
 
 	now := time.Now()
 	now := time.Now()
 	blah.NextInboundHandshakeTimerTick(now)
 	blah.NextInboundHandshakeTimerTick(now)
@@ -171,12 +171,12 @@ func Test_NewHandshakeManagerIndexcleanup(t *testing.T) {
 	blah.pendingHostMap.AddVpnIPHostInfo(101010, hostinfo)
 	blah.pendingHostMap.AddVpnIPHostInfo(101010, hostinfo)
 	assert.Contains(t, blah.pendingHostMap.Hosts, uint32(101010))
 	assert.Contains(t, blah.pendingHostMap.Hosts, uint32(101010))
 
 
-	for i := 1; i <= HandshakeRetries+2; i++ {
-		next_tick := now.Add(HandshakeTryInterval * time.Duration(i))
+	for i := 1; i <= DefaultHandshakeRetries+2; i++ {
+		next_tick := now.Add(DefaultHandshakeTryInterval * time.Duration(i))
 		blah.NextInboundHandshakeTimerTick(next_tick)
 		blah.NextInboundHandshakeTimerTick(next_tick)
 	}
 	}
 
 
-	next_tick := now.Add(HandshakeTryInterval*HandshakeRetries + 3)
+	next_tick := now.Add(DefaultHandshakeTryInterval*DefaultHandshakeRetries + 3)
 	blah.NextInboundHandshakeTimerTick(next_tick)
 	blah.NextInboundHandshakeTimerTick(next_tick)
 	assert.NotContains(t, blah.pendingHostMap.Hosts, uint32(101010))
 	assert.NotContains(t, blah.pendingHostMap.Hosts, uint32(101010))
 	assert.NotContains(t, blah.pendingHostMap.Indexes, uint32(12341234))
 	assert.NotContains(t, blah.pendingHostMap.Indexes, uint32(12341234))

+ 7 - 1
main.go

@@ -265,7 +265,13 @@ func Main(configPath string, configTest bool, buildVersion string) {
 		l.WithError(err).Error("Lighthouse unreachable")
 		l.WithError(err).Error("Lighthouse unreachable")
 	}
 	}
 
 
-	handshakeManager := NewHandshakeManager(tunCidr, preferredRanges, hostMap, lightHouse, udpServer)
+	handshakeConfig := HandshakeConfig{
+		tryInterval:  config.GetDuration("handshakes.try_interval", DefaultHandshakeTryInterval),
+		retries:      config.GetInt("handshakes.retries", DefaultHandshakeRetries),
+		waitRotation: config.GetInt("handshakes.wait_rotation", DefaultHandshakeWaitRotation),
+	}
+
+	handshakeManager := NewHandshakeManager(tunCidr, preferredRanges, hostMap, lightHouse, udpServer, handshakeConfig)
 
 
 	//TODO: These will be reused for psk
 	//TODO: These will be reused for psk
 	//handshakeMACKey := config.GetString("handshake_mac.key", "")
 	//handshakeMACKey := config.GetString("handshake_mac.key", "")