| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | package nebula | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"github.com/flynn/noise" | 
					
						
							|  |  |  | 	"github.com/sirupsen/logrus" | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 	"github.com/slackhq/nebula/firewall" | 
					
						
							|  |  |  | 	"github.com/slackhq/nebula/header" | 
					
						
							|  |  |  | 	"github.com/slackhq/nebula/iputil" | 
					
						
							|  |  |  | 	"github.com/slackhq/nebula/udp" | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | func (f *Interface) consumeInsidePacket(packet []byte, fwPacket *firewall.Packet, nb, out []byte, q int, localCache firewall.ConntrackCache) { | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	err := newPacket(packet, false, fwPacket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-01 09:44:58 -05:00
										 |  |  | 		if f.l.Level >= logrus.DebugLevel { | 
					
						
							|  |  |  | 			f.l.WithField("packet", packet).Debugf("Error while validating outbound packet: %s", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Ignore local broadcast packets | 
					
						
							|  |  |  | 	if f.dropLocalBroadcast && fwPacket.RemoteIP == f.localBroadcast { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 10:23:31 -05:00
										 |  |  | 	if fwPacket.RemoteIP == f.myVpnIp { | 
					
						
							| 
									
										
										
										
											2022-06-27 14:36:10 -04:00
										 |  |  | 		// Immediately forward packets from self to self. | 
					
						
							| 
									
										
										
										
											2023-01-23 16:51:54 -05:00
										 |  |  | 		// This should only happen on Darwin-based and FreeBSD hosts, which | 
					
						
							|  |  |  | 		// routes packets from the Nebula IP to the Nebula IP through the Nebula | 
					
						
							|  |  |  | 		// TUN device. | 
					
						
							| 
									
										
										
										
											2022-06-27 14:36:10 -04:00
										 |  |  | 		if immediatelyForwardToSelf { | 
					
						
							|  |  |  | 			_, err := f.readers[q].Write(packet) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				f.l.WithError(err).Error("Failed to forward to tun") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Otherwise, drop. On linux, we should never see these packets - Linux | 
					
						
							|  |  |  | 		// routes packets from the nebula IP to the nebula IP through the loopback device. | 
					
						
							| 
									
										
										
										
											2020-02-21 16:49:54 -08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	// Ignore broadcast packets | 
					
						
							|  |  |  | 	if f.dropMulticast && isMulticast(fwPacket.RemoteIP) { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hostinfo := f.getOrHandshake(fwPacket.RemoteIP) | 
					
						
							| 
									
										
										
										
											2020-08-04 22:59:04 -04:00
										 |  |  | 	if hostinfo == nil { | 
					
						
							| 
									
										
										
										
											2023-03-13 15:08:40 -04:00
										 |  |  | 		f.rejectInside(packet, out, q) | 
					
						
							| 
									
										
										
										
											2021-03-26 09:46:30 -05:00
										 |  |  | 		if f.l.Level >= logrus.DebugLevel { | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 			f.l.WithField("vpnIp", fwPacket.RemoteIP). | 
					
						
							| 
									
										
										
										
											2020-08-04 22:59:04 -04:00
										 |  |  | 				WithField("fwPacket", fwPacket). | 
					
						
							|  |  |  | 				Debugln("dropping outbound packet, vpnIp not in our CIDR or in unsafe routes") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	ci := hostinfo.ConnectionState | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ci.ready == false { | 
					
						
							|  |  |  | 		// Because we might be sending stored packets, lock here to stop new things going to | 
					
						
							|  |  |  | 		// the packet queue. | 
					
						
							|  |  |  | 		ci.queueLock.Lock() | 
					
						
							|  |  |  | 		if !ci.ready { | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 			hostinfo.cachePacket(f.l, header.Message, 0, packet, f.sendMessageNow, f.cachedPacketMetrics) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 			ci.queueLock.Unlock() | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ci.queueLock.Unlock() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 12:10:19 -05:00
										 |  |  | 	dropReason := f.firewall.Drop(packet, *fwPacket, false, hostinfo, f.caPool, localCache) | 
					
						
							| 
									
										
										
										
											2020-04-10 10:57:21 -07:00
										 |  |  | 	if dropReason == nil { | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 		f.sendNoMetrics(header.Message, 0, ci, hostinfo, nil, packet, nb, out, q) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-13 15:08:40 -04:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		f.rejectInside(packet, out, q) | 
					
						
							|  |  |  | 		if f.l.Level >= logrus.DebugLevel { | 
					
						
							|  |  |  | 			hostinfo.logger(f.l). | 
					
						
							|  |  |  | 				WithField("fwPacket", fwPacket). | 
					
						
							|  |  |  | 				WithField("reason", dropReason). | 
					
						
							|  |  |  | 				Debugln("dropping outbound packet") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (f *Interface) rejectInside(packet []byte, out []byte, q int) { | 
					
						
							|  |  |  | 	if !f.firewall.InSendReject { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-03-13 15:08:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	out = iputil.CreateRejectPacket(packet, out) | 
					
						
							|  |  |  | 	_, err := f.readers[q].Write(out) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		f.l.WithError(err).Error("Failed to write to tun") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (f *Interface) rejectOutside(packet []byte, ci *ConnectionState, hostinfo *HostInfo, nb, out []byte, q int) { | 
					
						
							|  |  |  | 	if !f.firewall.OutSendReject { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Use some out buffer space to build the packet before encryption | 
					
						
							|  |  |  | 	// Need 40 bytes for the reject packet (20 byte ipv4 header, 20 byte tcp rst packet) | 
					
						
							|  |  |  | 	// Leave 100 bytes for the encrypted packet (60 byte Nebula header, 40 byte reject packet) | 
					
						
							|  |  |  | 	out = out[:140] | 
					
						
							|  |  |  | 	outPacket := iputil.CreateRejectPacket(packet, out[100:]) | 
					
						
							|  |  |  | 	f.sendNoMetrics(header.Message, 0, ci, hostinfo, nil, outPacket, nb, out, q) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | func (f *Interface) Handshake(vpnIp iputil.VpnIp) { | 
					
						
							|  |  |  | 	f.getOrHandshake(vpnIp) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 22:59:04 -04:00
										 |  |  | // getOrHandshake returns nil if the vpnIp is not routable | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | func (f *Interface) getOrHandshake(vpnIp iputil.VpnIp) *HostInfo { | 
					
						
							| 
									
										
										
										
											2022-09-19 12:47:48 -05:00
										 |  |  | 	if !ipMaskContains(f.lightHouse.myVpnIp, f.lightHouse.myVpnZeros, vpnIp) { | 
					
						
							| 
									
										
										
										
											2021-11-12 11:19:28 -06:00
										 |  |  | 		vpnIp = f.inside.RouteFor(vpnIp) | 
					
						
							| 
									
										
										
										
											2020-08-04 22:59:04 -04:00
										 |  |  | 		if vpnIp == 0 { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-12 16:34:17 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 	hostinfo, err := f.hostMap.PromoteBestQueryVpnIp(vpnIp, f) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	//if err != nil || hostinfo.ConnectionState == nil { | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 		hostinfo, err = f.handshakeManager.pendingHostMap.QueryVpnIp(vpnIp) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2021-11-08 14:46:22 -05:00
										 |  |  | 			hostinfo = f.handshakeManager.AddVpnIp(vpnIp, f.initHostInfo) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ci := hostinfo.ConnectionState | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ci != nil && ci.eKey != nil && ci.ready { | 
					
						
							|  |  |  | 		return hostinfo | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-14 13:50:09 -05:00
										 |  |  | 	// Handshake is not ready, we need to grab the lock now before we start the handshake process | 
					
						
							| 
									
										
										
										
											2021-03-09 09:27:02 -05:00
										 |  |  | 	hostinfo.Lock() | 
					
						
							|  |  |  | 	defer hostinfo.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Double check, now that we have the lock | 
					
						
							|  |  |  | 	ci = hostinfo.ConnectionState | 
					
						
							|  |  |  | 	if ci != nil && ci.eKey != nil && ci.ready { | 
					
						
							|  |  |  | 		return hostinfo | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	// If we have already created the handshake packet, we don't want to call the function at all. | 
					
						
							|  |  |  | 	if !hostinfo.HandshakeReady { | 
					
						
							| 
									
										
										
										
											2021-03-09 09:27:02 -05:00
										 |  |  | 		ixHandshakeStage0(f, vpnIp, hostinfo) | 
					
						
							|  |  |  | 		// FIXME: Maybe make XX selectable, but probably not since psk makes it nearly pointless for us. | 
					
						
							|  |  |  | 		//xx_handshakeStage0(f, ip, hostinfo) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// If this is a static host, we don't need to wait for the HostQueryReply | 
					
						
							|  |  |  | 		// We can trigger the handshake right now | 
					
						
							| 
									
										
										
										
											2023-03-13 15:09:08 -04:00
										 |  |  | 		_, doTrigger := f.lightHouse.GetStaticHostList()[vpnIp] | 
					
						
							|  |  |  | 		if !doTrigger { | 
					
						
							|  |  |  | 			// Add any calculated remotes, and trigger early handshake if one found | 
					
						
							|  |  |  | 			doTrigger = f.lightHouse.addCalculatedRemotes(vpnIp) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if doTrigger { | 
					
						
							| 
									
										
										
										
											2021-03-09 09:27:02 -05:00
										 |  |  | 			select { | 
					
						
							|  |  |  | 			case f.handshakeManager.trigger <- vpnIp: | 
					
						
							|  |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2020-08-02 20:59:50 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return hostinfo | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 14:46:22 -05:00
										 |  |  | // initHostInfo is the init function to pass to (*HandshakeManager).AddVpnIP that | 
					
						
							|  |  |  | // will create the initial Noise ConnectionState | 
					
						
							|  |  |  | func (f *Interface) initHostInfo(hostinfo *HostInfo) { | 
					
						
							|  |  |  | 	hostinfo.ConnectionState = f.newConnectionState(f.l, true, noise.HandshakeIX, []byte{}, 0) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | func (f *Interface) sendMessageNow(t header.MessageType, st header.MessageSubType, hostInfo *HostInfo, p, nb, out []byte) { | 
					
						
							|  |  |  | 	fp := &firewall.Packet{} | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	err := newPacket(p, false, fp) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-03-26 09:46:30 -05:00
										 |  |  | 		f.l.Warnf("error while parsing outgoing packet for firewall check; %v", err) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check if packet is in outbound fw rules | 
					
						
							| 
									
										
										
										
											2021-03-29 12:10:19 -05:00
										 |  |  | 	dropReason := f.firewall.Drop(p, *fp, false, hostInfo, f.caPool, nil) | 
					
						
							| 
									
										
										
										
											2020-06-10 14:55:49 -07:00
										 |  |  | 	if dropReason != nil { | 
					
						
							| 
									
										
										
										
											2021-03-26 09:46:30 -05:00
										 |  |  | 		if f.l.Level >= logrus.DebugLevel { | 
					
						
							|  |  |  | 			f.l.WithField("fwPacket", fp). | 
					
						
							| 
									
										
										
										
											2020-06-10 14:55:49 -07:00
										 |  |  | 				WithField("reason", dropReason). | 
					
						
							|  |  |  | 				Debugln("dropping cached packet") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 	f.sendNoMetrics(header.Message, st, hostInfo.ConnectionState, hostInfo, nil, p, nb, out, 0) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SendMessageToVpnIp handles real ip:port lookup and sends to the current best known address for vpnIp | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | func (f *Interface) SendMessageToVpnIp(t header.MessageType, st header.MessageSubType, vpnIp iputil.VpnIp, p, nb, out []byte) { | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	hostInfo := f.getOrHandshake(vpnIp) | 
					
						
							| 
									
										
										
										
											2020-08-04 22:59:04 -04:00
										 |  |  | 	if hostInfo == nil { | 
					
						
							| 
									
										
										
										
											2021-03-26 09:46:30 -05:00
										 |  |  | 		if f.l.Level >= logrus.DebugLevel { | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 			f.l.WithField("vpnIp", vpnIp). | 
					
						
							| 
									
										
										
										
											2020-08-04 22:59:04 -04:00
										 |  |  | 				Debugln("dropping SendMessageToVpnIp, vpnIp not in our CIDR or in unsafe routes") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if !hostInfo.ConnectionState.ready { | 
					
						
							|  |  |  | 		// Because we might be sending stored packets, lock here to stop new things going to | 
					
						
							|  |  |  | 		// the packet queue. | 
					
						
							|  |  |  | 		hostInfo.ConnectionState.queueLock.Lock() | 
					
						
							|  |  |  | 		if !hostInfo.ConnectionState.ready { | 
					
						
							| 
									
										
										
										
											2021-04-27 22:23:18 -04:00
										 |  |  | 			hostInfo.cachePacket(f.l, t, st, p, f.sendMessageToVpnIp, f.cachedPacketMetrics) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 			hostInfo.ConnectionState.queueLock.Unlock() | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		hostInfo.ConnectionState.queueLock.Unlock() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f.sendMessageToVpnIp(t, st, hostInfo, p, nb, out) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | func (f *Interface) sendMessageToVpnIp(t header.MessageType, st header.MessageSubType, hostInfo *HostInfo, p, nb, out []byte) { | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 	f.send(t, st, hostInfo.ConnectionState, hostInfo, p, nb, out) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (f *Interface) send(t header.MessageType, st header.MessageSubType, ci *ConnectionState, hostinfo *HostInfo, p, nb, out []byte) { | 
					
						
							|  |  |  | 	f.messageMetrics.Tx(t, st, 1) | 
					
						
							|  |  |  | 	f.sendNoMetrics(t, st, ci, hostinfo, nil, p, nb, out, 0) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | func (f *Interface) sendTo(t header.MessageType, st header.MessageSubType, ci *ConnectionState, hostinfo *HostInfo, remote *udp.Addr, p, nb, out []byte) { | 
					
						
							| 
									
										
										
										
											2020-06-26 13:45:48 -04:00
										 |  |  | 	f.messageMetrics.Tx(t, st, 1) | 
					
						
							| 
									
										
										
										
											2021-02-25 15:01:14 -05:00
										 |  |  | 	f.sendNoMetrics(t, st, ci, hostinfo, remote, p, nb, out, 0) | 
					
						
							| 
									
										
										
										
											2020-06-26 13:45:48 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | // sendVia sends a payload through a Relay tunnel. No authentication or encryption is done | 
					
						
							|  |  |  | // to the payload for the ultimate target host, making this a useful method for sending | 
					
						
							|  |  |  | // handshake messages to peers through relay tunnels. | 
					
						
							|  |  |  | // via is the HostInfo through which the message is relayed. | 
					
						
							|  |  |  | // ad is the plaintext data to authenticate, but not encrypt | 
					
						
							|  |  |  | // nb is a buffer used to store the nonce value, re-used for performance reasons. | 
					
						
							|  |  |  | // out is a buffer used to store the result of the Encrypt operation | 
					
						
							|  |  |  | // q indicates which writer to use to send the packet. | 
					
						
							|  |  |  | func (f *Interface) SendVia(viaIfc interface{}, | 
					
						
							|  |  |  | 	relayIfc interface{}, | 
					
						
							|  |  |  | 	ad, | 
					
						
							|  |  |  | 	nb, | 
					
						
							|  |  |  | 	out []byte, | 
					
						
							|  |  |  | 	nocopy bool, | 
					
						
							|  |  |  | ) { | 
					
						
							|  |  |  | 	via := viaIfc.(*HostInfo) | 
					
						
							|  |  |  | 	relay := relayIfc.(*Relay) | 
					
						
							| 
									
										
										
										
											2022-10-31 13:37:41 -04:00
										 |  |  | 	c := via.ConnectionState.messageCounter.Add(1) | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	out = header.Encode(out, header.Version, header.Message, header.MessageRelay, relay.RemoteIndex, c) | 
					
						
							| 
									
										
										
										
											2023-02-13 14:41:05 -06:00
										 |  |  | 	f.connectionManager.Out(via.localIndexId) | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Authenticate the header and payload, but do not encrypt for this message type. | 
					
						
							|  |  |  | 	// The payload consists of the inner, unencrypted Nebula header, as well as the end-to-end encrypted payload. | 
					
						
							|  |  |  | 	if len(out)+len(ad)+via.ConnectionState.eKey.Overhead() > cap(out) { | 
					
						
							|  |  |  | 		via.logger(f.l). | 
					
						
							|  |  |  | 			WithField("outCap", cap(out)). | 
					
						
							|  |  |  | 			WithField("payloadLen", len(ad)). | 
					
						
							|  |  |  | 			WithField("headerLen", len(out)). | 
					
						
							|  |  |  | 			WithField("cipherOverhead", via.ConnectionState.eKey.Overhead()). | 
					
						
							|  |  |  | 			Error("SendVia out buffer not large enough for relay") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// The header bytes are written to the 'out' slice; Grow the slice to hold the header and associated data payload. | 
					
						
							|  |  |  | 	offset := len(out) | 
					
						
							|  |  |  | 	out = out[:offset+len(ad)] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// In one call path, the associated data _is_ already stored in out. In other call paths, the associated data must | 
					
						
							|  |  |  | 	// be copied into 'out'. | 
					
						
							|  |  |  | 	if !nocopy { | 
					
						
							|  |  |  | 		copy(out[offset:], ad) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	out, err = via.ConnectionState.eKey.EncryptDanger(out, out, nil, c, nb) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		via.logger(f.l).WithError(err).Info("Failed to EncryptDanger in sendVia") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	err = f.writers[0].WriteTo(out, via.remote) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		via.logger(f.l).WithError(err).Info("Failed to WriteTo in sendVia") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | func (f *Interface) sendNoMetrics(t header.MessageType, st header.MessageSubType, ci *ConnectionState, hostinfo *HostInfo, remote *udp.Addr, p, nb, out []byte, q int) { | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	if ci.eKey == nil { | 
					
						
							|  |  |  | 		//TODO: log warning | 
					
						
							| 
									
										
										
										
											2021-04-14 13:50:09 -05:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 	useRelay := remote == nil && hostinfo.remote == nil | 
					
						
							|  |  |  | 	fullOut := out | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if useRelay { | 
					
						
							|  |  |  | 		if len(out) < header.Len { | 
					
						
							|  |  |  | 			// out always has a capacity of mtu, but not always a length greater than the header.Len. | 
					
						
							|  |  |  | 			// Grow it to make sure the next operation works. | 
					
						
							|  |  |  | 			out = out[:header.Len] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Save a header's worth of data at the front of the 'out' buffer. | 
					
						
							|  |  |  | 		out = out[header.Len:] | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	//TODO: enable if we do more than 1 tun queue | 
					
						
							|  |  |  | 	//ci.writeLock.Lock() | 
					
						
							| 
									
										
										
										
											2022-10-31 13:37:41 -04:00
										 |  |  | 	c := ci.messageCounter.Add(1) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	//l.WithField("trace", string(debug.Stack())).Error("out Header ", &Header{Version, t, st, 0, hostinfo.remoteIndexId, c}, p) | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 	out = header.Encode(out, header.Version, t, st, hostinfo.remoteIndexId, c) | 
					
						
							| 
									
										
										
										
											2023-02-13 14:41:05 -06:00
										 |  |  | 	f.connectionManager.Out(hostinfo.localIndexId) | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 19:06:01 -06:00
										 |  |  | 	// Query our LH if we haven't since the last time we've been rebound, this will cause the remote to punch against | 
					
						
							|  |  |  | 	// all our IPs and enable a faster roaming. | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 	if t != header.CloseTunnel && hostinfo.lastRebindCount != f.rebindCount { | 
					
						
							| 
									
										
										
										
											2021-03-01 19:06:01 -06:00
										 |  |  | 		//NOTE: there is an update hole if a tunnel isn't used and exactly 256 rebinds occur before the tunnel is | 
					
						
							|  |  |  | 		// finally used again. This tunnel would eventually be torn down and recreated if this action didn't help. | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 		f.lightHouse.QueryServer(hostinfo.vpnIp, f) | 
					
						
							| 
									
										
										
										
											2021-03-01 19:06:01 -06:00
										 |  |  | 		hostinfo.lastRebindCount = f.rebindCount | 
					
						
							| 
									
										
										
										
											2021-03-26 09:46:30 -05:00
										 |  |  | 		if f.l.Level >= logrus.DebugLevel { | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | 			f.l.WithField("vpnIp", hostinfo.vpnIp).Debug("Lighthouse update triggered for punch due to rebind counter") | 
					
						
							| 
									
										
										
										
											2021-03-01 19:06:01 -06:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 	var err error | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	out, err = ci.eKey.EncryptDanger(out, out, p, c, nb) | 
					
						
							|  |  |  | 	//TODO: see above note on lock | 
					
						
							|  |  |  | 	//ci.writeLock.Unlock() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-03-26 09:46:30 -05:00
										 |  |  | 		hostinfo.logger(f.l).WithError(err). | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 			WithField("udpAddr", remote).WithField("counter", c). | 
					
						
							| 
									
										
										
										
											2021-03-05 21:18:33 -05:00
										 |  |  | 			WithField("attemptedCounter", c). | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 			Error("Failed to encrypt outgoing packet") | 
					
						
							| 
									
										
										
										
											2021-04-14 13:50:09 -05:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 	if remote != nil { | 
					
						
							|  |  |  | 		err = f.writers[q].WriteTo(out, remote) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			hostinfo.logger(f.l).WithError(err). | 
					
						
							|  |  |  | 				WithField("udpAddr", remote).Error("Failed to write outgoing packet") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if hostinfo.remote != nil { | 
					
						
							|  |  |  | 		err = f.writers[q].WriteTo(out, hostinfo.remote) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			hostinfo.logger(f.l).WithError(err). | 
					
						
							|  |  |  | 				WithField("udpAddr", remote).Error("Failed to write outgoing packet") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// Try to send via a relay | 
					
						
							|  |  |  | 		for _, relayIP := range hostinfo.relayState.CopyRelayIps() { | 
					
						
							|  |  |  | 			relayHostInfo, err := f.hostMap.QueryVpnIp(relayIP) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2023-03-30 15:07:31 -05:00
										 |  |  | 				hostinfo.logger(f.l).WithField("relay", relayIP).WithError(err).Info("sendNoMetrics failed to find HostInfo") | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			relay, ok := relayHostInfo.relayState.QueryRelayForByIp(hostinfo.vpnIp) | 
					
						
							|  |  |  | 			if !ok { | 
					
						
							|  |  |  | 				hostinfo.logger(f.l). | 
					
						
							| 
									
										
										
										
											2023-03-30 15:07:31 -05:00
										 |  |  | 					WithField("relay", relayHostInfo.vpnIp). | 
					
						
							|  |  |  | 					WithField("relayTo", hostinfo.vpnIp). | 
					
						
							| 
									
										
										
										
											2022-06-21 14:35:23 -04:00
										 |  |  | 					Info("sendNoMetrics relay missing object for target") | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			f.SendVia(relayHostInfo, relay, out, nb, fullOut[:header.Len+len(out)], true) | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-14 13:50:09 -05:00
										 |  |  | 	return | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-03 20:54:04 -05:00
										 |  |  | func isMulticast(ip iputil.VpnIp) bool { | 
					
						
							| 
									
										
										
										
											2019-11-19 17:00:20 +00:00
										 |  |  | 	// Class D multicast | 
					
						
							|  |  |  | 	if (((ip >> 24) & 0xff) & 0xf0) == 0xe0 { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } |