Skip to content

Commit

Permalink
Merge pull request #1101 from RunOnFlux/development
Browse files Browse the repository at this point in the history
v4.11.0
  • Loading branch information
TheTrunk authored Sep 5, 2023
2 parents 539693c + 188e37c commit 1099c81
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 102 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ sudo apt-get update -y
sudo apt-get install syncthing -y
```

Install Netcat

```bash
sudo apt install netcat -y
```

Clone Flux repo (Ubuntu):

```bash
Expand Down
9 changes: 9 additions & 0 deletions ZelBack/src/services/appsService.js
Original file line number Diff line number Diff line change
Expand Up @@ -9892,6 +9892,7 @@ async function syncthingApps() {
label,
path: folder,
devices,
paused: false,
});
}
}
Expand Down Expand Up @@ -10101,6 +10102,10 @@ async function checkMyAppsAvailability() {
askingIP = splittedIP[0];
askingIpPort = splittedIP[1];
}
if (myIP === askingIP) {
checkMyAppsAvailability();
return;
}
const timeout = 30000;
const axiosConfig = {
timeout,
Expand Down Expand Up @@ -10221,6 +10226,10 @@ async function checkInstallingAppPortAvailable(portsToTest = []) {
await serviceHelper.delay(10 * 1000);
// eslint-disable-next-line no-await-in-loop
let askingIP = await fluxNetworkHelper.getRandomConnection();
while (askingIP.split(':')[0] === myIP) {
// eslint-disable-next-line no-await-in-loop
askingIP = await fluxNetworkHelper.getRandomConnection();
}
let askingIpPort = config.server.apiport;
if (askingIP.includes(':')) { // has port specification
// it has port specification
Expand Down
125 changes: 25 additions & 100 deletions ZelBack/src/services/fluxNetworkHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ const fs = require('fs').promises;
const path = require('path');
// eslint-disable-next-line import/no-extraneous-dependencies
const util = require('util');
// eslint-disable-next-line import/no-extraneous-dependencies
const net = require('net');
const { LRUCache } = require('lru-cache');
const log = require('../lib/log');
const serviceHelper = require('./serviceHelper');
Expand Down Expand Up @@ -170,91 +168,18 @@ function isPortBanned(port) {

/**
* To perform a basic check if port on an ip is opened
* This requires our port to be also open on out
* @param {string} ip IP address.
* @param {number} port Port.
* @param {string} app Application name. Mostly for comsetic purposes, can be boolean. Defaults to undefined, as for testing main FluxOS not an app.
* @param {number} timeout Timeout in ms.
* @returns {boolean} Returns true if opened, otherwise false
*/
async function isPortOpen(ip, port, app, timeout = 5000) {
let resp;
let firewallActive;
async function isPortOpen(ip, port) {
try {
let portResponse = true;
// eslint-disable-next-line no-use-before-define
firewallActive = await isFirewallActive();
// open port first
if (firewallActive) {
// eslint-disable-next-line no-use-before-define
resp = await allowOutPort(port).catch((error) => { // requires allow out for apps checking, for our ports both
log.error(error);
});
if (!resp) {
resp = {};
}
} else {
resp.message = 'existing';
}

const promise = new Promise(((resolve, reject) => {
const socket = new net.Socket();

const onError = (err) => {
socket.destroy();
if (err.code && err.code === 'ETIMEDOUT') {
log.info(`Connection on ${ip}:${port} ETIMEDOUT. Flux or Flux App is not running correctly`);
reject();
} else if (app) {
resolve();
} else if (port === 16129) {
log.error(`Syncthing of Flux on ${ip}:${port} did not respond correctly but may be in use. Allowing`);
log.error(err);
resolve();
} else {
log.error(`Flux on ${ip}:${port} is not working correctly`);
log.error(err);
reject();
}
};

const onTimeout = () => {
log.error(`Connection on ${ip}:${port} timed out. Flux or Flux App is not running correctly`);
socket.destroy();
reject();
};

socket.setTimeout(timeout);
socket.once('error', onError);
socket.once('timeout', onTimeout);

socket.connect(port, ip, () => {
socket.destroy();
portResponse = 'listening';
resolve();
});
}));
await promise;
setTimeout(() => { // timeout ensure return first
if (app && firewallActive) {
// delete the rule
if (resp.message !== 'existing') { // new or updated rule or firewall not active from above
// eslint-disable-next-line no-use-before-define
deleteAllowOutPortRule(port); // no need waiting for response. Delete if was not present before to not create huge firewall list
}
}
}, 10);
return portResponse; // true for OK port. listening for port that is being listened to
const exec = `nc -w 5 -z -v ${ip} ${port} </dev/null; echo $?`;
const cmdAsync = util.promisify(nodecmd.get);
const result = await cmdAsync(exec);
return !+result;
} catch (error) {
setTimeout(() => { // timeout ensure return first
if (app && firewallActive) {
// delete the rule
if (resp.message !== 'existing') { // new or updated rule or firewall not active from above
// eslint-disable-next-line no-use-before-define
deleteAllowOutPortRule(port); // no need waiting for response. Delete if was not present before to not create huge firewall list
}
}
}, 10);
log.error(error);
return false;
}
}
Expand Down Expand Up @@ -287,12 +212,9 @@ async function isFluxAvailable(ip, port = config.server.apiport) {
if (!UIok) return false;

const syncthingPort = +port + 2;
// eslint-disable-next-line no-use-before-define
const syncthingOpen = await isPortOpen(ip, syncthingPort);
if (!syncthingOpen) return false;

return true;
return isPortOpen(ip, syncthingPort);
} catch (e) {
log.error(e);
return false;
}
}
Expand Down Expand Up @@ -343,7 +265,7 @@ async function checkAppAvailability(req, res) {
const processedBody = serviceHelper.ensureObject(body);

const {
ip, ports, appname, pubKey, signature,
ip, ports, pubKey, signature,
} = processedBody;

const ipPort = processedBody.port;
Expand All @@ -363,31 +285,19 @@ async function checkAppAvailability(req, res) {
const daemonHeight = syncStatus.data.height;
const minPort = daemonHeight >= config.fluxapps.portBlockheightChange ? config.fluxapps.portMinNew : config.fluxapps.portMin - 1000;
const maxPort = daemonHeight >= config.fluxapps.portBlockheightChange ? config.fluxapps.portMaxNew : config.fluxapps.portMax;
const portsListening = [];
// eslint-disable-next-line no-restricted-syntax
for (const port of ports) {
const iBP = isPortBanned(+port);
if (+port >= minPort && +port <= maxPort && !iBP) {
// eslint-disable-next-line no-await-in-loop
const isOpen = await isPortOpen(ip, port, appname, 30000);
const isOpen = await isPortOpen(ip, port);
if (!isOpen) {
throw new Error(`Flux Applications on ${ip}:${ipPort} are not available. Failed port: ${port}`);
} else if (isOpen === 'listening') { // this port is in use and listening. Later do check from other node on this port
portsListening.push(+port);
}
} else {
log.error(`Flux App port ${port} is outside allowed range.`);
}
}
// if ip is my if, do a data response with ports that are listening
const dataResponse = messageHelper.createDataMessage(portsListening);
// eslint-disable-next-line no-use-before-define
let myIP = await getMyFluxIPandPort();
myIP = myIP.split(':')[0];
if (ip === myIP) {
res.json(dataResponse);
return;
}
const successResponse = messageHelper.createSuccessMessage(`Flux Applications on ${ip}:${ipPort} are available.`);
res.json(successResponse);
} catch (error) {
Expand Down Expand Up @@ -1411,6 +1321,20 @@ async function allowNodeToBindPrivilegedPorts() {
}
}

/**
* Install Netcat from apt
* Despite nc tool is by default present on both Debian and Ubuntu we install netcat for precaution
*/
async function installNetcat() {
try {
const exec = 'sudo apt install netcat -y';
const cmdAsync = util.promisify(nodecmd.get);
cmdAsync(exec);
} catch (error) {
log.error(error);
}
}

module.exports = {
minVersionSatisfy,
isFluxAvailable,
Expand Down Expand Up @@ -1455,4 +1379,5 @@ module.exports = {
isPortBanned,
isPortUserBlocked,
allowNodeToBindPrivilegedPorts,
installNetcat,
};
3 changes: 2 additions & 1 deletion ZelBack/src/services/serviceManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ async function startFluxFunctions() {
} else {
upnpService.setupUPNP(apiPort);
}
fluxNetworkHelper.installNetcat();
log.info('Initiating MongoDB connection');
await dbHelper.initiateDB(); // either true or throws error
log.info('DB connected');
Expand Down Expand Up @@ -127,7 +128,7 @@ async function startFluxFunctions() {
}, 60 * 60 * 1000);
}, 4 * 60 * 1000);
setTimeout(() => {
appsService.syncthingApps(); // rechecks and possibly adjust syncthing configuration every minute
appsService.syncthingApps(); // rechecks and possibly adjust syncthing configuration every 2 minutes
}, 6 * 60 * 1000);
setTimeout(() => {
setInterval(() => { // every 30 mins (15 blocks)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "flux",
"version": "4.10.0",
"version": "4.11.0",
"description": "Flux, Your Gateway to a Decentralized World",
"repository": {
"type": "git",
Expand Down

0 comments on commit 1099c81

Please sign in to comment.