Randomize ports if node goes offline
This commit is contained in:
@@ -284,21 +284,10 @@ NodeService::ReasonForTermination NodeService::run()
|
|||||||
// in a node that appears to be in a coma. Secondary ports are now
|
// in a node that appears to be in a coma. Secondary ports are now
|
||||||
// randomized on startup.
|
// randomized on startup.
|
||||||
if (_allowSecondaryPort) {
|
if (_allowSecondaryPort) {
|
||||||
unsigned int randp = 0;
|
if (_secondaryPort) {
|
||||||
Utils::getSecureRandom(&randp, sizeof(randp));
|
_ports[1] = _secondaryPort;
|
||||||
_ports[1] = (_secondaryPort == 0) ? ((randp % (maxPort - minPort + 1)) + minPort) : _secondaryPort;
|
} else {
|
||||||
for (int i = 0;; ++i) {
|
_ports[1] = _getRandomPort(minPort, maxPort);
|
||||||
if (i > 1000) {
|
|
||||||
_ports[1] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (++_ports[1] >= maxPort) {
|
|
||||||
_ports[1] = minPort;
|
|
||||||
}
|
|
||||||
if (_trialBind(_ports[1])) {
|
|
||||||
_secondaryPort = _ports[1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef ZT_USE_MINIUPNPC
|
#ifdef ZT_USE_MINIUPNPC
|
||||||
@@ -310,8 +299,11 @@ NodeService::ReasonForTermination NodeService::run()
|
|||||||
maxPort = (_randomPortRangeEnd ? _randomPortRangeEnd : 65536);
|
maxPort = (_randomPortRangeEnd ? _randomPortRangeEnd : 65536);
|
||||||
|
|
||||||
if (_ports[1]) {
|
if (_ports[1]) {
|
||||||
_ports[2] = (_tertiaryPort == 0) ? _ports[1] : _tertiaryPort;
|
if (_tertiaryPort) {
|
||||||
for (int i = 0;; ++i) {
|
_ports[2] = _tertiaryPort;
|
||||||
|
} else {
|
||||||
|
_ports[2] = minPort + (_ports[0] % 40000);
|
||||||
|
for(int i=0;;++i) {
|
||||||
if (i > 1000) {
|
if (i > 1000) {
|
||||||
_ports[2] = 0;
|
_ports[2] = 0;
|
||||||
break;
|
break;
|
||||||
@@ -336,7 +328,9 @@ NodeService::ReasonForTermination NodeService::run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Join existing networks in networks.d
|
// Join existing networks in networks.d
|
||||||
if (_allowNetworkCaching) {
|
if (_allowNetworkCaching) {
|
||||||
std::vector<std::string> networksDotD(
|
std::vector<std::string> networksDotD(
|
||||||
@@ -357,7 +351,7 @@ NodeService::ReasonForTermination NodeService::run()
|
|||||||
int64_t lastCleanedPeersDb = 0;
|
int64_t lastCleanedPeersDb = 0;
|
||||||
int64_t lastLocalInterfaceAddressCheck =
|
int64_t lastLocalInterfaceAddressCheck =
|
||||||
(clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to
|
(clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to
|
||||||
// configure and other things time to settle
|
int64_t lastOnline = OSUtils::now();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_run_m.lock();
|
_run_m.lock();
|
||||||
if (! _run) {
|
if (! _run) {
|
||||||
@@ -381,6 +375,17 @@ NodeService::ReasonForTermination NodeService::run()
|
|||||||
restarted = true;
|
restarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If secondary port is not configured to a constant value and we've been offline for a while,
|
||||||
|
// bind a new secondary port. This is a workaround for a "coma" issue caused by buggy NATs that stop
|
||||||
|
// working on one port after a while.
|
||||||
|
if (_node->online()) {
|
||||||
|
lastOnline = now;
|
||||||
|
}
|
||||||
|
else if ((_secondaryPort == 0) && ((now - lastOnline) > ZT_PATH_HEARTBEAT_PERIOD)) {
|
||||||
|
_secondaryPort = _getRandomPort(minPort, maxPort);
|
||||||
|
lastBindRefresh = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Refresh bindings in case device's interfaces have changed,
|
// Refresh bindings in case device's interfaces have changed,
|
||||||
// and also sync routes to update any shadow routes (e.g. shadow
|
// and also sync routes to update any shadow routes (e.g. shadow
|
||||||
// default)
|
// default)
|
||||||
@@ -1675,6 +1680,25 @@ int NodeService::shouldBindInterface(const char* ifname, const InetAddress& ifad
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int NodeService::_getRandomPort(unsigned int minPort, unsigned int maxPort)
|
||||||
|
{
|
||||||
|
unsigned int randp = 0;
|
||||||
|
Utils::getSecureRandom(&randp,sizeof(randp));
|
||||||
|
randp = (randp % (maxPort - minPort + 1)) + minPort;
|
||||||
|
for(int i=0;;++i) {
|
||||||
|
if (i > 1000) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (++randp >= maxPort) {
|
||||||
|
randp = minPort;
|
||||||
|
}
|
||||||
|
if (_trialBind(randp)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return randp;
|
||||||
|
}
|
||||||
|
|
||||||
int NodeService::_trialBind(unsigned int port)
|
int NodeService::_trialBind(unsigned int port)
|
||||||
{
|
{
|
||||||
struct sockaddr_in in4;
|
struct sockaddr_in in4;
|
||||||
|
|||||||
@@ -362,6 +362,8 @@ class NodeService {
|
|||||||
|
|
||||||
int shouldBindInterface(const char* ifname, const InetAddress& ifaddr);
|
int shouldBindInterface(const char* ifname, const InetAddress& ifaddr);
|
||||||
|
|
||||||
|
unsigned int _getRandomPort(unsigned int minPort, unsigned int maxPort);
|
||||||
|
|
||||||
int _trialBind(unsigned int port);
|
int _trialBind(unsigned int port);
|
||||||
|
|
||||||
/** Return whether the NodeService is running */
|
/** Return whether the NodeService is running */
|
||||||
|
|||||||
Reference in New Issue
Block a user