Skip to content

Commit

Permalink
feat(dashmate): validate external IP (#2183)
Browse files Browse the repository at this point in the history
  • Loading branch information
shumkov authored Sep 29, 2024
1 parent 4ae1efd commit bc55acd
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 20 deletions.
60 changes: 48 additions & 12 deletions packages/dashmate/src/doctor/analyse/analyseConfigFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,25 @@ and revoke the previous certificate in the ZeroSSL dashboard`,
if (coreP2pPort && coreP2pPort !== 'OPEN') {
const port = config.get('core.p2p.port');
const externalIp = config.get('externalIp');
const problem = new Problem(
'Core P2P port is unavailable for incoming connections.',
chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open

let solution = chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open
for incoming connections. You may need to configure your firewall to
ensure this port is accessible from the public internet. If you are using
Network Address Translation (NAT), please enable port forwarding for port 80
and all Dash service ports listed above.`;
if (externalIp) {
solution = chalk`Please ensure your configured IP address ${externalIp} is your public IP.
You can change it using {bold.cyanBright dashmate config set externalIp [IP]}.
Also, ensure that port ${port} on your public IP address is open
for incoming connections. You may need to configure your firewall to
ensure this port is accessible from the public internet. If you are using
Network Address Translation (NAT), please enable port forwarding for port 80
and all Dash service ports listed above.`,
and all Dash service ports listed above.`;
}

const problem = new Problem(
'Core P2P port is unavailable for incoming connections.',
solution,
SEVERITY.HIGH,
);

Expand All @@ -178,13 +190,25 @@ and all Dash service ports listed above.`,
if (gatewayHttpPort && gatewayHttpPort !== 'OPEN') {
const port = config.get('platform.gateway.listeners.dapiAndDrive.port');
const externalIp = config.get('externalIp');
const problem = new Problem(
'Gateway HTTP port is unavailable for incoming connections.',
chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open

let solution = chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open
for incoming connections. You may need to configure your firewall to
ensure this port is accessible from the public internet. If you are using
Network Address Translation (NAT), please enable port forwarding for port 80
and all Dash service ports listed above.`;
if (externalIp) {
solution = chalk`Please ensure your configured IP address ${externalIp} is your public IP.
You can change it using {bold.cyanBright dashmate config set externalIp [IP]}.
Also, ensure that port ${port} on your public IP address is open
for incoming connections. You may need to configure your firewall to
ensure this port is accessible from the public internet. If you are using
Network Address Translation (NAT), please enable port forwarding for port 80
and all Dash service ports listed above.`,
and all Dash service ports listed above.`;
}

const problem = new Problem(
'Gateway HTTP port is unavailable for incoming connections.',
solution,
SEVERITY.HIGH,
);

Expand All @@ -196,13 +220,25 @@ and all Dash service ports listed above.`,
if (tenderdashP2pPort && tenderdashP2pPort !== 'OPEN') {
const port = config.get('platform.drive.tenderdash.p2p.port');
const externalIp = config.get('externalIp');
const problem = new Problem(
'Tenderdash P2P port is unavailable for incoming connections.',
chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open

let solution = chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open
for incoming connections. You may need to configure your firewall to
ensure this port is accessible from the public internet. If you are using
Network Address Translation (NAT), please enable port forwarding for port 80
and all Dash service ports listed above.`,
and all Dash service ports listed above.`;
if (externalIp) {
solution = chalk`Please ensure your configured IP address ${externalIp} is your public IP.
You can change it using {bold.cyanBright dashmate config set externalIp [IP]}.
Also, ensure that port ${port} on your public IP address is open
for incoming connections. You may need to configure your firewall to
ensure this port is accessible from the public internet. If you are using
Network Address Translation (NAT), please enable port forwarding for port 80
and all Dash service ports listed above.`;
}

const problem = new Problem(
'Tenderdash P2P port is unavailable for incoming connections.',
solution,
SEVERITY.HIGH,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export default function collectSamplesTaskFactory(
title: 'Core P2P port',
task: async () => {
const port = config.get('core.p2p.port');
const response = await providers.mnowatch.checkPortStatus(port);
const response = await providers.mnowatch.checkPortStatus(port, config.get('externalIp'));

ctx.samples.setServiceInfo('core', 'p2pPort', response);
},
Expand All @@ -176,7 +176,7 @@ export default function collectSamplesTaskFactory(
enabled: () => config.get('platform.enable'),
task: async () => {
const port = config.get('platform.gateway.listeners.dapiAndDrive.port');
const response = await providers.mnowatch.checkPortStatus(port);
const response = await providers.mnowatch.checkPortStatus(port, config.get('externalIp'));

ctx.samples.setServiceInfo('gateway', 'httpPort', response);
},
Expand All @@ -185,7 +185,7 @@ export default function collectSamplesTaskFactory(
title: 'Tenderdash P2P port',
task: async () => {
const port = config.get('platform.drive.tenderdash.p2p.port');
const response = await providers.mnowatch.checkPortStatus(port);
const response = await providers.mnowatch.checkPortStatus(port, config.get('externalIp'));

ctx.samples.setServiceInfo('drive_tenderdash', 'p2pPort', response);
},
Expand Down
11 changes: 9 additions & 2 deletions packages/dashmate/src/status/providers.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,14 @@ export default {
},
},
mnowatch: {
checkPortStatus: async (port) => {
/**
* Check the status of a port and optionally validate an IP address.
*
* @param {number} port - The port number to check.
* @param {string} [ip] - Optional. The IP address to validate.
* @returns {Promise<string>} A promise that resolves to the port status.
*/
checkPortStatus: async (port, ip = undefined) => {
// We use http request instead fetch function to force
// using IPv4 otherwise mnwatch could try to connect to IPv6 node address
// and fail (Core listens for IPv4 only)
Expand All @@ -72,7 +79,7 @@ export default {
const options = {
hostname: 'mnowatch.org',
port: 443,
path: `/${port}/`,
path: ip ? `/${port}/?validateIp=${ip}` : `/${port}/`,
method: 'GET',
family: 4, // Force IPv4
timeout: MAX_REQUEST_TIMEOUT,
Expand Down
2 changes: 1 addition & 1 deletion packages/dashmate/src/status/scopes/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export default function getCoreScopeFactory(

const providersResult = await Promise.allSettled([
providers.github.release('dashpay/dash'),
providers.mnowatch.checkPortStatus(config.get('core.p2p.port')),
providers.mnowatch.checkPortStatus(config.get('core.p2p.port'), config.get('externalIp')),
providers.insight(config.get('network')).status(),
]);

Expand Down
4 changes: 2 additions & 2 deletions packages/dashmate/src/status/scopes/platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ export default function getPlatformScopeFactory(
// Collecting platform data fails if Tenderdash is waiting for core to sync
if (info.serviceStatus === ServiceStatusEnum.up) {
const portStatusResult = await Promise.allSettled([
providers.mnowatch.checkPortStatus(config.get('platform.gateway.listeners.dapiAndDrive.port')),
providers.mnowatch.checkPortStatus(config.get('platform.drive.tenderdash.p2p.port')),
providers.mnowatch.checkPortStatus(config.get('platform.gateway.listeners.dapiAndDrive.port'), config.get('externalIp')),
providers.mnowatch.checkPortStatus(config.get('platform.drive.tenderdash.p2p.port'), config.get('externalIp')),
]);
const [httpPortState, p2pPortState] = portStatusResult.map((result) => (result.status === 'fulfilled' ? result.value : null));

Expand Down

0 comments on commit bc55acd

Please sign in to comment.