From 41afd3ff31245a5f5590bded443c5e952f0e8a4b Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 13 Nov 2018 16:58:02 +0900 Subject: [PATCH 1/7] Don't mutate db --- build/src/src/client.js | 3 --- build/src/src/db.js | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/build/src/src/client.js b/build/src/src/client.js index c38f0efe..7d7e8042 100644 --- a/build/src/src/client.js +++ b/build/src/src/client.js @@ -100,9 +100,6 @@ async function start() { // Print db censoring privateKey const _db = await db.get(); - if (_db && _db.privateKey) { - _db.privateKey = _db.privateKey.replace(/./g, '*'); - } logs.info(JSON.stringify(_db, null, 2 )); // /////////////////////// diff --git a/build/src/src/db.js b/build/src/src/db.js index e36b8c6e..2225bc59 100644 --- a/build/src/src/db.js +++ b/build/src/src/db.js @@ -25,7 +25,7 @@ const get = async (key) => { if (key) { return db.get(key).value(); } else { - return db.getState(); + return Object.assign({}, db.getState()); } }; From 3bcb8c3e2aeb8444c5be39f51f0475411117fe70 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 13 Nov 2018 18:31:48 +0900 Subject: [PATCH 2/7] On corrupted privateKey, generate new one Modified the dyndnsClient.generateKeys() function to check if the privateKey is valid calling `EthCrypto.publicKeyByPrivateKey(privateKey)` inside a try/catch block. If the privateKey is not valid, a new one is generate, along the publicKey and domain. dyndnsClient.generateKeys() is called at every VPN startup in client.js line 72 If the privateKey is corrupted a new one will be generated in that line. On client.js line 83 `await dyndnsClient.updateIp();` is called on every VPN startup if the static IP is not set. In that case it will register the new dyndns domain. --- build/src/src/client.js | 2 ++ build/src/src/dyndnsClient/generateKeys.js | 34 +++++++++++++++++-- .../test/dyndnsClient/generateKeys.test.js | 27 +++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/build/src/src/client.js b/build/src/src/client.js index 7d7e8042..4b5e89f7 100644 --- a/build/src/src/client.js +++ b/build/src/src/client.js @@ -67,6 +67,8 @@ async function start() { // init.sh // 1. Create VPN's address + publicKey + privateKey if it doesn't exist yet + // Also, verify if the privateKey is corrupted or lost. + // In that case generate a new identity and alert the user await dyndnsClient.generateKeys(); // fetchVpnParameters read the output files from the .sh scripts diff --git a/build/src/src/dyndnsClient/generateKeys.js b/build/src/src/dyndnsClient/generateKeys.js index a30bc2d4..484015f8 100644 --- a/build/src/src/dyndnsClient/generateKeys.js +++ b/build/src/src/dyndnsClient/generateKeys.js @@ -2,6 +2,18 @@ const EthCrypto = require('eth-crypto'); const db = require('../db'); const logs = require('../logs.js')(module); +const corruptedPrivateKeyMessage = +` + + +===================================================================== + Found corrupted privateKey. + Reseting DYNDNS subdomain, please update your user's profiles +===================================================================== + + +`; + /** * EthCrypto reference * @@ -33,11 +45,27 @@ function getDyndnsHost() { : DYNDNS_DOMAIN; } +function isPrivateKeyValid(privateKey) { + try { + EthCrypto.publicKeyByPrivateKey(privateKey); + return true; + } catch (e) { + /* eslint-disable max-len */ + logs.warn('Private key verification failed. EthCrypto.publicKeyByPrivateKey returned error: '+e.stack); + return false; + } +} + async function generateKeys() { - if (await db.get('privateKey')) { - logs.info(`Skipping keys generation, found identity in db`); - return; + const currentPrivateKey = await db.get('privateKey'); + if (currentPrivateKey) { + if (isPrivateKeyValid(currentPrivateKey)) { + logs.info(`Skipping keys generation, found identity in db`); + return; + } else { + logs.warn(corruptedPrivateKeyMessage); + } } const {address, privateKey, publicKey} = EthCrypto.createIdentity(); await db.set('address', address); diff --git a/build/src/test/dyndnsClient/generateKeys.test.js b/build/src/test/dyndnsClient/generateKeys.test.js index fd1a1ebe..85455053 100644 --- a/build/src/test/dyndnsClient/generateKeys.test.js +++ b/build/src/test/dyndnsClient/generateKeys.test.js @@ -5,6 +5,7 @@ const logs = require('../../src/logs.js')(module); const unlink = util.promisify(fs.unlink); const {exec} = require('child_process'); let db = require('../../src/db'); +const EthCrypto = require('eth-crypto'); process.env.DYNDNS_DOMAIN = 'dyn.test.io'; const dbPath = './vpndb'; @@ -70,4 +71,30 @@ describe('generateKeys', function() { }); }); }); + + describe('recover a corrupted privateKey', () => { + it('should detect that a privateKey is corrupted', async () => { + /* eslint-disable max-len */ + // Store old private key and domain to assert the change + const oldPrivateKey = await db.get('privateKey'); + const oldDomain = await db.get('domain'); + + // corrupt the private key + const corruptedPrivateKey = '******************************************************************'; + await db.set('privateKey', corruptedPrivateKey); + + // Call generateKeys. This function will be called always when the VPN resets + await generateKeys(); + + // Assert that a new valid private key is created. + // Also that the domain changed + const newPrivateKey = await db.get('privateKey'); + const newDomain = await db.get('domain'); + expect(newPrivateKey).to.not.equal(oldPrivateKey); + expect(newPrivateKey).to.not.equal(corruptedPrivateKey); + const publicKey = EthCrypto.publicKeyByPrivateKey(newPrivateKey); + expect(publicKey).to.exist; + expect(newDomain).to.not.equal(oldDomain); + }); + }); }); From 05697385e12701336fa73fa8bf89cd1282111732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Antu=C3=B1a=20D=C3=ADez?= Date: Tue, 13 Nov 2018 11:03:07 +0100 Subject: [PATCH 3/7] Added bash as a dependency --- build/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/Dockerfile b/build/Dockerfile index d3a48ff8..2d235b66 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -6,7 +6,8 @@ RUN apk add --update --no-cache \ docker \ git \ libpcap-dev \ - linux-headers + linux-headers \ + bash RUN git clone https://github.com/xelerance/xl2tpd.git && cd xl2tpd && make From a37a36adfdd3a5b1538936afeba3105d6e47b4fa Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 14 Nov 2018 02:20:31 +0900 Subject: [PATCH 4/7] remove unnecessary check --- build/src/src/calls/setStaticIp.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/build/src/src/calls/setStaticIp.js b/build/src/src/calls/setStaticIp.js index 64f5c0d0..12a9ae30 100644 --- a/build/src/src/calls/setStaticIp.js +++ b/build/src/src/calls/setStaticIp.js @@ -15,12 +15,8 @@ async function setStaticIp({staticIp}) { if (!oldStaticIp && staticIp) { message = `Enabled static IP: ${staticIp}`; } else if (oldStaticIp && !staticIp) { - message = `Disabled static IP`; - // If the staticIp is being disabled but there is no keys: register to dyndns - if (!await db.get('registeredToDyndns')) { - await dyndnsClient.updateIp(); - message += `, and registered to dyndns: ${await db.get('domain')}`; - } + await dyndnsClient.updateIp(); + message = `Disabled static IP, and registered to dyndns: ${await db.get('domain')}`; } else { message = `Updated static IP: ${staticIp}`; } From 4374fd92449e47639387c4fd5e28587cbd3540f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Antu=C3=B1a=20D=C3=ADez?= Date: Tue, 13 Nov 2018 20:43:01 +0100 Subject: [PATCH 5/7] registeredToDyndns removed --- build/src/src/dyndnsClient/updateIp.js | 1 - 1 file changed, 1 deletion(-) diff --git a/build/src/src/dyndnsClient/updateIp.js b/build/src/src/dyndnsClient/updateIp.js index b4a09edc..f4ec4898 100644 --- a/build/src/src/dyndnsClient/updateIp.js +++ b/build/src/src/dyndnsClient/updateIp.js @@ -70,7 +70,6 @@ async function updateIp() { if (res.code === 200) { logs.info(`dyndns client success: ${data.message}`); await db.set('domain', data.domain); - await db.set('registeredToDyndns', true); return data.domain; } else { const errorMsg = data.message || JSON.stringify(data); From 4faf9a35d11677bd29788b1784a0e2b6d24a5af9 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 14 Nov 2018 14:17:57 +0900 Subject: [PATCH 6/7] Advanced version --- dappnode_package.json | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/dappnode_package.json b/dappnode_package.json index fc4db213..8d976344 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -1,6 +1,6 @@ { "name": "vpn.dnp.dappnode.eth", - "version": "0.1.18", + "version": "0.1.19", "description": "Dappnode package responsible for providing the VPN (L2TP/IPSec) connection", "avatar": "/ipfs/QmWwMb3XhuCH6JnCF6m6EQzA4mW9pHHtg7rqAfhDr2ofi8", "type": "dncore", @@ -15,10 +15,7 @@ "/var/run/docker.sock:/var/run/docker.sock", "/usr/src/dappnode/config:/usr/src/app/config:ro" ], - "ports": [ - "4500:4500/udp", - "500:500/udp" - ], + "ports": ["4500:4500/udp", "500:500/udp"], "privileged": "true", "restart": "always", "subnet": "172.33.0.0/16", @@ -30,12 +27,7 @@ "DAppLion (https://github.com/dapplion)", "Alex Floyd (https://github.com/mex20)" ], - "keywords": [ - "DAppNodeCore", - "VPN", - "IPSec", - "L2TP" - ], + "keywords": ["DAppNodeCore", "VPN", "IPSec", "L2TP"], "homepage": { "userui": "https://dappnode.github.io/DAppNode_OTP", "homepage": "https://github.com/dappnode/DNP_VPN#readme" @@ -48,4 +40,4 @@ "url": "https://github.com/dappnode/DNP_VPN/issues" }, "license": "GPL-3.0" -} \ No newline at end of file +} From 2fbfa528c732978ce741bda30b80fb62077304a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Antu=C3=B1a=20D=C3=ADez?= Date: Wed, 14 Nov 2018 17:16:09 +0100 Subject: [PATCH 7/7] Updated version number --- dappnode_package.json | 14 +++++++++++--- docker-compose-vpn.yml | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/dappnode_package.json b/dappnode_package.json index 8d976344..c55982d9 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -15,7 +15,10 @@ "/var/run/docker.sock:/var/run/docker.sock", "/usr/src/dappnode/config:/usr/src/app/config:ro" ], - "ports": ["4500:4500/udp", "500:500/udp"], + "ports": [ + "4500:4500/udp", + "500:500/udp" + ], "privileged": "true", "restart": "always", "subnet": "172.33.0.0/16", @@ -27,7 +30,12 @@ "DAppLion (https://github.com/dapplion)", "Alex Floyd (https://github.com/mex20)" ], - "keywords": ["DAppNodeCore", "VPN", "IPSec", "L2TP"], + "keywords": [ + "DAppNodeCore", + "VPN", + "IPSec", + "L2TP" + ], "homepage": { "userui": "https://dappnode.github.io/DAppNode_OTP", "homepage": "https://github.com/dappnode/DNP_VPN#readme" @@ -40,4 +48,4 @@ "url": "https://github.com/dappnode/DNP_VPN/issues" }, "license": "GPL-3.0" -} +} \ No newline at end of file diff --git a/docker-compose-vpn.yml b/docker-compose-vpn.yml index 18355c29..79eca472 100644 --- a/docker-compose-vpn.yml +++ b/docker-compose-vpn.yml @@ -11,7 +11,7 @@ volumes: services: vpn.dnp.dappnode.eth: build: ./build - image: 'vpn.dnp.dappnode.eth:0.1.18' + image: 'vpn.dnp.dappnode.eth:0.1.19' container_name: DAppNodeCore-vpn.dnp.dappnode.eth privileged: true restart: always