echo_test.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. //go:build e2e_testing
  2. package e2e
  3. import (
  4. "testing"
  5. "time"
  6. "github.com/slackhq/nebula"
  7. "github.com/slackhq/nebula/cert"
  8. "github.com/slackhq/nebula/cert_test"
  9. "github.com/slackhq/nebula/e2e/router"
  10. "github.com/slackhq/nebula/header"
  11. "github.com/slackhq/nebula/udp"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. )
  15. func assertTestRequestEchoed(t *testing.T, cipher string) {
  16. ca, _, caKey, _ := cert_test.NewTestCaCert(cert.Version1, cert.Curve_CURVE25519, time.Now(), time.Now().Add(10*time.Minute), nil, nil, []string{})
  17. over := m{"cipher": cipher}
  18. a, aNet, aUdp, _ := newSimpleServer(cert.Version1, ca, caKey, "a", "10.128.0.1/24", over)
  19. b, bNet, bUdp, _ := newSimpleServer(cert.Version1, ca, caKey, "b", "10.128.0.2/24", over)
  20. a.InjectLightHouseAddr(bNet[0].Addr(), bUdp)
  21. b.InjectLightHouseAddr(aNet[0].Addr(), aUdp)
  22. a.Start()
  23. b.Start()
  24. t.Cleanup(func() { a.Stop(); b.Stop() })
  25. r := router.NewR(t, a, b)
  26. defer r.RenderFlow()
  27. assertTunnel(t, aNet[0].Addr(), bNet[0].Addr(), a, b, r)
  28. drainUDPTx(a)
  29. drainUDPTx(b)
  30. payload := []byte("a test payload well over sixteen bytes long, wow it's so very long long long!")
  31. require.Greater(t, len(payload), header.Len)
  32. a.GetF().SendMessageToVpnAddr(header.Test, header.TestRequest, bNet[0].Addr(), payload, make([]byte, 12, 12), make([]byte, udp.MTU))
  33. // Deliver A's request to B; B must echo a reply back
  34. b.InjectUDPPacket(a.GetFromUDP(true))
  35. reply := nextUDPTxOfType(t, b, header.Test, header.TestReply, 2*time.Second)
  36. assert.Equal(t, aUdp, reply.To, "the reply must go back to the requester")
  37. // header + echoed payload + 16-byte AEAD tag: proves the whole payload
  38. // round-tripped rather than being dropped or truncated.
  39. assert.Equal(t, header.Len+len(payload)+16, len(reply.Data), "the full payload must be echoed back")
  40. }
  41. func TestTestRequestEchoesLongPayloadAES(t *testing.T) {
  42. assertTestRequestEchoed(t, "aes")
  43. }
  44. func TestTestRequestEchoesLongPayloadChaChaPoly(t *testing.T) {
  45. assertTestRequestEchoed(t, "chachapoly")
  46. }
  47. // drainUDPTx empties a control's UDP tx queue without blocking.
  48. func drainUDPTx(c *nebula.Control) {
  49. for c.GetFromUDP(false) != nil {
  50. }
  51. }
  52. // nextUDPTxOfType returns the next packet a control transmits whose nebula
  53. // header matches (wantType, wantSub), skipping unrelated packets.
  54. // It fails the test if none arrives within the timeout.
  55. func nextUDPTxOfType(t *testing.T, c *nebula.Control, wantType header.MessageType, wantSub header.MessageSubType, within time.Duration) *udp.Packet {
  56. t.Helper()
  57. ch := c.GetUDPTxChan()
  58. timeout := time.After(within)
  59. for {
  60. select {
  61. case p := <-ch:
  62. var h header.H
  63. if err := h.Parse(p.Data); err == nil && h.Type == wantType && h.Subtype == wantSub {
  64. return p
  65. }
  66. case <-timeout:
  67. t.Fatalf("timed out waiting for a %v/%v packet on the udp tx queue", wantType, wantSub)
  68. return nil
  69. }
  70. }
  71. }