Rip out dead "firewall opener" code, replace in pipeline with anti-symmetric-NAT tactics.

This commit is contained in:
Adam Ierymenko 2014-09-05 16:23:24 -07:00
parent d02ecfb288
commit 4e9280fc7a
9 changed files with 27 additions and 134 deletions

View File

@ -274,27 +274,6 @@
*/
#define ZT_PEER_DIRECT_PING_DELAY 120000
/**
* Delay in ms between firewall opener packets to direct links
*
* This should be lower than the UDP conversation entry timeout in most
* stateful firewalls.
*
* Uncomment to disable firewall openers.
*/
//#define ZT_FIREWALL_OPENER_DELAY 30000
/**
* Number of hops to open via firewall opener packets
*
* The firewall opener code iterates from 1 to this value (inclusive), sending
* a tiny packet with each TTL value.
*
* 2 should permit traversal of double-NAT configurations, such as from inside
* a VM running behind local NAT on a host that is itself behind NAT.
*/
//#define ZT_FIREWALL_OPENER_HOPS 2
/**
* Delay between requests for updated network autoconf information
*/
@ -371,12 +350,9 @@
#define ZT_MIN_UNITE_INTERVAL 30000
/**
* Delay in milliseconds between firewall opener and real packet for NAT-t
*
* If firewall openers are disbled, it just waits this long before sending
* NAT-t packets.
* Delay between initial direct NAT-t packet and more aggressive techniques
*/
#define ZT_RENDEZVOUS_NAT_T_DELAY 500
#define ZT_NAT_T_TACTICAL_ESCALATION_DELAY 2000
/**
* Size of anti-recursion history (see AntiRecursion.hpp)

View File

@ -728,9 +728,6 @@ Node::ReasonForTermination Node::run()
lastPingCheck = now;
try {
_r->topology->eachPeer(Topology::PingPeersThatNeedPing(_r,now));
#ifdef ZT_FIREWALL_OPENER_DELAY
_r->topology->eachPeer(Topology::OpenPeersThatNeedFirewallOpener(_r,now));
#endif
} catch (std::exception &exc) {
LOG("unexpected exception running ping check cycle: %s",exc.what());
} catch ( ... ) {

View File

@ -39,7 +39,7 @@
#include "Utils.hpp"
#include "Buffer.hpp"
#define ZT_PATH_SERIALIZATION_VERSION 2
#define ZT_PATH_SERIALIZATION_VERSION 3
namespace ZeroTier {
@ -60,7 +60,6 @@ public:
Path() :
_lastSend(0),
_lastReceived(0),
_lastFirewallOpener(0),
_lastPing(0),
_addr(),
_type(PATH_TYPE_NULL),
@ -75,7 +74,6 @@ public:
Path(const InetAddress &addr,Type t,bool fixed = false) :
_lastSend(0),
_lastReceived(0),
_lastFirewallOpener(0),
_lastPing(0),
_addr(addr),
_type(t),
@ -95,7 +93,6 @@ public:
inline uint64_t lastSend() const throw() { return _lastSend; }
inline uint64_t lastReceived() const throw() { return _lastReceived; }
inline uint64_t lastFirewallOpener() const throw() { return _lastFirewallOpener; }
inline uint64_t lastPing() const throw() { return _lastPing; }
inline bool fixed() const throw() { return _fixed; }
@ -103,7 +100,6 @@ public:
inline void sent(uint64_t t) throw() { _lastSend = t; }
inline void received(uint64_t t) throw() { _lastReceived = t; }
inline void firewallOpenerSent(uint64_t t) throw() { _lastFirewallOpener = t; }
inline void pinged(uint64_t t) throw() { _lastPing = t; }
/**
@ -130,12 +126,11 @@ public:
case PATH_TYPE_TCP_OUT: t = "tcp_out"; break;
case PATH_TYPE_TCP_IN: t = "tcp_in"; break;
}
Utils::snprintf(tmp,sizeof(tmp),"%s;%s;%lld;%lld;%lld;%lld;%s",
Utils::snprintf(tmp,sizeof(tmp),"%s;%s;%lld;%lld;%lld;%s",
t,
_addr.toString().c_str(),
(long long)((_lastSend != 0) ? ((now - _lastSend) / 1000LL) : -1),
(long long)((_lastReceived != 0) ? ((now - _lastReceived) / 1000LL) : -1),
(long long)((_lastFirewallOpener != 0) ? ((now - _lastFirewallOpener) / 1000LL) : -1),
(long long)((_lastPing != 0) ? ((now - _lastPing) / 1000LL) : -1),
((_fixed) ? "fixed" : (active(now) ? "active" : "inactive"))
);
@ -161,7 +156,6 @@ public:
b.append((unsigned char)ZT_PATH_SERIALIZATION_VERSION);
b.append(_lastSend);
b.append(_lastReceived);
b.append(_lastFirewallOpener);
b.append(_lastPing);
b.append((unsigned char)_addr.type());
switch(_addr.type()) {
@ -189,7 +183,6 @@ public:
_lastSend = b.template at<uint64_t>(p); p += sizeof(uint64_t);
_lastReceived = b.template at<uint64_t>(p); p += sizeof(uint64_t);
_lastFirewallOpener = b.template at<uint64_t>(p); p += sizeof(uint64_t);
_lastPing = b.template at<uint64_t>(p); p += sizeof(uint64_t);
switch((InetAddress::AddressType)b[p++]) {
case InetAddress::TYPE_IPV4:
@ -213,7 +206,6 @@ public:
private:
volatile uint64_t _lastSend;
volatile uint64_t _lastReceived;
volatile uint64_t _lastFirewallOpener;
volatile uint64_t _lastPing;
InetAddress _addr;
Type _type;

View File

@ -181,23 +181,6 @@ Path::Type Peer::send(const RuntimeEnvironment *_r,const void *data,unsigned int
return Path::PATH_TYPE_NULL;
}
#ifdef ZT_FIREWALL_OPENER_DELAY
bool Peer::sendFirewallOpener(const RuntimeEnvironment *_r,uint64_t now)
{
bool sent = false;
Mutex::Lock _l(_lock);
for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
if (p->type() == Path::PATH_TYPE_UDP) {
for(unsigned int h=1;h<=ZT_FIREWALL_OPENER_HOPS;++h)
sent |= _r->sm->sendFirewallOpener(p->address(),h);
}
}
return sent;
}
#endif
bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now)
{
bool sent = false;

View File

@ -50,7 +50,7 @@
#include "NonCopyable.hpp"
#include "Mutex.hpp"
#define ZT_PEER_SERIALIZATION_VERSION 10
#define ZT_PEER_SERIALIZATION_VERSION 11
namespace ZeroTier {
@ -142,17 +142,6 @@ public:
*/
Path::Type send(const RuntimeEnvironment *_r,const void *data,unsigned int len,uint64_t now);
#ifdef ZT_FIREWALL_OPENER_DELAY
/**
* Send firewall opener to all UDP paths
*
* @param _r Runtime environment
* @param now Current time
* @return True if send appears successful for at least one address type
*/
bool sendFirewallOpener(const RuntimeEnvironment *_r,uint64_t now);
#endif
/**
* Send HELLO to a peer via all direct paths available
*
@ -193,19 +182,6 @@ public:
return false;
}
/**
* @return Last successfully sent firewall opener for any path
*/
inline uint64_t lastFirewallOpener() const
throw()
{
uint64_t x = 0;
Mutex::Lock _l(_lock);
for(std::vector<Path>::const_iterator p(_paths.begin());p!=_paths.end();++p)
x = std::max(x,p->lastFirewallOpener());
return x;
}
/**
* @return Time of last direct packet receive for any path
*/

