mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-19 19:28:58 +00:00
Try another NAT traversal improvement.
This commit is contained in:
parent
dda376c9eb
commit
b31071463c
@ -296,6 +296,9 @@
|
||||
|
||||
/**
|
||||
* Delay between initial direct NAT-t packet and more aggressive techniques
|
||||
*
|
||||
* This may also be a delay before sending the first packet if we determine
|
||||
* that we should wait for the remote to initiate rendezvous first.
|
||||
*/
|
||||
#define ZT_NAT_T_TACTICAL_ESCALATION_DELAY 1000
|
||||
|
||||
|
@ -488,7 +488,7 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<
|
||||
InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
|
||||
TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
|
||||
peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP);
|
||||
RR->sw->contact(withPeer,atAddr);
|
||||
RR->sw->rendezvous(withPeer,atAddr);
|
||||
} else {
|
||||
TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
|
||||
}
|
||||
|
@ -147,4 +147,19 @@ void SelfAwareness::clean(uint64_t now)
|
||||
}
|
||||
}
|
||||
|
||||
bool SelfAwareness::areGlobalIPv4PortsRandomized() const
|
||||
{
|
||||
int port = 0;
|
||||
Mutex::Lock _l(_phy_m);
|
||||
for(std::map< PhySurfaceKey,PhySurfaceEntry >::const_iterator p(_phy.begin());p!=_phy.end();++p) {
|
||||
if ((p->first.scope == InetAddress::IP_SCOPE_GLOBAL)&&(p->second.mySurface.ss_family == AF_INET)) {
|
||||
const int tmp = (int)p->second.mySurface.port();
|
||||
if ((port)&&(tmp != port))
|
||||
return true;
|
||||
else port = tmp;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
@ -66,6 +66,11 @@ public:
|
||||
*/
|
||||
void clean(uint64_t now);
|
||||
|
||||
/**
|
||||
* @return True if our external (global scope) IPv4 ports appear to be randomized by a NAT device
|
||||
*/
|
||||
bool areGlobalIPv4PortsRandomized() const;
|
||||
|
||||
private:
|
||||
struct PhySurfaceKey
|
||||
{
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "Topology.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "AntiRecursion.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Packet.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
@ -385,15 +386,23 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Switch::contact(const SharedPtr<Peer> &peer,const InetAddress &atAddr)
|
||||
void Switch::rendezvous(const SharedPtr<Peer> &peer,const InetAddress &atAddr)
|
||||
{
|
||||
TRACE("sending NAT-t message to %s(%s)",peer->address().toString().c_str(),atAddr.toString().c_str());
|
||||
const uint64_t now = RR->node->now();
|
||||
|
||||
// Attempt to contact directly
|
||||
peer->attemptToContactAt(RR,atAddr,now);
|
||||
/* Attempt direct contact now unless we are IPv4 and our external ports
|
||||
* appear to be randomized by a NAT device. In that case, we should let
|
||||
* the other side send a message first. Why? If the other side is also
|
||||
* randomized and symmetric, we are probably going to fail. But if the
|
||||
* other side is "port restricted" but otherwise sane, us sending a
|
||||
* packet first may actually close the remote's outgoing port to us!
|
||||
* This assists with NAT-t in cases where one side is symmetric and the
|
||||
* other is full cone but port restricted. */
|
||||
if ((atAddr.ss_family != AF_INET)||(!RR->sa->areGlobalIPv4PortsRandomized()))
|
||||
peer->attemptToContactAt(RR,atAddr,now);
|
||||
|
||||
// If we have not punched through after this timeout, open refreshing can of whupass
|
||||
// After 1s, try again and perhaps try more NAT-t strategies
|
||||
{
|
||||
Mutex::Lock _l(_contactQueue_m);
|
||||
_contactQueue.push_back(ContactQueueEntry(peer,now + ZT_NAT_T_TACTICAL_ESCALATION_DELAY,atAddr));
|
||||
|
@ -136,12 +136,12 @@ public:
|
||||
bool unite(const Address &p1,const Address &p2,bool force);
|
||||
|
||||
/**
|
||||
* Send NAT traversal messages to peer at the given candidate address
|
||||
* Attempt NAT traversal to peer at a given physical address
|
||||
*
|
||||
* @param peer Peer to contact
|
||||
* @param atAddr Address of peer
|
||||
*/
|
||||
void contact(const SharedPtr<Peer> &peer,const InetAddress &atAddr);
|
||||
void rendezvous(const SharedPtr<Peer> &peer,const InetAddress &atAddr);
|
||||
|
||||
/**
|
||||
* Request WHOIS on a given address
|
||||
|
Loading…
Reference in New Issue
Block a user