浏览代码

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

Adam Ierymenko 10 年之前
父节点
当前提交
a2821e9000
共有 6 个文件被更改,包括 83 次插入40 次删除
  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 "Switch.hpp"
 #include "Peer.hpp"
 #include "Peer.hpp"
 #include "NetworkConfigMaster.hpp"
 #include "NetworkConfigMaster.hpp"
+#include "SelfAwareness.hpp"
 
 
 namespace ZeroTier {
 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 vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION];
 		const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO_IDX_REVISION);
 		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 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()) {
 		if (source() != id.address()) {
 			TRACE("dropped HELLO from %s(%s): identity not for sending address",source().toString().c_str(),_remoteAddress.toString().c_str());
 			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->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP);
 		peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision);
 		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);
 		Packet outp(id.address(),RR->identity.address(),Packet::VERB_OK);
+
 		outp.append((unsigned char)Packet::VERB_HELLO);
 		outp.append((unsigned char)Packet::VERB_HELLO);
 		outp.append(packetId());
 		outp.append(packetId());
 		outp.append(timestamp);
 		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_MAJOR);
 		outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
 		outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
 		outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
 		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);
 		outp.armor(peer->key(),true);
 		RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation);
 		RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation);
 	} catch (std::exception &ex) {
 	} catch (std::exception &ex) {

+ 4 - 0
node/Node.cpp

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

+ 25 - 0
node/Packet.hpp

@@ -175,6 +175,12 @@
  */
  */
 #define ZT_PROTO_BEACON_IDX_ADDRESS 8
 #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 -------------------------------------------
 // Field incides for parsing verbs -------------------------------------------
 
 
 // Some verbs have variable-length fields. Those aren't fully defined here
 // Some verbs have variable-length fields. Those aren't fully defined here
@@ -467,6 +473,23 @@ public:
 		 *   <[2] software revision>
 		 *   <[2] software revision>
 		 *   <[8] timestamp (ms since epoch)>
 		 *   <[8] timestamp (ms since epoch)>
 		 *   <[...] binary serialized identity (see Identity)>
 		 *   <[...] 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:
 		 * OK payload:
 		 *   <[8] timestamp (echoed from original HELLO)>
 		 *   <[8] timestamp (echoed from original HELLO)>
@@ -474,6 +497,8 @@ public:
 		 *   <[1] software major version (of responder)>
 		 *   <[1] software major version (of responder)>
 		 *   <[1] software minor version (of responder)>
 		 *   <[1] software minor version (of responder)>
 		 *   <[2] software revision (of responder)>
 		 *   <[2] software revision (of responder)>
+		 *   <[1] destination address type (for this OK, not copied from HELLO)>
+		 *   [<[...] destination address>]
 		 *
 		 *
 		 * ERROR has no payload.
 		 * ERROR has no payload.
 		 */
 		 */

+ 4 - 1
node/RuntimeEnvironment.hpp

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

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

@@ -25,40 +25,32 @@
  * LLC. Start here: http://www.zerotier.com/
  * 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"
 #include "InetAddress.hpp"
 
 
 namespace ZeroTier {
 namespace ZeroTier {
 
 
+class RuntimeEnvironment;
+
 /**
 /**
  * Tracks changes to this peer's real world addresses
  * Tracks changes to this peer's real world addresses
  */
  */
-class ExternalSurface
+class SelfAwareness
 {
 {
 public:
 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:
 private:
-	InetAddress _s[4]; // global v4, link-local v4, global v6, link-local v6
 };
 };
 
 
 } // namespace ZeroTier
 } // namespace ZeroTier

+ 0 - 17
node/Topology.hpp

@@ -45,7 +45,6 @@
 #include "InetAddress.hpp"
 #include "InetAddress.hpp"
 #include "Utils.hpp"
 #include "Utils.hpp"
 #include "Dictionary.hpp"
 #include "Dictionary.hpp"
-#include "ExternalSurface.hpp"
 
 
 namespace ZeroTier {
 namespace ZeroTier {
 
 
@@ -321,20 +320,6 @@ public:
 	};
 	};
 #endif
 #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
 	 * Validate a root topology dictionary against the identities specified in Defaults
 	 *
 	 *
@@ -356,8 +341,6 @@ private:
 	std::vector< Address > _supernodeAddresses;
 	std::vector< Address > _supernodeAddresses;
 	std::vector< SharedPtr<Peer> > _supernodePeers;
 	std::vector< SharedPtr<Peer> > _supernodePeers;
 
 
-	ExternalSurface _surface;
-
 	Mutex _lock;
 	Mutex _lock;
 
 
 	// Set to true if my identity is in _supernodes
 	// Set to true if my identity is in _supernodes