Browse Source

Pick a new random secondary port if we are offline for more than path-timeout seconds (COMA problem workaround).

Adam Ierymenko 3 years ago
parent
commit
11b352458e
3 changed files with 54 additions and 62 deletions
  1. 9 33
      ext/installfiles/mac/postinst.sh
  2. 15 14
      ext/installfiles/mac/preinst.sh
  3. 30 15
      service/OneService.cpp

+ 9 - 33
ext/installfiles/mac/postinst.sh

@@ -2,31 +2,8 @@
 
 export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin
 
-OSX_RELEASE=`sw_vers -productVersion | cut -d . -f 1,2`
-DARWIN_MAJOR=`uname -r | cut -d . -f 1`
-
-launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1
-sleep 0.5
-
 cd "/Library/Application Support/ZeroTier/One"
 
-if [ "$OSX_RELEASE" = "10.7" -o "$OSX_RELEASE" = "10.8" -o "$OSX_RELEASE" = "10.9" -o "$OSX_RELEASE" = "10.10" -o "$OSX_RELEASE" = "10.11" -o "$OSX_RELEASE" = "10.12" ]; then
-	rm -f tap.kext.10_7.tar.gz
-	curl -s https://download.zerotier.com/tap.kext.10_7.tar.gz >tap.kext.10_7.tar.gz
-	if [ -s tap.kext.10_7.tar.gz -a "`shasum -a 256 tap.kext.10_7.tar.gz | cut -d ' ' -f 1`" = "e133d4832cef571621d3618f417381b44f51a76ed625089fb4e545e65d3ef2a9" ]; then
-		rm -rf tap.kext
-		tar -xzf tap.kext.10_7.tar.gz
-		chown -R 0 tap.kext
-		chgrp -R 0 tap.kext
-	fi
-	rm -f tap.kext.10_7.tar.gz
-fi
-
-rm -rf node.log node.log.old root-topology shutdownIfUnreadable autoupdate.log updates.d ui peers.save
-
-chown -R 0 tap.kext
-chgrp -R 0 tap.kext
-
 if [ ! -f authtoken.secret ]; then
 	head -c 1024 /dev/urandom | md5 | head -c 24 >authtoken.secret
 	chown 0 authtoken.secret
@@ -37,25 +14,24 @@ fi
 rm -f zerotier-cli zerotier-idtool
 ln -sf zerotier-one zerotier-cli
 ln -sf zerotier-one zerotier-idtool
-mkdir -p /usr/local/bin
+if [ ! -d /usr/local/bin ]; then
+	mkdir -p /usr/local/bin
+fi
 cd /usr/local/bin
 rm -f zerotier-cli zerotier-idtool
 ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-cli
 ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-idtool
 
-if [ $DARWIN_MAJOR -le 16 ]; then
-	cd "/Library/Application Support/ZeroTier/One"
-	kextload -r . tap.kext >>/dev/null 2>&1 &
-	disown %1
-fi
-
 launchctl load /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1
-
-sleep 1
+sleep 2
 
 if [ -f /tmp/zt1-gui-restart.tmp ]; then
 	for u in `cat /tmp/zt1-gui-restart.tmp`; do
-		su $u -c '/Applications/ZeroTier\ One.app/Contents/MacOS/ZeroTier\ One &' >>/dev/null 2>&1 &
+		if [ -f '/Applications/ZeroTier One.app/Contents/MacOS/ZeroTier One' ]; then
+			su $u -c '/Applications/ZeroTier\ One.app/Contents/MacOS/ZeroTier\ One &' >>/dev/null 2>&1 &
+		else
+			su $u -c '/Applications/ZeroTier.app/Contents/MacOS/ZeroTier &' >>/dev/null 2>&1 &
+		fi
 	done
 fi
 rm -f /tmp/zt1-gui-restart.tmp

+ 15 - 14
ext/installfiles/mac/preinst.sh

