diff options
| author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2016-02-10 18:41:39 -0800 |
|---|---|---|
| committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2016-02-10 18:41:39 -0800 |
| commit | 0c951b6e56db47f2be4850343ae3908d0ea83099 (patch) | |
| tree | 08bc539fcbb90a4e5b3c0419495ea63c08a2d9fc /node/SelfAwareness.cpp | |
| parent | eadafd8de754336f8c06302305a26669762a365d (diff) | |
| download | infinitytier-0c951b6e56db47f2be4850343ae3908d0ea83099.tar.gz infinitytier-0c951b6e56db47f2be4850343ae3908d0ea83099.zip | |
More tweaks to new symmetric NAT buster, and stop using old iterative method since this supersedes it.
Diffstat (limited to 'node/SelfAwareness.cpp')
| -rw-r--r-- | node/SelfAwareness.cpp | 63 |
1 files changed, 44 insertions, 19 deletions
diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index db069046..cf43a644 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -20,6 +20,9 @@ #include <stdlib.h> #include <string.h> +#include <set> +#include <vector> + #include "Constants.hpp" #include "SelfAwareness.hpp" #include "RuntimeEnvironment.hpp" @@ -68,30 +71,14 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi { const InetAddress::IpScope scope = myPhysicalAddress.ipScope(); - // This would be weird, e.g. a public IP talking to 10.0.0.1, so just ignore it. - // If your network is this weird it's probably not reliable information. - if (scope != reporterPhysicalAddress.ipScope()) + if ((scope != reporterPhysicalAddress.ipScope())||(scope == InetAddress::IP_SCOPE_NONE)||(scope == InetAddress::IP_SCOPE_LOOPBACK)||(scope == InetAddress::IP_SCOPE_MULTICAST)) return; - // Some scopes we ignore, and global scope IPs are only used for this - // mechanism if they come from someone we trust (e.g. a root). - switch(scope) { - case InetAddress::IP_SCOPE_NONE: - case InetAddress::IP_SCOPE_LOOPBACK: - case InetAddress::IP_SCOPE_MULTICAST: - return; - case InetAddress::IP_SCOPE_GLOBAL: - if (!trusted) - return; - break; - default: - break; - } - Mutex::Lock _l(_phy_m); PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter,reporterPhysicalAddress,scope)]; - if ( ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress)) ) { + if ( (trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress)) ) { + // Changes to external surface reported by trusted peers causes path reset in this scope entry.mySurface = myPhysicalAddress; entry.ts = now; TRACE("physical address %s for scope %u as seen from %s(%s) differs from %s, resetting paths in scope",myPhysicalAddress.toString().c_str(),(unsigned int)scope,reporter.toString().c_str(),reporterPhysicalAddress.toString().c_str(),entry.mySurface.toString().c_str()); @@ -123,6 +110,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi } } } else { + // Otherwise just update DB to use to determine external surface info entry.mySurface = myPhysicalAddress; entry.ts = now; } @@ -140,4 +128,41 @@ void SelfAwareness::clean(uint64_t now) } } +std::vector<InetAddress> SelfAwareness::getSymmetricNatPredictions() +{ + std::set<InetAddress> surfaces; + + // Ideas based on: https://tools.ietf.org/html/draft-takeda-symmetric-nat-traversal-00 + + { + Mutex::Lock _l(_phy_m); + Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy); + PhySurfaceKey *k = (PhySurfaceKey *)0; + PhySurfaceEntry *e = (PhySurfaceEntry *)0; + while (i.next(k,e)) { + if ((e->mySurface.ss_family == AF_INET)&&(e->mySurface.ipScope() == InetAddress::IP_SCOPE_GLOBAL)) { + surfaces.insert(e->mySurface); + } + } + } + + if (surfaces.size() > 1) { + // More than one global IPv4 surface means this is a symmetric NAT + std::vector<InetAddress> r; + for(std::set<InetAddress>::iterator i(surfaces.begin());i!=surfaces.end();++i) { + InetAddress nextPort(*i); + unsigned int p = nextPort.port(); + if (p >= 65535) + p = 1025; + else ++p; + nextPort.setPort(p); + if (surfaces.count(nextPort) == 0) + r.push_back(nextPort); + } + return r; + } + + return std::vector<InetAddress>(); +} + } // namespace ZeroTier |
