|
|
@@ -20,7 +20,8 @@ const (
|
|
|
minFwPacketLen = 4
|
|
|
)
|
|
|
|
|
|
-func (f *Interface) readOutsidePackets(via ViaSender, out []byte, packet []byte, h *header.H, fwPacket *firewall.Packet, lhf *LightHouseHandler, nb []byte, q int, localCache firewall.ConntrackCache, now time.Time) {
|
|
|
+func (f *Interface) readOutsidePacketFromRelay(via ViaSender, out []byte, packet []byte, h *header.H, fwPacket *firewall.Packet, lhf *LightHouseHandler, nb []byte, q int, localCache firewall.ConntrackCache, now time.Time) {
|
|
|
+ //todo this is way too similar to readOutsidePacketsMany, find a way to eliminate
|
|
|
err := h.Parse(packet)
|
|
|
if err != nil {
|
|
|
// Hole punch packets are 0 or 1 byte big, so lets ignore printing those errors
|
|
|
@@ -65,70 +66,11 @@ func (f *Interface) readOutsidePackets(via ViaSender, out []byte, packet []byte,
|
|
|
return
|
|
|
}
|
|
|
case header.MessageRelay:
|
|
|
- // The entire body is sent as AD, not encrypted.
|
|
|
- // The packet consists of a 16-byte parsed Nebula header, Associated Data-protected payload, and a trailing 16-byte AEAD signature value.
|
|
|
- // The packet is guaranteed to be at least 16 bytes at this point, b/c it got past the h.Parse() call above. If it's
|
|
|
- // otherwise malformed (meaning, there is no trailing 16 byte AEAD value), then this will result in at worst a 0-length slice
|
|
|
- // which will gracefully fail in the DecryptDanger call.
|
|
|
- signedPayload := packet[:len(packet)-hostinfo.ConnectionState.dKey.Overhead()]
|
|
|
- signatureValue := packet[len(packet)-hostinfo.ConnectionState.dKey.Overhead():]
|
|
|
- out, err = hostinfo.ConnectionState.dKey.DecryptDanger(out, signedPayload, signatureValue, h.MessageCounter, nb)
|
|
|
- if err != nil {
|
|
|
- return
|
|
|
- }
|
|
|
- // Successfully validated the thing. Get rid of the Relay header.
|
|
|
- signedPayload = signedPayload[header.Len:]
|
|
|
- // Pull the Roaming parts up here, and return in all call paths.
|
|
|
- f.handleHostRoaming(hostinfo, via)
|
|
|
- // Track usage of both the HostInfo and the Relay for the received & authenticated packet
|
|
|
- f.connectionManager.In(hostinfo)
|
|
|
- f.connectionManager.RelayUsed(h.RemoteIndex)
|
|
|
-
|
|
|
- relay, ok := hostinfo.relayState.QueryRelayForByIdx(h.RemoteIndex)
|
|
|
- if !ok {
|
|
|
- // The only way this happens is if hostmap has an index to the correct HostInfo, but the HostInfo is missing
|
|
|
- // its internal mapping. This should never happen.
|
|
|
- hostinfo.logger(f.l).WithFields(logrus.Fields{"vpnAddrs": hostinfo.vpnAddrs, "remoteIndex": h.RemoteIndex}).Error("HostInfo missing remote relay index")
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- switch relay.Type {
|
|
|
- case TerminalType:
|
|
|
- // If I am the target of this relay, process the unwrapped packet
|
|
|
- // From this recursive point, all these variables are 'burned'. We shouldn't rely on them again.
|
|
|
- via = ViaSender{
|
|
|
- UdpAddr: via.UdpAddr,
|
|
|
- relayHI: hostinfo,
|
|
|
- remoteIdx: relay.RemoteIndex,
|
|
|
- relay: relay,
|
|
|
- IsRelayed: true,
|
|
|
- }
|
|
|
- f.readOutsidePackets(via, out[:0], signedPayload, h, fwPacket, lhf, nb, q, localCache, now)
|
|
|
- return
|
|
|
- case ForwardingType:
|
|
|
- // Find the target HostInfo relay object
|
|
|
- targetHI, targetRelay, err := f.hostMap.QueryVpnAddrsRelayFor(hostinfo.vpnAddrs, relay.PeerAddr)
|
|
|
- if err != nil {
|
|
|
- hostinfo.logger(f.l).WithField("relayTo", relay.PeerAddr).WithError(err).WithField("hostinfo.vpnAddrs", hostinfo.vpnAddrs).Info("Failed to find target host info by ip")
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // If that relay is Established, forward the payload through it
|
|
|
- if targetRelay.State == Established {
|
|
|
- switch targetRelay.Type {
|
|
|
- case ForwardingType:
|
|
|
- // Forward this packet through the relay tunnel
|
|
|
- // Find the target HostInfo
|
|
|
- f.SendVia(targetHI, targetRelay, signedPayload, nb, out, false)
|
|
|
- return
|
|
|
- case TerminalType:
|
|
|
- hostinfo.logger(f.l).Error("Unexpected Relay Type of Terminal")
|
|
|
- }
|
|
|
- } else {
|
|
|
- hostinfo.logger(f.l).WithFields(logrus.Fields{"relayTo": relay.PeerAddr, "relayFrom": hostinfo.vpnAddrs[0], "targetRelayState": targetRelay.State}).Info("Unexpected target relay state")
|
|
|
- return
|
|
|
- }
|
|
|
+ //this packet already came to us via a relay
|
|
|
+ if f.l.Level >= logrus.DebugLevel {
|
|
|
+ f.l.WithField("from", via).Debug("Refusing to process double relayed packet")
|
|
|
}
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
case header.LightHouse:
|
|
|
@@ -308,7 +250,14 @@ func (f *Interface) readOutsidePacketsMany(packets []*packet.Packet, out []*pack
|
|
|
case TerminalType:
|
|
|
// If I am the target of this relay, process the unwrapped packet
|
|
|
// From this recursive point, all these variables are 'burned'. We shouldn't rely on them again.
|
|
|
- f.readOutsidePackets(ViaSender{relayHI: hostinfo, remoteIdx: relay.RemoteIndex, relay: relay}, out[i].Scratch[:0], signedPayload, h, fwPacket, lhf, nb, q, localCache, now)
|
|
|
+ via = ViaSender{
|
|
|
+ UdpAddr: via.UdpAddr,
|
|
|
+ relayHI: hostinfo,
|
|
|
+ remoteIdx: relay.RemoteIndex,
|
|
|
+ relay: relay,
|
|
|
+ IsRelayed: true,
|
|
|
+ }
|
|
|
+ f.readOutsidePacketFromRelay(via, out[i].Scratch[:0], signedPayload, h, fwPacket, lhf, nb, q, localCache, now)
|
|
|
return
|
|
|
case ForwardingType:
|
|
|
// Find the target HostInfo relay object
|