connection_manager_test.go 7.9 KB

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