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

This commit is contained in:
Adam Ierymenko 2015-04-06 20:17:21 -07:00
parent 76ad19f411
commit a2821e9000
6 changed files with 83 additions and 40 deletions

View file

@ -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())) {
//if (RR->topology->isSupernode(id.address())) RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision);
// 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) {

View file

@ -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;

View file

@ -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.
*/ */

View file

@ -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

View file

@ -25,40 +25,32 @@
* LLC. Start here: http://www.zerotier.com/ * LLC. Start here: http://www.zerotier.com/
*/ */
#ifndef ZT_EXTERNALSURFACE_HPP #ifndef ZT_SELFAWARENESS_HPP
#define ZT_EXTERNALSURFACE_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 * @param physicalAddress Physical address as reflected by any trusted peer
* @return True if our external surface has changed
*/ */
inline bool update(const InetAddress &remote) void iam(const InetAddress &physicalAddress);
throw()
{
const unsigned long idx = (remote.isV4() ? 0 : 2) | (remote.isLinkLocal() ? 1 : 0);
if (_s[idx] != remote) {
_s[idx] = remote;
return true;
}
return false;
}
private: private:
InetAddress _s[4]; // global v4, link-local v4, global v6, link-local v6
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -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