Browse Source

Add code to check external surface against reported surface from other trusted peers, and also rename ExternalSurface to SelfAwareness because lulz.

Adam Ierymenko 10 năm trước cách đây
mục cha
commit
a2821e9000
6 tập tin đã thay đổi với 83 bổ sung40 xóa
  1. 40 4
      node/IncomingPacket.cpp
  2. 4 0
      node/Node.cpp
  3. 25 0
      node/Packet.hpp
  4. 4 1
      node/RuntimeEnvironment.hpp
  5. 10 18
      node/SelfAwareness.hpp
  6. 0 17
      node/Topology.hpp

+ 40 - 4
node/IncomingPacket.cpp

@@ -39,6 +39,7 @@
 #include "Switch.hpp"
 #include "Peer.hpp"
 #include "NetworkConfigMaster.hpp"
+#include "SelfAwareness.hpp"
 
 namespace ZeroTier {
 
@@ -174,7 +175,23 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
 		const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION];
 		const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO_IDX_REVISION);
 		const uint64_t timestamp = at<uint64_t>(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP);
-		const Identity id(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
+
+		Identity id;
+		unsigned int destAddrPtr = id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY) + ZT_PROTO_VERB_HELLO_IDX_IDENTITY;
+
+		unsigned int destAddrType = ZT_PROTO_DEST_ADDRESS_TYPE_NONE;
+		if (destAddrPtr < size()) // ZeroTier One < 1.0.3 did not include this field
+			destAddrType = (*this)[destAddrPtr++];
+
+		InetAddress destAddr;
+		switch(destAddrType) {
+			case ZT_PROTO_DEST_ADDRESS_TYPE_IPV4:
+				destAddr.set(field(destAddrPtr,4),4,at<uint16_t>(destAddrPtr + 4));
+				break;
+			case ZT_PROTO_DEST_ADDRESS_TYPE_IPV6:
+				destAddr.set(field(destAddrPtr,16),16,at<uint16_t>(destAddrPtr + 16));
+				break;
+		}
 
 		if (source() != id.address()) {
 			TRACE("dropped HELLO from %s(%s): identity not for sending address",source().toString().c_str(),_remoteAddress.toString().c_str());
@@ -245,11 +262,13 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
 		peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP);
 		peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision);
 
-		// Won't get HELLO *from* supernodes, so skip this for now here. It's done in OK(HELLO).
-		//if (RR->topology->isSupernode(id.address()))
-		//	RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision);
+		if (RR->topology->isSupernode(id.address())) {
+			RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision);
+			RR->sa->iam(destAddr);
+		}
 
 		Packet outp(id.address(),RR->identity.address(),Packet::VERB_OK);
+
 		outp.append((unsigned char)Packet::VERB_HELLO);
 		outp.append(packetId());
 		outp.append(timestamp);
@@ -257,6 +276,23 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
 		outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
 		outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
 		outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
