mirror of
https://github.com/slackhq/nebula.git
synced 2026-11-15 18:26:52 +01:00
Send by the relay when hybrid msg3 came by one, the direct address learned from msg1 may only work toward us
This commit is contained in:
1 parent
bd82089a3f
commit
437d47ffc5
2 files changed
+62
No files matched your search
@@ -649,3 +649,60 @@ func TestHybridMsg2LostDirect(t *testing.T) {
|
|||||||
relayControl.Stop()
|
relayControl.Stop()
|
||||||
theirControl.Stop()
|
theirControl.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestHybridOneWayDirect loses everything the responder sends directly, not
|
||||||
|
// just msg2, so only the relay carries anything back. msg3 comes by the relay,
|
||||||
|
// since that is where msg2 got through, and the responder must then send by the
|
||||||
|
// relay too: its confirmation, and its replies. Keeping the direct address it
|
||||||
|
// learned from msg1 would lose both, and the initiator would close the tunnel as
|
||||||
|
// never confirmed.
|
||||||
|
func TestHybridOneWayDirect(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
ca := newHybridCA(t)
|
||||||
|
useRelays := pqRequire()
|
||||||
|
useRelays["relay"] = m{"use_relays": true}
|
||||||
|
// The relay takes about a second to come up in this harness; 8 retries make the
|
||||||
|
// handshake timeout 3.6s, which the end of the test waits out.
|
||||||
|
useRelays["handshakes"].(m)["retries"] = 8
|
||||||
|
amRelay := pqRequire()
|
||||||
|
amRelay["relay"] = m{"am_relay": true}
|
||||||
|
myControl, myVpn, _, _ := newSimpleServer(cert.Version3, ca.ca, ca.key, "me ", "10.128.0.1/24", useRelays)
|
||||||
|
relayControl, relayVpn, relayUdp, _ := newSimpleServer(cert.Version3, ca.ca, ca.key, "relay ", "10.128.0.128/24", amRelay)
|
||||||
|
theirControl, theirVpn, theirUdp, _ := newSimpleServer(cert.Version3, ca.ca, ca.key, "them ", "10.128.0.2/24", useRelays)
|
||||||
|
|
||||||
|
myControl.InjectLightHouseAddr(theirVpn[0].Addr(), theirUdp)
|
||||||
|
myControl.InjectLightHouseAddr(relayVpn[0].Addr(), relayUdp)
|
||||||
|
myControl.InjectRelays(theirVpn[0].Addr(), []netip.Addr{relayVpn[0].Addr()})
|
||||||
|
relayControl.InjectLightHouseAddr(theirVpn[0].Addr(), theirUdp)
|
||||||
|
|
||||||
|
r := router.NewR(t, myControl, relayControl, theirControl)
|
||||||
|
defer r.RenderFlow()
|
||||||
|
myControl.Start()
|
||||||
|
relayControl.Start()
|
||||||
|
theirControl.Start()
|
||||||
|
|
||||||
|
oneWay := func(p *udp.Packet, receiver *nebula.Control) router.ExitType {
|
||||||
|
if p.From == theirUdp && receiver == myControl {
|
||||||
|
return router.Drop
|
||||||
|
}
|
||||||
|
return router.KeepRouting
|
||||||
|
}
|
||||||
|
|
||||||
|
myControl.InjectTunPacket(BuildTunUDPPacket(theirVpn[0].Addr(), 80, myVpn[0].Addr(), 80, []byte("Hi from me")))
|
||||||
|
require.True(t, routeUntilData(t, r, theirControl, 10*time.Second, oneWay), "tunnel never came up")
|
||||||
|
assertUdpPacket(t, []byte("Hi from me"), theirControl.GetFromTun(true), myVpn[0].Addr(), theirVpn[0].Addr(), 80, 80)
|
||||||
|
|
||||||
|
theirControl.InjectTunPacket(BuildTunUDPPacket(myVpn[0].Addr(), 80, theirVpn[0].Addr(), 80, []byte("Hi from them")))
|
||||||
|
require.True(t, routeUntilData(t, r, myControl, 3*time.Second, oneWay), "the reply never came back")
|
||||||
|
assertUdpPacket(t, []byte("Hi from them"), myControl.GetFromTun(true), theirVpn[0].Addr(), myVpn[0].Addr(), 80, 80)
|
||||||
|
|
||||||
|
// Well past the handshake timeout, the initiator must still have the tunnel.
|
||||||
|
r.RouteForAllExitFuncOrTimeout(4*time.Second, oneWay)
|
||||||
|
mine := myControl.GetHostInfoByVpnAddr(theirVpn[0].Addr(), false)
|
||||||
|
require.NotNil(t, mine, "the initiator heard back, so it kept the tunnel")
|
||||||
|
assert.Equal(t, cert.Version3, mine.Cert.Version())
|
||||||
|
|
||||||
|
myControl.Stop()
|
||||||
|
relayControl.Stop()
|
||||||
|
theirControl.Stop()
|
||||||
|
}
|
||||||
@@ -255,9 +255,14 @@ func (hm *HandshakeManager) completeHybridResponder(via ViaSender, hh *Handshake
|
|||||||
hostinfo.ConnectionState = cs
|
hostinfo.ConnectionState = cs
|
||||||
hostinfo.remoteIndexId = result.RemoteIndex
|
hostinfo.remoteIndexId = result.RemoteIndex
|
||||||
hostinfo.lastHandshakeTime = result.HandshakeTime
|
hostinfo.lastHandshakeTime = result.HandshakeTime
|
||||||
|
// The initiator sends msg3 by the path its msg2 got through, so that path
|
||||||
|
// works both ways: send by it. A relayed msg3 also means the direct address
|
||||||
|
// learned from msg1 may only work toward us, so forget it and let traffic,
|
||||||
|
// the confirmation first, go by the relay.
|
||||||
if !via.IsRelayed {
|
if !via.IsRelayed {
|
||||||
hostinfo.SetRemote(via.UdpAddr)
|
hostinfo.SetRemote(via.UdpAddr)
|
||||||
} else {
|
} else {
|
||||||
|
hostinfo.remote.Store(nil)
|
||||||
hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
|
hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
|
||||||
}
|
}
|
||||||
remoteCert := result.RemoteCert
|
remoteCert := result.RemoteCert
|
||||||
|
|||||||
Reference in new issue
Block a user