handshakes_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. //go:build e2e_testing
  2. // +build e2e_testing
  3. package e2e
  4. import (
  5. "net"
  6. "testing"
  7. "time"
  8. "github.com/slackhq/nebula"
  9. "github.com/slackhq/nebula/e2e/router"
  10. "github.com/slackhq/nebula/header"
  11. "github.com/slackhq/nebula/iputil"
  12. "github.com/slackhq/nebula/udp"
  13. "github.com/stretchr/testify/assert"
  14. )
  15. func TestGoodHandshake(t *testing.T) {
  16. ca, _, caKey, _ := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  17. myControl, myVpnIp, myUdpAddr := newSimpleServer(ca, caKey, "me", net.IP{10, 0, 0, 1}, nil)
  18. theirControl, theirVpnIp, theirUdpAddr := newSimpleServer(ca, caKey, "them", net.IP{10, 0, 0, 2}, nil)
  19. // Put their info in our lighthouse
  20. myControl.InjectLightHouseAddr(theirVpnIp, theirUdpAddr)
  21. // Start the servers
  22. myControl.Start()
  23. theirControl.Start()
  24. t.Log("Send a udp packet through to begin standing up the tunnel, this should come out the other side")
  25. myControl.InjectTunUDPPacket(theirVpnIp, 80, 80, []byte("Hi from me"))
  26. t.Log("Have them consume my stage 0 packet. They have a tunnel now")
  27. theirControl.InjectUDPPacket(myControl.GetFromUDP(true))
  28. t.Log("Get their stage 1 packet so that we can play with it")
  29. stage1Packet := theirControl.GetFromUDP(true)
  30. t.Log("I consume a garbage packet with a proper nebula header for our tunnel")
  31. // this should log a statement and get ignored, allowing the real handshake packet to complete the tunnel
  32. badPacket := stage1Packet.Copy()
  33. badPacket.Data = badPacket.Data[:len(badPacket.Data)-header.Len]
  34. myControl.InjectUDPPacket(badPacket)
  35. t.Log("Have me consume their real stage 1 packet. I have a tunnel now")
  36. myControl.InjectUDPPacket(stage1Packet)
  37. t.Log("Wait until we see my cached packet come through")
  38. myControl.WaitForType(1, 0, theirControl)
  39. t.Log("Make sure our host infos are correct")
  40. assertHostInfoPair(t, myUdpAddr, theirUdpAddr, myVpnIp, theirVpnIp, myControl, theirControl)
  41. t.Log("Get that cached packet and make sure it looks right")
  42. myCachedPacket := theirControl.GetFromTun(true)
  43. assertUdpPacket(t, []byte("Hi from me"), myCachedPacket, myVpnIp, theirVpnIp, 80, 80)
  44. t.Log("Do a bidirectional tunnel test")
  45. assertTunnel(t, myVpnIp, theirVpnIp, myControl, theirControl, router.NewR(myControl, theirControl))
  46. myControl.Stop()
  47. theirControl.Stop()
  48. //TODO: assert hostmaps
  49. }
  50. func TestWrongResponderHandshake(t *testing.T) {
  51. ca, _, caKey, _ := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  52. // The IPs here are chosen on purpose:
  53. // The current remote handling will sort by preference, public, and then lexically.
  54. // So we need them to have a higher address than evil (we could apply a preference though)
  55. myControl, myVpnIp, myUdpAddr := newSimpleServer(ca, caKey, "me", net.IP{10, 0, 0, 100}, nil)
  56. theirControl, theirVpnIp, theirUdpAddr := newSimpleServer(ca, caKey, "them", net.IP{10, 0, 0, 99}, nil)
  57. evilControl, evilVpnIp, evilUdpAddr := newSimpleServer(ca, caKey, "evil", net.IP{10, 0, 0, 2}, nil)
  58. // Add their real udp addr, which should be tried after evil.
  59. myControl.InjectLightHouseAddr(theirVpnIp, theirUdpAddr)
  60. // Put the evil udp addr in for their vpn Ip, this is a case of being lied to by the lighthouse.
  61. myControl.InjectLightHouseAddr(theirVpnIp, evilUdpAddr)
  62. // Build a router so we don't have to reason who gets which packet
  63. r := router.NewR(myControl, theirControl, evilControl)
  64. // Start the servers
  65. myControl.Start()
  66. theirControl.Start()
  67. evilControl.Start()
  68. t.Log("Start the handshake process, we will route until we see our cached packet get sent to them")
  69. myControl.InjectTunUDPPacket(theirVpnIp, 80, 80, []byte("Hi from me"))
  70. r.RouteForAllExitFunc(func(p *udp.Packet, c *nebula.Control) router.ExitType {
  71. h := &header.H{}
  72. err := h.Parse(p.Data)
  73. if err != nil {
  74. panic(err)
  75. }
  76. if p.ToIp.Equal(theirUdpAddr.IP) && p.ToPort == uint16(theirUdpAddr.Port) && h.Type == 1 {
  77. return router.RouteAndExit
  78. }
  79. return router.KeepRouting
  80. })
  81. //TODO: Assert pending hostmap - I should have a correct hostinfo for them now
  82. t.Log("My cached packet should be received by them")
  83. myCachedPacket := theirControl.GetFromTun(true)
  84. assertUdpPacket(t, []byte("Hi from me"), myCachedPacket, myVpnIp, theirVpnIp, 80, 80)
  85. t.Log("Test the tunnel with them")
  86. assertHostInfoPair(t, myUdpAddr, theirUdpAddr, myVpnIp, theirVpnIp, myControl, theirControl)
  87. assertTunnel(t, myVpnIp, theirVpnIp, myControl, theirControl, r)
  88. t.Log("Flush all packets from all controllers")
  89. r.FlushAll()
  90. t.Log("Ensure ensure I don't have any hostinfo artifacts from evil")
  91. assert.Nil(t, myControl.GetHostInfoByVpnIp(iputil.Ip2VpnIp(evilVpnIp), true), "My pending hostmap should not contain evil")
  92. assert.Nil(t, myControl.GetHostInfoByVpnIp(iputil.Ip2VpnIp(evilVpnIp), false), "My main hostmap should not contain evil")
  93. //NOTE: if evil lost the handshake race it may still have a tunnel since me would reject the handshake since the tunnel is complete
  94. //TODO: assert hostmaps for everyone
  95. t.Log("Success!")
  96. myControl.Stop()
  97. theirControl.Stop()
  98. }
  99. func Test_Case1_Stage1Race(t *testing.T) {
  100. ca, _, caKey, _ := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  101. myControl, myVpnIp, myUdpAddr := newSimpleServer(ca, caKey, "me ", net.IP{10, 0, 0, 1}, nil)
  102. theirControl, theirVpnIp, theirUdpAddr := newSimpleServer(ca, caKey, "them", net.IP{10, 0, 0, 2}, nil)
  103. // Put their info in our lighthouse and vice versa
  104. myControl.InjectLightHouseAddr(theirVpnIp, theirUdpAddr)
  105. theirControl.InjectLightHouseAddr(myVpnIp, myUdpAddr)
  106. // Build a router so we don't have to reason who gets which packet
  107. r := router.NewR(myControl, theirControl)
  108. // Start the servers
  109. myControl.Start()
  110. theirControl.Start()
  111. t.Log("Trigger a handshake to start on both me and them")
  112. myControl.InjectTunUDPPacket(theirVpnIp, 80, 80, []byte("Hi from me"))
  113. theirControl.InjectTunUDPPacket(myVpnIp, 80, 80, []byte("Hi from them"))
  114. t.Log("Get both stage 1 handshake packets")
  115. myHsForThem := myControl.GetFromUDP(true)
  116. theirHsForMe := theirControl.GetFromUDP(true)
  117. t.Log("Now inject both stage 1 handshake packets")
  118. myControl.InjectUDPPacket(theirHsForMe)
  119. theirControl.InjectUDPPacket(myHsForThem)
  120. //TODO: they should win, grab their index for me and make sure I use it in the end.
  121. t.Log("They should not have a stage 2 (won the race) but I should send one")
  122. theirControl.InjectUDPPacket(myControl.GetFromUDP(true))
  123. t.Log("Route for me until I send a message packet to them")
  124. myControl.WaitForType(1, 0, theirControl)
  125. t.Log("My cached packet should be received by them")
  126. myCachedPacket := theirControl.GetFromTun(true)
  127. assertUdpPacket(t, []byte("Hi from me"), myCachedPacket, myVpnIp, theirVpnIp, 80, 80)
  128. t.Log("Route for them until I send a message packet to me")
  129. theirControl.WaitForType(1, 0, myControl)
  130. t.Log("Their cached packet should be received by me")
  131. theirCachedPacket := myControl.GetFromTun(true)
  132. assertUdpPacket(t, []byte("Hi from them"), theirCachedPacket, theirVpnIp, myVpnIp, 80, 80)
  133. t.Log("Do a bidirectional tunnel test")
  134. assertTunnel(t, myVpnIp, theirVpnIp, myControl, theirControl, r)
  135. myControl.Stop()
  136. theirControl.Stop()
  137. //TODO: assert hostmaps
  138. }
  139. //TODO: add a test with many lies
  140. func TestPSK(t *testing.T) {
  141. tests := []struct {
  142. name string
  143. myPskMode nebula.PskMode
  144. theirPskMode nebula.PskMode
  145. }{
  146. // None and transitional-accepting both ways
  147. {
  148. name: "none to transitional-accepting",
  149. myPskMode: nebula.PskNone,
  150. theirPskMode: nebula.PskTransitionalAccepting,
  151. },
  152. {
  153. name: "transitional-accepting to none",
  154. myPskMode: nebula.PskTransitionalAccepting,
  155. theirPskMode: nebula.PskNone,
  156. },
  157. // All transitional-accepting
  158. {
  159. name: "both transitional-accepting",
  160. myPskMode: nebula.PskTransitionalAccepting,
  161. theirPskMode: nebula.PskTransitionalAccepting,
  162. },
  163. // transitional-accepting and transitional-sending both ways
  164. {
  165. name: "transitional-accepting to transitional-sending",
  166. myPskMode: nebula.PskTransitionalAccepting,
  167. theirPskMode: nebula.PskTransitionalSending,
  168. },
  169. {
  170. name: "transitional-sending to transitional-accepting",
  171. myPskMode: nebula.PskTransitionalSending,
  172. theirPskMode: nebula.PskTransitionalAccepting,
  173. },
  174. // All transitional-sending
  175. {
  176. name: "transitional-sending to transitional-sending",
  177. myPskMode: nebula.PskTransitionalSending,
  178. theirPskMode: nebula.PskTransitionalSending,
  179. },
  180. // enforced and transitional-sending both ways
  181. {
  182. name: "enforced to transitional-sending",
  183. myPskMode: nebula.PskEnforced,
  184. theirPskMode: nebula.PskTransitionalSending,
  185. },
  186. {
  187. name: "transitional-sending to enforced",
  188. myPskMode: nebula.PskTransitionalSending,
  189. theirPskMode: nebula.PskEnforced,
  190. },
  191. // All enforced
  192. {
  193. name: "both enforced",
  194. myPskMode: nebula.PskEnforced,
  195. theirPskMode: nebula.PskEnforced,
  196. },
  197. // Enforced can technically handshake with a traditional-accepting but it is bad to be in this state
  198. {
  199. name: "enforced to traditional-accepting",
  200. myPskMode: nebula.PskEnforced,
  201. theirPskMode: nebula.PskTransitionalAccepting,
  202. },
  203. }
  204. for _, test := range tests {
  205. t.Run(test.name, func(t *testing.T) {
  206. var myPskSettings, theirPskSettings *m
  207. switch test.myPskMode {
  208. case nebula.PskNone:
  209. myPskSettings = &m{"handshakes": &m{"psk": &m{"mode": "none"}}}
  210. case nebula.PskTransitionalAccepting:
  211. myPskSettings = &m{"handshakes": &m{"psk": &m{"mode": "transitional-accepting", "keys": []string{"this is a key"}}}}
  212. case nebula.PskTransitionalSending:
  213. myPskSettings = &m{"handshakes": &m{"psk": &m{"mode": "transitional-sending", "keys": []string{"this is a key"}}}}
  214. case nebula.PskEnforced:
  215. myPskSettings = &m{"handshakes": &m{"psk": &m{"mode": "enforced", "keys": []string{"this is a key"}}}}
  216. }
  217. switch test.theirPskMode {
  218. case nebula.PskNone:
  219. theirPskSettings = &m{"handshakes": &m{"psk": &m{"mode": "none"}}}
  220. case nebula.PskTransitionalAccepting:
  221. theirPskSettings = &m{"handshakes": &m{"psk": &m{"mode": "transitional-accepting", "keys": []string{"this is a key"}}}}
  222. case nebula.PskTransitionalSending:
  223. theirPskSettings = &m{"handshakes": &m{"psk": &m{"mode": "transitional-sending", "keys": []string{"this is a key"}}}}
  224. case nebula.PskEnforced:
  225. theirPskSettings = &m{"handshakes": &m{"psk": &m{"mode": "enforced", "keys": []string{"this is a key"}}}}
  226. }
  227. ca, _, caKey, _ := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  228. myControl, myVpnIp, myUdpAddr := newSimpleServer(ca, caKey, "me", net.IP{10, 0, 0, 1}, myPskSettings)
  229. theirControl, theirVpnIp, theirUdpAddr := newSimpleServer(ca, caKey, "them", net.IP{10, 0, 0, 2}, theirPskSettings)
  230. myControl.InjectLightHouseAddr(theirVpnIp, theirUdpAddr)
  231. r := router.NewR(myControl, theirControl)
  232. // Start the servers
  233. myControl.Start()
  234. theirControl.Start()
  235. t.Log("Route until we see our cached packet flow")
  236. myControl.InjectTunUDPPacket(theirVpnIp, 80, 80, []byte("Hi from me"))
  237. r.RouteForAllExitFunc(func(p *udp.Packet, c *nebula.Control) router.ExitType {
  238. h := &header.H{}
  239. err := h.Parse(p.Data)
  240. if err != nil {
  241. panic(err)
  242. }
  243. // If this is the stage 1 handshake packet and I am configured to send with a psk, my cert name should
  244. // not appear. It would likely be more obvious to unmarshal the payload and check but this works fine for now
  245. if test.myPskMode == nebula.PskEnforced || test.myPskMode == nebula.PskTransitionalSending {
  246. if h.Type == 0 && h.MessageCounter == 1 {
  247. assert.NotContains(t, string(p.Data), "test me")
  248. }
  249. }
  250. if p.ToIp.Equal(theirUdpAddr.IP) && p.ToPort == uint16(theirUdpAddr.Port) && h.Type == 1 {
  251. return router.RouteAndExit
  252. }
  253. return router.KeepRouting
  254. })
  255. t.Log("My cached packet should be received by them")
  256. myCachedPacket := theirControl.GetFromTun(true)
  257. assertUdpPacket(t, []byte("Hi from me"), myCachedPacket, myVpnIp, theirVpnIp, 80, 80)
  258. t.Log("Test the tunnel with them")
  259. assertHostInfoPair(t, myUdpAddr, theirUdpAddr, myVpnIp, theirVpnIp, myControl, theirControl)
  260. assertTunnel(t, myVpnIp, theirVpnIp, myControl, theirControl, r)
  261. myControl.Stop()
  262. theirControl.Stop()
  263. //TODO: assert hostmaps
  264. })
  265. }
  266. }