@@ -8,7 +8,17 @@ for i in `ps axuwww | tr -s ' ' ',' | grep -F '/Applications/ZeroTier,One.app' |
 	p=`echo $i | cut -d , -f 2`
 	if [ ! -z "$u" -a "0$p" -gt 0 ]; then
 		kill $p >>/dev/null 2>&1
-		sleep 0.2
+		sleep 0.5
+		kill -9 $p >>/dev/null 2>&1
+		echo "$u" >>/tmp/zt1-gui-restart.tmp
+	fi
+done
+for i in `ps axuwww | tr -s ' ' ',' | grep -F '/Applications/ZeroTier.app' | grep -F -v grep | cut -d , -f 1,2 | xargs`; do
+	u=`echo $i | cut -d , -f 1`
+	p=`echo $i | cut -d , -f 2`
+	if [ ! -z "$u" -a "0$p" -gt 0 ]; then
+		kill $p >>/dev/null 2>&1
+		sleep 0.5
 		kill -9 $p >>/dev/null 2>&1
 		echo "$u" >>/tmp/zt1-gui-restart.tmp
 	fi
@@ -17,23 +27,14 @@ chmod 0600 /tmp/zt1-gui-restart.tmp
 
 if [ -f /Library/LaunchDaemons/com.zerotier.one.plist ]; then
 	launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1
+	sleep 5
 fi
-
-sleep 1
-
-if [ -d "/Library/Application Support/ZeroTier/One" ]; then
-	cd "/Library/Application Support/ZeroTier/One"
-	if [ -f "zerotier-one.pid" ]; then
-		ztpid=`cat zerotier-one.pid`
-		if [ "$ztpid" -gt "0" ]; then
-			kill `cat zerotier-one.pid`
-		fi
-	fi
+if [ -f '/Library/Application Support/ZeroTier/One/zerotier-one.pid' ]; then
+	kill -9 `cat /Library/Application Support/ZeroTier/One/zerotier-one.pid`
 fi
 
-sleep 1
-
 cd "/Applications"
 rm -rf "ZeroTier One.app"
+rm -rf "ZeroTier.app"
 
 exit 0

+ 30 - 15
service/OneService.cpp

@@ -743,19 +743,7 @@ public:
 				if (_secondaryPort) {
 					_ports[1] = _secondaryPort;
 				} else {
-					unsigned int randp = 0;
-					Utils::getSecureRandom(&randp,sizeof(randp));
-					_ports[1] = 20000 + (randp % 45500);
-					for(int i=0;;++i) {
-						if (i > 1000) {
-							_ports[1] = 0;
-							break;
-						} else if (++_ports[1] >= 65536) {
-							_ports[1] = 20000;
-						}
-						if (_trialBind(_ports[1]))
-							break;
-					}
+					_ports[1] = _getRandomPort();
 				}
 			}
 #ifdef ZT_USE_MINIUPNPC
@@ -767,7 +755,7 @@ public:
 					if (_tertiaryPort) {
 						_ports[2] = _tertiaryPort;
 					} else {
-						_ports[2] = _ports[1];
+						_ports[2] = 20000 + (_ports[0] % 40000);
 						for(int i=0;;++i) {
 							if (i > 1000) {
 								_ports[2] = 0;
@@ -828,6 +816,7 @@ public:
 			int64_t lastCleanedPeersDb = 0;
 			int64_t lastLocalInterfaceAddressCheck = (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 lastLocalConfFileCheck = OSUtils::now();
+			int64_t lastOnline = lastLocalConfFileCheck;
 			for(;;) {
 				_run_m.lock();
 				if (!_run) {
@@ -869,6 +858,16 @@ public:
 					}
 				}
 
+				// 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();
+					lastBindRefresh = 0;
+				}
+
 				// Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow routes (e.g. shadow default)
 				if (((now - lastBindRefresh) >= (_node->bondController()->inUse() ? ZT_BINDER_REFRESH_PERIOD / 4 : ZT_BINDER_REFRESH_PERIOD))||(restarted)) {
 					lastBindRefresh = now;
@@ -1858,7 +1857,7 @@ public:
 		_secondaryPort = (unsigned int)OSUtils::jsonInt(settings["secondaryPort"],0);
 		_tertiaryPort = (unsigned int)OSUtils::jsonInt(settings["tertiaryPort"],0);
 		if (_secondaryPort != 0 || _tertiaryPort != 0) {
-			fprintf(stderr,"WARNING: using manually-specified ports. This can cause NAT issues." ZT_EOL_S);
+			fprintf(stderr,"WARNING: using manually-specified secondary and/or tertiary ports. This can cause NAT issues." ZT_EOL_S);
 		}
 		_portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true);
 
@@ -3102,6 +3101,22 @@ public:
 		return true;
 	}
 
+	unsigned int _getRandomPort()
+	{
+		unsigned int randp = 0;
+		Utils::getSecureRandom(&randp,sizeof(randp));
+		randp = 20000 + (randp % 45500);
+		for(int i=0;;++i) {
+			if (i > 1000) {
+				return 0;
+			} else if (++randp >= 65536) {
+				randp = 20000;
+			}
+			if (_trialBind(randp))
+				break;
+		}
+	}
+
 	bool _trialBind(unsigned int port)
 	{
 		struct sockaddr_in in4;