connection_manager_test.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package nebula
  2. import (
  3. "context"
  4. "crypto/ed25519"
  5. "crypto/rand"
  6. "net"
  7. "testing"
  8. "time"
  9. "github.com/flynn/noise"
  10. "github.com/slackhq/nebula/cert"
  11. "github.com/slackhq/nebula/iputil"
  12. "github.com/slackhq/nebula/overlay"
  13. "github.com/slackhq/nebula/test"
  14. "github.com/slackhq/nebula/udp"
  15. "github.com/stretchr/testify/assert"
  16. )
  17. var vpnIp iputil.VpnIp
  18. func Test_NewConnectionManagerTest(t *testing.T) {
  19. l := test.NewLogger()
  20. //_, tuncidr, _ := net.ParseCIDR("1.1.1.1/24")
  21. _, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
  22. _, localrange, _ := net.ParseCIDR("10.1.1.1/24")
  23. vpnIp = iputil.Ip2VpnIp(net.ParseIP("172.1.1.2"))
  24. preferredRanges := []*net.IPNet{localrange}
  25. // Very incomplete mock objects
  26. hostMap := NewHostMap(l, "test", vpncidr, preferredRanges)
  27. cs := &CertState{
  28. rawCertificate: []byte{},
  29. privateKey: []byte{},
  30. certificate: &cert.NebulaCertificate{},
  31. rawCertificateNoKey: []byte{},
  32. }
  33. lh := NewLightHouse(l, false, &net.IPNet{IP: net.IP{0, 0, 0, 0}, Mask: net.IPMask{0, 0, 0, 0}}, []iputil.VpnIp{}, 1000, 0, &udp.Conn{}, false, 1, false)
  34. ifce := &Interface{
  35. hostMap: hostMap,
  36. inside: &overlay.Tun{},
  37. outside: &udp.Conn{},
  38. certState: cs,
  39. firewall: &Firewall{},
  40. lightHouse: lh,
  41. handshakeManager: NewHandshakeManager(l, vpncidr, preferredRanges, hostMap, lh, &udp.Conn{}, defaultHandshakeConfig),
  42. l: l,
  43. }
  44. now := time.Now()
  45. // Create manager
  46. ctx, cancel := context.WithCancel(context.Background())
  47. defer cancel()
  48. nc := newConnectionManager(ctx, l, ifce, 5, 10)
  49. p := []byte("")
  50. nb := make([]byte, 12, 12)
  51. out := make([]byte, mtu)
  52. nc.HandleMonitorTick(now, p, nb, out)
  53. // Add an ip we have established a connection w/ to hostmap
  54. hostinfo, _ := nc.hostMap.AddVpnIp(vpnIp, nil)
  55. hostinfo.ConnectionState = &ConnectionState{
  56. certState: cs,
  57. H: &noise.HandshakeState{},
  58. }
  59. // We saw traffic out to vpnIp
  60. nc.Out(vpnIp)
  61. assert.NotContains(t, nc.pendingDeletion, vpnIp)
  62. assert.Contains(t, nc.hostMap.Hosts, vpnIp)
  63. // Move ahead 5s. Nothing should happen
  64. next_tick := now.Add(5 * time.Second)
  65. nc.HandleMonitorTick(next_tick, p, nb, out)
  66. nc.HandleDeletionTick(next_tick)
  67. // Move ahead 6s. We haven't heard back
  68. next_tick = now.Add(6 * time.Second)
  69. nc.HandleMonitorTick(next_tick, p, nb, out)
  70. nc.HandleDeletionTick(next_tick)
  71. // This host should now be up for deletion
  72. assert.Contains(t, nc.pendingDeletion, vpnIp)
  73. assert.Contains(t, nc.hostMap.Hosts, vpnIp)
  74. // Move ahead some more
  75. next_tick = now.Add(45 * time.Second)
  76. nc.HandleMonitorTick(next_tick, p, nb, out)
  77. nc.HandleDeletionTick(next_tick)
  78. // The host should be evicted
  79. assert.NotContains(t, nc.pendingDeletion, vpnIp)
  80. assert.NotContains(t, nc.hostMap.Hosts, vpnIp)
  81. }
  82. func Test_NewConnectionManagerTest2(t *testing.T) {
  83. l := test.NewLogger()
  84. //_, tuncidr, _ := net.ParseCIDR("1.1.1.1/24")
  85. _, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
  86. _, localrange, _ := net.ParseCIDR("10.1.1.1/24")
  87. preferredRanges := []*net.IPNet{localrange}
  88. // Very incomplete mock objects
  89. hostMap := NewHostMap(l, "test", vpncidr, preferredRanges)
  90. cs := &CertState{
  91. rawCertificate: []byte{},
  92. privateKey: []byte{},
  93. certificate: &cert.NebulaCertificate{},
  94. rawCertificateNoKey: []byte{},
  95. }
  96. lh := NewLightHouse(l, false, &net.IPNet{IP: net.IP{0, 0, 0, 0}, Mask: net.IPMask{0, 0, 0, 0}}, []iputil.VpnIp{}, 1000, 0, &udp.Conn{}, false, 1, false)
  97. ifce := &Interface{
  98. hostMap: hostMap,
  99. inside: &overlay.Tun{},
  100. outside: &udp.Conn{},
  101. certState: cs,
  102. firewall: &Firewall{},
  103. lightHouse: lh,
  104. handshakeManager: NewHandshakeManager(l, vpncidr, preferredRanges, hostMap, lh, &udp.Conn{}, defaultHandshakeConfig),
  105. l: l,
  106. }
  107. now := time.Now()
  108. // Create manager
  109. ctx, cancel := context.WithCancel(context.Background())
  110. defer cancel()
  111. nc := newConnectionManager(ctx, l, ifce, 5, 10)
  112. p := []byte("")
  113. nb := make([]byte, 12, 12)
  114. out := make([]byte, mtu)
  115. nc.HandleMonitorTick(now, p, nb, out)
  116. // Add an ip we have established a connection w/ to hostmap
  117. hostinfo, _ := nc.hostMap.AddVpnIp(vpnIp, nil)
  118. hostinfo.ConnectionState = &ConnectionState{
  119. certState: cs,
  120. H: &noise.HandshakeState{},
  121. }
  122. // We saw traffic out to vpnIp
  123. nc.Out(vpnIp)
  124. assert.NotContains(t, nc.pendingDeletion, vpnIp)
  125. assert.Contains(t, nc.hostMap.Hosts, vpnIp)
  126. // Move ahead 5s. Nothing should happen
  127. next_tick := now.Add(5 * time.Second)
  128. nc.HandleMonitorTick(next_tick, p, nb, out)
  129. nc.HandleDeletionTick(next_tick)
  130. // Move ahead 6s. We haven't heard back
  131. next_tick = now.Add(6 * time.Second)
  132. nc.HandleMonitorTick(next_tick, p, nb, out)
  133. nc.HandleDeletionTick(next_tick)
  134. // This host should now be up for deletion
  135. assert.Contains(t, nc.pendingDeletion, vpnIp)
  136. assert.Contains(t, nc.hostMap.Hosts, vpnIp)
  137. // We heard back this time
  138. nc.In(vpnIp)
  139. // Move ahead some more
  140. next_tick = now.Add(45 * time.Second)
  141. nc.HandleMonitorTick(next_tick, p, nb, out)
  142. nc.HandleDeletionTick(next_tick)
  143. // The host should be evicted
  144. assert.NotContains(t, nc.pendingDeletion, vpnIp)
  145. assert.Contains(t, nc.hostMap.Hosts, vpnIp)
  146. }
  147. // Check if we can disconnect the peer.
  148. // Validate if the peer's certificate is invalid (expired, etc.)
  149. // Disconnect only if disconnectInvalid: true is set.
  150. func Test_NewConnectionManagerTest_DisconnectInvalid(t *testing.T) {
  151. now := time.Now()
  152. l := test.NewLogger()
  153. ipNet := net.IPNet{
  154. IP: net.IPv4(172, 1, 1, 2),
  155. Mask: net.IPMask{255, 255, 255, 0},
  156. }
  157. _, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
  158. _, localrange, _ := net.ParseCIDR("10.1.1.1/24")
  159. preferredRanges := []*net.IPNet{localrange}
  160. hostMap := NewHostMap(l, "test", vpncidr, preferredRanges)
  161. // Generate keys for CA and peer's cert.
  162. pubCA, privCA, _ := ed25519.GenerateKey(rand.Reader)
  163. caCert := cert.NebulaCertificate{
  164. Details: cert.NebulaCertificateDetails{
  165. Name: "ca",
  166. NotBefore: now,
  167. NotAfter: now.Add(1 * time.Hour),
  168. IsCA: true,
  169. PublicKey: pubCA,
  170. },
  171. }
  172. caCert.Sign(privCA)
  173. ncp := &cert.NebulaCAPool{
  174. CAs: cert.NewCAPool().CAs,
  175. }
  176. ncp.CAs["ca"] = &caCert
  177. pubCrt, _, _ := ed25519.GenerateKey(rand.Reader)
  178. peerCert := cert.NebulaCertificate{
  179. Details: cert.NebulaCertificateDetails{
  180. Name: "host",
  181. Ips: []*net.IPNet{&ipNet},
  182. Subnets: []*net.IPNet{},
  183. NotBefore: now,
  184. NotAfter: now.Add(60 * time.Second),
  185. PublicKey: pubCrt,
  186. IsCA: false,
  187. Issuer: "ca",
  188. },
  189. }
  190. peerCert.Sign(privCA)
  191. cs := &CertState{
  192. rawCertificate: []byte{},
  193. privateKey: []byte{},
  194. certificate: &cert.NebulaCertificate{},
  195. rawCertificateNoKey: []byte{},
  196. }
  197. lh := NewLightHouse(l, false, &net.IPNet{IP: net.IP{0, 0, 0, 0}, Mask: net.IPMask{0, 0, 0, 0}}, []iputil.VpnIp{}, 1000, 0, &udp.Conn{}, false, 1, false)
  198. ifce := &Interface{
  199. hostMap: hostMap,
  200. inside: &overlay.Tun{},
  201. outside: &udp.Conn{},
  202. certState: cs,
  203. firewall: &Firewall{},
  204. lightHouse: lh,
  205. handshakeManager: NewHandshakeManager(l, vpncidr, preferredRanges, hostMap, lh, &udp.Conn{}, defaultHandshakeConfig),
  206. l: l,
  207. disconnectInvalid: true,
  208. caPool: ncp,
  209. }
  210. // Create manager
  211. ctx, cancel := context.WithCancel(context.Background())
  212. defer cancel()
  213. nc := newConnectionManager(ctx, l, ifce, 5, 10)
  214. ifce.connectionManager = nc
  215. hostinfo, _ := nc.hostMap.AddVpnIp(vpnIp, nil)
  216. hostinfo.ConnectionState = &ConnectionState{
  217. certState: cs,
  218. peerCert: &peerCert,
  219. H: &noise.HandshakeState{},
  220. }
  221. // Move ahead 45s.
  222. // Check if to disconnect with invalid certificate.
  223. // Should be alive.
  224. nextTick := now.Add(45 * time.Second)
  225. destroyed := nc.handleInvalidCertificate(nextTick, vpnIp, hostinfo)
  226. assert.False(t, destroyed)
  227. // Move ahead 61s.
  228. // Check if to disconnect with invalid certificate.
  229. // Should be disconnected.
  230. nextTick = now.Add(61 * time.Second)
  231. destroyed = nc.handleInvalidCertificate(nextTick, vpnIp, hostinfo)
  232. assert.True(t, destroyed)
  233. }