@@ -6,9 +6,12 @@ package e2e
66import (
77 "fmt"
88 "net/netip"
9+ "slices"
910 "testing"
1011 "time"
1112
13+ "github.com/google/gopacket"
14+ "github.com/google/gopacket/layers"
1215 "github.com/sirupsen/logrus"
1316 "github.com/slackhq/nebula"
1417 "github.com/slackhq/nebula/e2e/router"
@@ -369,6 +372,137 @@ func TestRelays(t *testing.T) {
369372 //TODO: assert we actually used the relay even though it should be impossible for a tunnel to have occurred without it
370373}
371374
375+ func TestReestablishRelays (t * testing.T ) {
376+ ca , _ , caKey , _ := NewTestCaCert (time .Now (), time .Now ().Add (10 * time .Minute ), nil , nil , []string {})
377+ myControl , myVpnIpNet , _ , _ := newSimpleServer (ca , caKey , "me " , "10.128.0.1/24" , m {"relay" : m {"use_relays" : true }})
378+ relayControl , relayVpnIpNet , relayUdpAddr , _ := newSimpleServer (ca , caKey , "relay " , "10.128.0.128/24" , m {"relay" : m {"am_relay" : true }})
379+ theirControl , theirVpnIpNet , theirUdpAddr , _ := newSimpleServer (ca , caKey , "them " , "10.128.0.2/24" , m {"relay" : m {"use_relays" : true }})
380+
381+ // Teach my how to get to the relay and that their can be reached via the relay
382+ myControl .InjectLightHouseAddr (relayVpnIpNet .Addr (), relayUdpAddr )
383+ myControl .InjectRelays (theirVpnIpNet .Addr (), []netip.Addr {relayVpnIpNet .Addr ()})
384+ relayControl .InjectLightHouseAddr (theirVpnIpNet .Addr (), theirUdpAddr )
385+
386+ // Build a router so we don't have to reason who gets which packet
387+ r := router .NewR (t , myControl , relayControl , theirControl )
388+ defer r .RenderFlow ()
389+
390+ // Start the servers
391+ myControl .Start ()
392+ relayControl .Start ()
393+ theirControl .Start ()
394+
395+ t .Log ("Trigger a handshake from me to them via the relay" )
396+ myControl .InjectTunUDPPacket (theirVpnIpNet .Addr (), 80 , 80 , []byte ("Hi from me" ))
397+
398+ p := r .RouteForAllUntilTxTun (theirControl )
399+ r .Log ("Assert the tunnel works" )
400+ assertUdpPacket (t , []byte ("Hi from me" ), p , myVpnIpNet .Addr (), theirVpnIpNet .Addr (), 80 , 80 )
401+
402+ t .Log ("Ensure packet traversal from them to me via the relay" )
403+ theirControl .InjectTunUDPPacket (myVpnIpNet .Addr (), 80 , 80 , []byte ("Hi from them" ))
404+
405+ p = r .RouteForAllUntilTxTun (myControl )
406+ r .Log ("Assert the tunnel works" )
407+ assertUdpPacket (t , []byte ("Hi from them" ), p , theirVpnIpNet .Addr (), myVpnIpNet .Addr (), 80 , 80 )
408+
409+ // If we break the relay's connection to 'them', 'me' needs to detect and recover the connection
410+ r .Log ("Close the tunnel" )
411+ relayControl .CloseTunnel (theirVpnIpNet .Addr (), true )
412+
413+ start := len (myControl .GetHostmap ().Indexes )
414+ curIndexes := len (myControl .GetHostmap ().Indexes )
415+ for curIndexes >= start {
416+ curIndexes = len (myControl .GetHostmap ().Indexes )
417+ r .Logf ("Wait for the dead index to go away:start=%v indexes, currnet=%v indexes" , start , curIndexes )
418+ myControl .InjectTunUDPPacket (theirVpnIpNet .Addr (), 80 , 80 , []byte ("Hi from me should fail" ))
419+
420+ r .RouteForAllExitFunc (func (p * udp.Packet , c * nebula.Control ) router.ExitType {
421+ return router .RouteAndExit
422+ })
423+ time .Sleep (2 * time .Second )
424+ }
425+ r .Log ("Dead index went away. Woot!" )
426+ r .RenderHostmaps ("Me removed hostinfo" , myControl , relayControl , theirControl )
427+ // Next packet should re-establish a relayed connection and work just great.
428+
429+ t .Logf ("Assert the tunnel..." )
430+ for {
431+ t .Log ("RouteForAllUntilTxTun" )
432+ myControl .InjectLightHouseAddr (relayVpnIpNet .Addr (), relayUdpAddr )
433+ myControl .InjectRelays (theirVpnIpNet .Addr (), []netip.Addr {relayVpnIpNet .Addr ()})
434+ relayControl .InjectLightHouseAddr (theirVpnIpNet .Addr (), theirUdpAddr )
435+ myControl .InjectTunUDPPacket (theirVpnIpNet .Addr (), 80 , 80 , []byte ("Hi from me" ))
436+
437+ p = r .RouteForAllUntilTxTun (theirControl )
438+ r .Log ("Assert the tunnel works" )
439+ packet := gopacket .NewPacket (p , layers .LayerTypeIPv4 , gopacket .Lazy )
440+ v4 := packet .Layer (layers .LayerTypeIPv4 ).(* layers.IPv4 )
441+ if slices .Compare (v4 .SrcIP , myVpnIpNet .Addr ().AsSlice ()) != 0 {
442+ t .Logf ("SrcIP is unexpected...this is not the packet I'm looking for. Keep looking" )
443+ continue
444+ }
445+ if slices .Compare (v4 .DstIP , theirVpnIpNet .Addr ().AsSlice ()) != 0 {
446+ t .Logf ("DstIP is unexpected...this is not the packet I'm looking for. Keep looking" )
447+ continue
448+ }
449+
450+ udp := packet .Layer (layers .LayerTypeUDP ).(* layers.UDP )
451+ if udp == nil {
452+ t .Log ("Not a UDP packet. This is not the packet I'm looking for. Keep looking" )
453+ continue
454+ }
455+ data := packet .ApplicationLayer ()
456+ if data == nil {
457+ t .Log ("No data found in packet. This is not the packet I'm looking for. Keep looking." )
458+ continue
459+ }
460+ if string (data .Payload ()) != "Hi from me" {
461+ t .Logf ("Unexpected payload: '%v', keep looking" , string (data .Payload ()))
462+ continue
463+ }
464+ t .Log ("I found my lost packet. I am so happy." )
465+ break
466+ }
467+ t .Log ("Assert the tunnel works the other way, too" )
468+ for {
469+ t .Log ("RouteForAllUntilTxTun" )
470+ theirControl .InjectTunUDPPacket (myVpnIpNet .Addr (), 80 , 80 , []byte ("Hi from them" ))
471+
472+ p = r .RouteForAllUntilTxTun (myControl )
473+ r .Log ("Assert the tunnel works" )
474+ packet := gopacket .NewPacket (p , layers .LayerTypeIPv4 , gopacket .Lazy )
475+ v4 := packet .Layer (layers .LayerTypeIPv4 ).(* layers.IPv4 )
476+ if slices .Compare (v4 .DstIP , myVpnIpNet .Addr ().AsSlice ()) != 0 {
477+ t .Logf ("Dst is unexpected...this is not the packet I'm looking for. Keep looking" )
478+ continue
479+ }
480+ if slices .Compare (v4 .SrcIP , theirVpnIpNet .Addr ().AsSlice ()) != 0 {
481+ t .Logf ("SrcIP is unexpected...this is not the packet I'm looking for. Keep looking" )
482+ continue
483+ }
484+
485+ udp := packet .Layer (layers .LayerTypeUDP ).(* layers.UDP )
486+ if udp == nil {
487+ t .Log ("Not a UDP packet. This is not the packet I'm looking for. Keep looking" )
488+ continue
489+ }
490+ data := packet .ApplicationLayer ()
491+ if data == nil {
492+ t .Log ("No data found in packet. This is not the packet I'm looking for. Keep looking." )
493+ continue
494+ }
495+ if string (data .Payload ()) != "Hi from them" {
496+ t .Logf ("Unexpected payload: '%v', keep looking" , string (data .Payload ()))
497+ continue
498+ }
499+ t .Log ("I found my lost packet. I am so happy." )
500+ break
501+ }
502+ r .RenderHostmaps ("Final hostmaps" , myControl , relayControl , theirControl )
503+
504+ }
505+
372506func TestStage1RaceRelays (t * testing.T ) {
373507 //NOTE: this is a race between me and relay resulting in a full tunnel from me to them via relay
374508 ca , _ , caKey , _ := NewTestCaCert (time .Now (), time .Now ().Add (10 * time .Minute ), nil , nil , []string {})
0 commit comments