mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-18 20:47:53 +00:00
Add forced TCP relay mode
This patch implements a "TUNNELED" status indicator and "forceTcpRelay" setting for custom relays via local.conf. For example: { "settings": { "tcpFallbackRelay": "6.79.53.215/443", "forceTcpRelay":true } }
This commit is contained in:
parent
d31f238be0
commit
eccc31a4b9
16
one.cpp
16
one.cpp
@ -449,12 +449,16 @@ static int cli(int argc,char **argv)
|
||||
if (json) {
|
||||
printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str());
|
||||
} else {
|
||||
bool anyTunneled = false;
|
||||
printf("200 peers\n<ztaddr> <ver> <role> <lat> <link> <lastTX> <lastRX> <path>" ZT_EOL_S);
|
||||
if (j.is_array()) {
|
||||
for(unsigned long k=0;k<j.size();++k) {
|
||||
nlohmann::json &p = j[k];
|
||||
std::string bestPath;
|
||||
nlohmann::json &paths = p["paths"];
|
||||
if (p["tunneled"]) {
|
||||
anyTunneled = true;
|
||||
}
|
||||
if (paths.is_array()) {
|
||||
for(unsigned long i=0;i<paths.size();++i) {
|
||||
nlohmann::json &path = paths[i];
|
||||
@ -465,12 +469,19 @@ static int cli(int argc,char **argv)
|
||||
int64_t lastSendDiff = (uint64_t)path["lastSend"] ? now - (uint64_t)path["lastSend"] : -1;
|
||||
int64_t lastReceiveDiff = (uint64_t)path["lastReceive"] ? now - (uint64_t)path["lastReceive"] : -1;
|
||||
OSUtils::ztsnprintf(tmp,sizeof(tmp),"%-8lld %-8lld %s",lastSendDiff,lastReceiveDiff,addr.c_str());
|
||||
if (p["tunneled"]) {
|
||||
bestPath = std::string("RELAY ") + tmp;
|
||||
}
|
||||
else {
|
||||
bestPath = std::string("DIRECT ") + tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestPath.length() == 0) bestPath = "RELAY";
|
||||
if (bestPath.length() == 0) {
|
||||
bestPath = "RELAY";
|
||||
}
|
||||
char ver[128];
|
||||
int64_t vmaj = p["versionMajor"];
|
||||
int64_t vmin = p["versionMinor"];
|
||||
@ -489,6 +500,9 @@ static int cli(int argc,char **argv)
|
||||
bestPath.c_str());
|
||||
}
|
||||
}
|
||||
if (anyTunneled) {
|
||||
printf("NOTE: Currently tunneling through a TCP relay. Ensure that UDP is not blocked.\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -521,7 +521,7 @@ static void _networkToJson(nlohmann::json &nj,NetworkState &ns)
|
||||
}
|
||||
}
|
||||
|
||||
static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer, SharedPtr<Bond> &bond)
|
||||
static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer, SharedPtr<Bond> &bond, bool isTunneled)
|
||||
{
|
||||
char tmp[256];
|
||||
|
||||
@ -542,6 +542,7 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer, SharedPtr<Bond>
|
||||
pj["latency"] = peer->latency;
|
||||
pj["role"] = prole;
|
||||
pj["isBonded"] = peer->isBonded;
|
||||
pj["tunneled"] = isTunneled;
|
||||
if (bond && peer->isBonded) {
|
||||
pj["bondingPolicyCode"] = peer->bondingPolicy;
|
||||
pj["bondingPolicyStr"] = Bond::getPolicyStrByCode(peer->bondingPolicy);
|
||||
@ -714,6 +715,7 @@ public:
|
||||
PhySocket *_localControlSocket6;
|
||||
bool _updateAutoApply;
|
||||
bool _allowTcpFallbackRelay;
|
||||
bool _forceTcpRelay;
|
||||
bool _allowSecondaryPort;
|
||||
|
||||
unsigned int _primaryPort;
|
||||
@ -812,6 +814,7 @@ public:
|
||||
,_localControlSocket4((PhySocket *)0)
|
||||
,_localControlSocket6((PhySocket *)0)
|
||||
,_updateAutoApply(false)
|
||||
,_forceTcpRelay(false)
|
||||
,_primaryPort(port)
|
||||
,_udpPortPickerCounter(0)
|
||||
,_lastDirectReceiveFromGlobal(0)
|
||||
@ -1093,7 +1096,10 @@ public:
|
||||
if (_ports[i])
|
||||
p[pc++] = _ports[i];
|
||||
}
|
||||
if (!_forceTcpRelay) {
|
||||
// Only bother binding UDP ports if we aren't forcing TCP-relay mode
|
||||
_binder.refresh(_phy,p,pc,explicitBind,*this);
|
||||
}
|
||||
{
|
||||
Mutex::Lock _l(_nets_m);
|
||||
for(std::map<uint64_t,NetworkState>::iterator n(_nets.begin());n!=_nets.end();++n) {
|
||||
@ -1111,8 +1117,9 @@ public:
|
||||
}
|
||||
|
||||
// Close TCP fallback tunnel if we have direct UDP
|
||||
if ((_tcpFallbackTunnel)&&((now - _lastDirectReceiveFromGlobal) < (ZT_TCP_FALLBACK_AFTER / 2)))
|
||||
if (!_forceTcpRelay && (_tcpFallbackTunnel) && ((now - _lastDirectReceiveFromGlobal) < (ZT_TCP_FALLBACK_AFTER / 2))) {
|
||||
_phy.close(_tcpFallbackTunnel->sock);
|
||||
}
|
||||
|
||||
// Sync multicast group memberships
|
||||
if ((now - lastTapMulticastGroupCheck) >= ZT_TAP_CHECK_MULTICAST_INTERVAL) {
|
||||
@ -1488,7 +1495,7 @@ public:
|
||||
if (ps[1] == "show") {
|
||||
SharedPtr<Bond> bond = _node->bondController()->getBondByPeerId(wantp);
|
||||
if (bond) {
|
||||
_peerToJson(res,&(pl->peers[i]),bond);
|
||||
_peerToJson(res,&(pl->peers[i]),bond,(_tcpFallbackTunnel != (TcpConnection *)0));
|
||||
scode = 200;
|
||||
} else {
|
||||
scode = 400;
|
||||
@ -1530,6 +1537,7 @@ public:
|
||||
}
|
||||
json &settings = res["config"]["settings"];
|
||||
settings["allowTcpFallbackRelay"] = OSUtils::jsonBool(settings["allowTcpFallbackRelay"],_allowTcpFallbackRelay);
|
||||
settings["forceTcpRelay"] = OSUtils::jsonBool(settings["forceTcpRelay"],_forceTcpRelay);
|
||||
settings["primaryPort"] = OSUtils::jsonInt(settings["primaryPort"],(uint64_t)_primaryPort) & 0xffff;
|
||||
settings["secondaryPort"] = OSUtils::jsonInt(settings["secondaryPort"],(uint64_t)_secondaryPort) & 0xffff;
|
||||
settings["tertiaryPort"] = OSUtils::jsonInt(settings["tertiaryPort"],(uint64_t)_tertiaryPort) & 0xffff;
|
||||
@ -1634,7 +1642,7 @@ public:
|
||||
const uint64_t id = pl->peers[i].address;
|
||||
bond = _node->bondController()->getBondByPeerId(id);
|
||||
}
|
||||
_peerToJson(pj,&(pl->peers[i]),bond);
|
||||
_peerToJson(pj,&(pl->peers[i]),bond,(_tcpFallbackTunnel != (TcpConnection *)0));
|
||||
res.push_back(pj);
|
||||
}
|
||||
|
||||
@ -1649,7 +1657,7 @@ public:
|
||||
if (pl->peers[i].isBonded) {
|
||||
bond = _node->bondController()->getBondByPeerId(wantp);
|
||||
}
|
||||
_peerToJson(res,&(pl->peers[i]),bond);
|
||||
_peerToJson(res,&(pl->peers[i]),bond,(_tcpFallbackTunnel != (TcpConnection *)0));
|
||||
scode = 200;
|
||||
break;
|
||||
}
|
||||
@ -2118,6 +2126,8 @@ public:
|
||||
|
||||
// bondingPolicy cannot be used with allowTcpFallbackRelay
|
||||
_allowTcpFallbackRelay = OSUtils::jsonBool(settings["allowTcpFallbackRelay"],true);
|
||||
_forceTcpRelay = OSUtils::jsonBool(settings["forceTcpRelay"],false);
|
||||
|
||||
#ifdef ZT_TCP_FALLBACK_RELAY
|
||||
_fallbackRelayAddress = InetAddress(OSUtils::jsonString(settings["tcpFallbackRelay"], ZT_TCP_FALLBACK_RELAY).c_str());
|
||||
#endif
|
||||
@ -2404,6 +2414,9 @@ public:
|
||||
|
||||
inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len)
|
||||
{
|
||||
if (_forceTcpRelay) {
|
||||
return;
|
||||
}
|
||||
const uint64_t now = OSUtils::now();
|
||||
if ((len >= 16)&&(reinterpret_cast<const InetAddress *>(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL))
|
||||
_lastDirectReceiveFromGlobal = now;
|
||||
@ -3112,7 +3125,7 @@ public:
|
||||
// IP address in ZT_TCP_FALLBACK_AFTER milliseconds. If we do start getting
|
||||
// valid direct traffic we'll stop using it and close the socket after a while.
|
||||
const int64_t now = OSUtils::now();
|
||||
if (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER)&&((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER)) {
|
||||
if (_forceTcpRelay || (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER)&&((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER))) {
|
||||
if (_tcpFallbackTunnel) {
|
||||
bool flushNow = false;
|
||||
{
|
||||
@ -3138,7 +3151,7 @@ public:
|
||||
void *tmpptr = (void *)_tcpFallbackTunnel;
|
||||
phyOnTcpWritable(_tcpFallbackTunnel->sock,&tmpptr);
|
||||
}
|
||||
} else if (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)&&((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INVERVAL / 2))) {
|
||||
} else if (_forceTcpRelay || (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)&&((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INVERVAL / 2)))) {
|
||||
const InetAddress addr(_fallbackRelayAddress);
|
||||
TcpConnection *tc = new TcpConnection();
|
||||
{
|
||||
@ -3159,12 +3172,15 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_forceTcpRelay) {
|
||||
// Shortcut here so that we don't emit any UDP packets
|
||||
return 0;
|
||||
}
|
||||
#endif // ZT_TCP_FALLBACK_RELAY
|
||||
|
||||
// Even when relaying we still send via UDP. This way if UDP starts
|
||||
// working we can instantly "fail forward" to it and stop using TCP
|
||||
// proxy fallback, which is slow.
|
||||
|
||||
if ((localSocket != -1)&&(localSocket != 0)&&(_binder.isUdpSocketValid((PhySocket *)((uintptr_t)localSocket)))) {
|
||||
if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),ttl);
|
||||
const bool r = _phy.udpSend((PhySocket *)((uintptr_t)localSocket),(const struct sockaddr *)addr,data,len);
|
||||
|
Loading…
Reference in New Issue
Block a user