connection_manager_test.go 7.8 KB

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