View File

@ -452,20 +452,6 @@ bool SocketManager::send(const InetAddress &to,bool tcp,bool autoConnectTcp,cons
return false;
}
#ifdef ZT_FIREWALL_OPENER_DELAY
bool SocketManager::sendFirewallOpener(const InetAddress &to,int hopLimit)
{
if (to.isV4()) {
if (_udpV4Socket)
return ((UdpSocket *)_udpV4Socket.ptr())->sendWithHopLimit(to,"",1,hopLimit);
} else if (to.isV6()) {
if (_udpV6Socket)
return ((UdpSocket *)_udpV6Socket.ptr())->sendWithHopLimit(to,"",1,hopLimit);
}
return false;
}
#endif
void SocketManager::poll(unsigned long timeout)
{
fd_set rfds,wfds,efds;

View File

@ -103,16 +103,6 @@ public:
*/
inline bool sendUdp(const InetAddress &to,const void *msg,unsigned int msglen) { return send(to,false,false,msg,msglen); }
/**
* Send a UDP packet with a limited IP TTL
*
* @param to Destination address
* @param hopLimit IP TTL
*/
#ifdef ZT_FIREWALL_OPENER_DELAY
bool sendFirewallOpener(const InetAddress &to,int hopLimit);
#endif
/**
* Perform I/O polling operation (e.g. select())
*

View File

@ -461,13 +461,14 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)
void Switch::contact(const SharedPtr<Peer> &peer,const InetAddress &atAddr)
{
#ifdef ZT_FIREWALL_OPENER_HOPS
_r->sm->sendFirewallOpener(atAddr,ZT_FIREWALL_OPENER_HOPS);
#endif
// Send simple packet directly to indicated address -- works for most NATs
sendHELLO(peer,atAddr);
TRACE("sending NAT-t HELLO to %s(%s)",peer->address().toString().c_str(),atAddr.toString().c_str());
// If we have not punched through after this timeout, open refreshing can of whupass
{
Mutex::Lock _l(_contactQueue_m);
_contactQueue.push_back(ContactQueueEntry(peer,Utils::now() + ZT_RENDEZVOUS_NAT_T_DELAY,atAddr));
_contactQueue.push_back(ContactQueueEntry(peer,Utils::now() + ZT_NAT_T_TACTICAL_ESCALATION_DELAY,atAddr));
}
// Kick main loop out of wait so that it can pick up this
@ -484,8 +485,23 @@ unsigned long Switch::doTimerTasks()
Mutex::Lock _l(_contactQueue_m);
for(std::list<ContactQueueEntry>::iterator qi(_contactQueue.begin());qi!=_contactQueue.end();) {
if (now >= qi->fireAtTime) {
TRACE("sending NAT-T HELLO to %s(%s)",qi->peer->address().toString().c_str(),qi->inaddr.toString().c_str());
sendHELLO(qi->peer,qi->inaddr);
if (!qi->peer->hasActiveDirectPath(now)) {
TRACE("deploying aggressive NAT-t against %s(%s)",qi->peer->address().toString().c_str(),qi->inaddr.toString().c_str());
/* Shotgun approach -- literally -- against symmetric NATs. Most of these
* either increment or decrement ports so this gets a good number. Also try
* the original port one more time for good measure, since sometimes it
* fails first time around. */
int p = (int)qi->inaddr.port() - 2;
for(int k=0;k<5;++k) {
if ((p > 0)&&(p <= 0xffff)) {
qi->inaddr.setPort((unsigned int)p);
sendHELLO(qi->peer,qi->inaddr);
}
++p;
}
}
_contactQueue.erase(qi++);
} else {
nextDelay = std::min(nextDelay,(unsigned long)(qi->fireAtTime - now));

View File

@ -207,29 +207,6 @@ public:
f(*this,*p);
}
#ifdef ZT_FIREWALL_OPENER_DELAY
/**
* Function object to collect peers that need a firewall opener sent
*/
class OpenPeersThatNeedFirewallOpener
{
public:
OpenPeersThatNeedFirewallOpener(const RuntimeEnvironment *renv,uint64_t now) throw() :
_now(now),
_r(renv) {}
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
{
if ((p->hasDirectPath())&&((_now - std::max(p->lastFirewallOpener(),p->lastDirectSend())) >= ZT_FIREWALL_OPENER_DELAY))
p->sendFirewallOpener(_r,_now);
}
private:
uint64_t _now;
const RuntimeEnvironment *_r;
};
#endif
/**
* Pings all peers that need a ping sent, excluding supernodes
*