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 "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) {

View File

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

View File

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

View File

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

View File

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

View File

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