@@ -725,6 +725,70 @@ func TestReestablishRelays(t *testing.T) {
725725
726726}
727727
728+ func TestRelayHandshakeOverDisestablishedEntry (t * testing.T ) {
729+ t .Parallel ()
730+ // If them tears down the tunnel while me keeps Established relay state, me's next
731+ // handshake flows through the relay with no fresh CreateRelayRequest and lands on
732+ // them's Disestablished terminal relay entry. them must re-establish that entry, or
733+ // its first transmit deletes its only relay and the tunnel is born transmit-dead:
734+ // them can receive but every send is silently dropped.
735+ ca , _ , caKey , _ := cert_test .NewTestCaCert (cert .Version1 , cert .Curve_CURVE25519 , time .Now (), time .Now ().Add (10 * time .Minute ), nil , nil , []string {})
736+ myControl , myVpnIpNet , _ , _ := newSimpleServer (cert .Version1 , ca , caKey , "me " , "10.128.0.1/24" , m {"relay" : m {"use_relays" : true }})
737+ relayControl , relayVpnIpNet , relayUdpAddr , _ := newSimpleServer (cert .Version1 , ca , caKey , "relay " , "10.128.0.128/24" , m {"relay" : m {"am_relay" : true }})
738+ theirControl , theirVpnIpNet , theirUdpAddr , _ := newSimpleServer (cert .Version1 , ca , caKey , "them " , "10.128.0.2/24" , m {"relay" : m {"use_relays" : true }})
739+
740+ // Teach my how to get to the relay and that their can be reached via the relay
741+ myControl .InjectLightHouseAddr (relayVpnIpNet [0 ].Addr (), relayUdpAddr )
742+ myControl .InjectRelays (theirVpnIpNet [0 ].Addr (), []netip.Addr {relayVpnIpNet [0 ].Addr ()})
743+ relayControl .InjectLightHouseAddr (theirVpnIpNet [0 ].Addr (), theirUdpAddr )
744+
745+ // Build a router so we don't have to reason who gets which packet
746+ r := router .NewR (t , myControl , relayControl , theirControl )
747+ defer r .RenderFlow ()
748+
749+ // Start the servers
750+ myControl .Start ()
751+ relayControl .Start ()
752+ theirControl .Start ()
753+
754+ t .Log ("Trigger a handshake from me to them via the relay" )
755+ myControl .InjectTunPacket (BuildTunUDPPacket (theirVpnIpNet [0 ].Addr (), 80 , myVpnIpNet [0 ].Addr (), 80 , []byte ("Hi from me" )))
756+
757+ p := r .RouteForAllUntilTxTun (theirControl )
758+ assertUdpPacket (t , []byte ("Hi from me" ), p , myVpnIpNet [0 ].Addr (), theirVpnIpNet [0 ].Addr (), 80 , 80 )
759+ oldIdx := myControl .GetHostInfoByVpnAddr (theirVpnIpNet [0 ].Addr (), false ).LocalIndex
760+
761+ t .Log ("Close the tunnel on them only, marking their relay entry Disestablished" )
762+ theirControl .CloseTunnel (myVpnIpNet [0 ].Addr (), true )
763+
764+ t .Log ("Re-handshake from me, riding the still-Established relay state" )
765+ myControl .ReHandshake (theirVpnIpNet [0 ].Addr ())
766+ for {
767+ h := myControl .GetHostInfoByVpnAddr (theirVpnIpNet [0 ].Addr (), false )
768+ if h != nil && h .LocalIndex != oldIdx && h .RemoteIndex != 0 {
769+ break
770+ }
771+ r .RouteForAllExitFunc (func (* udp.Packet , * nebula.Control ) router.ExitType {
772+ return router .RouteAndExit
773+ })
774+ }
775+
776+ hAtThem := theirControl .GetHostInfoByVpnAddr (myVpnIpNet [0 ].Addr (), false )
777+ require .NotNil (t , hAtThem , "them should have completed the relayed handshake" )
778+ require .Equal (t , []netip.Addr {relayVpnIpNet [0 ].Addr ()}, hAtThem .CurrentRelaysToMe , "them should know a relay for the new tunnel" )
779+
780+ t .Log ("Send from them to me; their only relay entry must survive the transmit" )
781+ theirControl .InjectTunPacket (BuildTunUDPPacket (myVpnIpNet [0 ].Addr (), 80 , theirVpnIpNet [0 ].Addr (), 80 , []byte ("Hi from them" )))
782+ require .Never (t , func () bool {
783+ h := theirControl .GetHostInfoByVpnAddr (myVpnIpNet [0 ].Addr (), false )
784+ return h == nil || len (h .CurrentRelaysToMe ) == 0
785+ }, time .Second , 10 * time .Millisecond , "them deleted its only relay entry; the tunnel is permanently transmit-dead" )
786+
787+ p = r .RouteForAllUntilTxTun (myControl )
788+ assertUdpPacket (t , []byte ("Hi from them" ), p , theirVpnIpNet [0 ].Addr (), myVpnIpNet [0 ].Addr (), 80 , 80 )
789+ r .RenderHostmaps ("Final hostmaps" , myControl , relayControl , theirControl )
790+ }
791+
728792func TestStage1RaceRelays (t * testing.T ) {
729793 t .Parallel ()
730794 //NOTE: this is a race between me and relay resulting in a full tunnel from me to them via relay
0 commit comments