+
+		switch(_remoteAddress.ss_family) {
+			case AF_INET:
+				outp.append((unsigned char)ZT_PROTO_DEST_ADDRESS_TYPE_IPV4);
+				outp.append(_remoteAddress.rawIpData(),4);
+				outp.append((uint16_t)_remoteAddress.port());
+				break;
+			case AF_INET6:
+				outp.append((unsigned char)ZT_PROTO_DEST_ADDRESS_TYPE_IPV6);
+				outp.append(_remoteAddress.rawIpData(),16);
+				outp.append((uint16_t)_remoteAddress.port());
+				break;
+			default:
+				outp.append((unsigned char)ZT_PROTO_DEST_ADDRESS_TYPE_NONE);
+				break;
+		}
+
 		outp.armor(peer->key(),true);
 		RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation);
 	} catch (std::exception &ex) {

+ 4 - 0
node/Node.cpp

@@ -41,6 +41,7 @@
 #include "Logger.hpp"
 #include "Address.hpp"
 #include "Identity.hpp"
+#include "SelfAwareness.hpp"
 
 namespace ZeroTier {
 
@@ -77,7 +78,9 @@ Node::Node(
 		RR->mc = new Multicaster(RR);
 		RR->antiRec = new AntiRecursion();
 		RR->topology = new Topology(RR);
+		RR->sa = new SelfAwareness(RR);
 	} catch ( ... ) {
+		delete RR->sa;
 		delete RR->topology;
 		delete RR->antiRec;
 		delete RR->mc;
@@ -91,6 +94,7 @@ Node::Node(
 
 Node::~Node()
 {
+	delete RR->sa;
 	delete RR->topology;
 	delete RR->antiRec;
 	delete RR->mc;

+ 25 - 0
node/Packet.hpp

@@ -175,6 +175,12 @@
  */
 #define ZT_PROTO_BEACON_IDX_ADDRESS 8
 
+// Destination address types from HELLO and OK(HELLO)
+#define ZT_PROTO_DEST_ADDRESS_TYPE_NONE 0
+#define ZT_PROTO_DEST_ADDRESS_TYPE_ETHERNET 1
+#define ZT_PROTO_DEST_ADDRESS_TYPE_IPV4 4
+#define ZT_PROTO_DEST_ADDRESS_TYPE_IPV6 6
+
 // Field incides for parsing verbs -------------------------------------------
 
 // Some verbs have variable-length fields. Those aren't fully defined here
@@ -467,6 +473,23 @@ public:
 		 *   <[2] software revision>
 		 *   <[8] timestamp (ms since epoch)>
 		 *   <[...] binary serialized identity (see Identity)>
+		 *   <[1] destination address type>
+		 *   [<[...] destination address>]
+		 *
+		 * This is the only message that ever must be sent in the clear, since it
+		 * is used to push an identity to a new peer.
+		 *
+		 * The destination address is the wire address to which this packet is
+		 * being sent, and in OK is *also* the destination address of the OK
+		 * packet. This can be used by the receiver to detect NAT, learn its real
+		 * external address if behind NAT, and detect changes to its external
+		 * address that require re-establishing connectivity.
+		 *
+		 * Destination address types and formats (not all of these are used now):
+		 *   0 - None -- no destination address data present
+		 *   1 - Ethernet address -- format: <[6] Ethernet MAC>
+		 *   4 - 6-byte IPv4 address -- format: <[4] IP>, <[2] port>
+		 *   6 - 18-byte IPv6 address -- format: <[16] IP>, <[2] port>
 		 *
 		 * OK payload:
 		 *   <[8] timestamp (echoed from original HELLO)>
@@ -474,6 +497,8 @@ public:
 		 *   <[1] software major version (of responder)>
 		 *   <[1] software minor version (of responder)>
 		 *   <[2] software revision (of responder)>
+		 *   <[1] destination address type (for this OK, not copied from HELLO)>
+		 *   [<[...] destination address>]
 		 *
 		 * ERROR has no payload.
 		 */

+ 4 - 1
node/RuntimeEnvironment.hpp

@@ -44,6 +44,7 @@ class Node;
 class Multicaster;
 class AntiRecursion;
 class NetworkConfigMaster;
+class SelfAwareness;
 
 /**
  * Holds global state for an instance of ZeroTier::Node
@@ -69,7 +70,8 @@ public:
 		sw((Switch *)0),
 		mc((Multicaster *)0),
 		antiRec((AntiRecursion *)0),
-		topology((Topology *)0)
+		topology((Topology *)0),
+		sa((SelfAwareness *)0)
 	{
 	}
 
@@ -96,6 +98,7 @@ public:
 	Multicaster *mc;
 	AntiRecursion *antiRec;
 	Topology *topology;
+	SelfAwareness *sa;
 };
 
 } // namespace ZeroTier

+ 10 - 18
node/ExternalSurface.hpp → node/SelfAwareness.hpp

@@ -25,40 +25,32 @@
  * LLC. Start here: http://www.zerotier.com/
  */
 
-#ifndef ZT_EXTERNALSURFACE_HPP
-#define ZT_EXTERNALSURFACE_HPP
+#ifndef ZT_SELFAWARENESS_HPP
+#define ZT_SELFAWARENESS_HPP
 
 #include "InetAddress.hpp"
 
 namespace ZeroTier {
 
+class RuntimeEnvironment;
+
 /**
  * Tracks changes to this peer's real world addresses
  */
-class ExternalSurface
+class SelfAwareness
 {
 public:
-	ExternalSurface() {}
+	SelfAwareness(const RuntimeEnvironment *renv);
+	~SelfAwareness();
 
 	/**
-	 * Revise our external surface image, return true if it changed
+	 * Called when a trusted remote peer informs us of our external network address
 	 *
-	 * @param remote Remote address as reflected by any trusted peer
-	 * @return True if our external surface has changed
+	 * @param physicalAddress Physical address as reflected by any trusted peer
 	 */
-	inline bool update(const InetAddress &remote)
-		throw()
-	{
-		const unsigned long idx = (remote.isV4() ? 0 : 2) | (remote.isLinkLocal() ? 1 : 0);
-		if (_s[idx] != remote) {
-			_s[idx] = remote;
-			return true;
-		}
-		return false;
-	}
+	void iam(const InetAddress &physicalAddress);
 
 private:
-	InetAddress _s[4]; // global v4, link-local v4, global v6, link-local v6
 };
 
 } // namespace ZeroTier

+ 0 - 17
node/Topology.hpp

@@ -45,7 +45,6 @@
 #include "InetAddress.hpp"
 #include "Utils.hpp"
 #include "Dictionary.hpp"
-#include "ExternalSurface.hpp"
 
 namespace ZeroTier {
 
@@ -321,20 +320,6 @@ public:
 	};
 #endif
 
-	/**
-	 * Update our knowledge of exterior network addresses
-	 *
-	 * If the remote peer in question is trusted, this will update our internal
-	 * instance of ExternalSurface. If our surface has changed, this triggers a
-	 * partial or total reset of ephemeral peer addresses and a renegotiation of
-	 * new ones using supernodes / relays.
-	 *
-	 * @param remotePeer Remote peer address
-	 * @param mirroredAddress Real-world network address the remote peer told us we have
-	 * @param now Current time
-	 */
-	bool updateSurface(const SharedPtr<Peer> &remotePeer,const InetAddress &mirroredAddress,uint64_t now);
-
 	/**
 	 * Validate a root topology dictionary against the identities specified in Defaults
 	 *
@@ -356,8 +341,6 @@ private:
 	std::vector< Address > _supernodeAddresses;
 	std::vector< SharedPtr<Peer> > _supernodePeers;
 
-	ExternalSurface _surface;
-
 	Mutex _lock;
 
 	// Set to true if my identity is in _supernodes