diff --git a/plugins/cloud/package-lock.json b/plugins/cloud/package-lock.json index 8f5cb5102..d59ce45ee 100644 --- a/plugins/cloud/package-lock.json +++ b/plugins/cloud/package-lock.json @@ -1,14 +1,16 @@ { "name": "@scrypted/cloud", - "version": "0.0.43", + "version": "0.0.44", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/cloud", - "version": "0.0.43", + "version": "0.0.44", "dependencies": { "@eneris/push-receiver": "../../external/push-receiver", + "@scrypted/common": "file:../../common", + "@scrypted/sdk": "file:../../sdk", "axios": "^0.25.0", "bpmux": "^8.1.3", "debug": "^4.3.1", @@ -17,17 +19,15 @@ "query-string": "^6.14.1" }, "devDependencies": { - "@scrypted/common": "file:../../common", - "@scrypted/sdk": "file:../../sdk", "@types/debug": "^4.1.5", "@types/http-proxy": "^1.17.5", - "@types/nat-upnp": "^1.1.2" + "@types/nat-upnp": "^1.1.2", + "@types/node": "^18.11.18" } }, "../../common": { "name": "@scrypted/common", "version": "1.0.1", - "dev": true, "license": "ISC", "dependencies": { "@scrypted/sdk": "file:../sdk", @@ -72,8 +72,7 @@ }, "../../sdk": { "name": "@scrypted/sdk", - "version": "0.2.55", - "dev": true, + "version": "0.2.56", "license": "ISC", "dependencies": { "@babel/preset-typescript": "^7.18.6", @@ -154,9 +153,9 @@ } }, "node_modules/@types/node": { - "version": "17.0.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.15.tgz", - "integrity": "sha512-zWt4SDDv1S9WRBNxLFxFRHxdD9tvH8f5/kg5/IaLFdnSNXsDY4eL3Q3XXN+VxUnWIhyVFDwcsmAprvwXoM/ClA==", + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", "dev": true }, "node_modules/ansi-regex": { @@ -185,6 +184,11 @@ "lodash": "^4.17.14" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -288,6 +292,17 @@ "node": ">=0.1.90" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", @@ -329,9 +344,9 @@ } }, "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "engines": { "node": ">=0.10" } @@ -380,6 +395,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/diff": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", @@ -481,9 +504,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "funding": [ { "type": "individual", @@ -508,6 +531,19 @@ "is-callable": "^1.1.3" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/frame-stream": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/frame-stream/-/frame-stream-2.1.0.tgz", @@ -1124,6 +1160,25 @@ "integrity": "sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==", "dev": true }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", @@ -1377,6 +1432,11 @@ "node": ">= 0.6.6" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/query-string": { "version": "6.14.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", @@ -1803,9 +1863,11 @@ "dev": true }, "node-nat-upnp": { + "name": "nat-upnp", "version": "1.1.1", "dependencies": { "async": "^2.1.5", + "axios": "^1.2.4", "ip": "^1.1.4", "xml2js": "~0.1.14" }, @@ -1813,6 +1875,16 @@ "jscs": "^1.11.2", "mocha": "^3.2.0" } + }, + "node-nat-upnp/node_modules/axios": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.4.tgz", + "integrity": "sha512-lIQuCfBJvZB/Bv7+RWUqEJqNShGOVpk9v7P0ZWx5Ip0qY6u7JBAU6dzQPMLasU9vHL2uD8av/1FDJXj7n6c39w==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } } }, "dependencies": { @@ -1908,9 +1980,9 @@ } }, "@types/node": { - "version": "17.0.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.15.tgz", - "integrity": "sha512-zWt4SDDv1S9WRBNxLFxFRHxdD9tvH8f5/kg5/IaLFdnSNXsDY4eL3Q3XXN+VxUnWIhyVFDwcsmAprvwXoM/ClA==", + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", "dev": true }, "ansi-regex": { @@ -1933,6 +2005,11 @@ "lodash": "^4.17.14" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -2015,6 +2092,14 @@ "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", @@ -2042,9 +2127,9 @@ } }, "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==" }, "deep-equal": { "version": "2.2.0", @@ -2081,6 +2166,11 @@ "object-keys": "^1.1.1" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "diff": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", @@ -2151,9 +2241,9 @@ "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=" }, "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" }, "for-each": { "version": "0.3.3", @@ -2164,6 +2254,16 @@ "is-callable": "^1.1.3" } }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "frame-stream": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/frame-stream/-/frame-stream-2.1.0.tgz", @@ -2637,6 +2737,19 @@ "integrity": "sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==", "dev": true }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, "minimatch": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", @@ -2754,10 +2867,23 @@ "version": "file:node-nat-upnp", "requires": { "async": "^2.1.5", + "axios": "^1.2.4", "ip": "^1.1.4", "jscs": "^1.11.2", "mocha": "^3.2.0", "xml2js": "~0.1.14" + }, + "dependencies": { + "axios": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.4.tgz", + "integrity": "sha512-lIQuCfBJvZB/Bv7+RWUqEJqNShGOVpk9v7P0ZWx5Ip0qY6u7JBAU6dzQPMLasU9vHL2uD8av/1FDJXj7n6c39w==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + } } }, "ncp": { @@ -2840,6 +2966,11 @@ "winston": "0.8.x" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "query-string": { "version": "6.14.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", diff --git a/plugins/cloud/package.json b/plugins/cloud/package.json index 80323b13c..841e4aac5 100644 --- a/plugins/cloud/package.json +++ b/plugins/cloud/package.json @@ -34,6 +34,8 @@ ] }, "dependencies": { + "@scrypted/common": "file:../../common", + "@scrypted/sdk": "file:../../sdk", "@eneris/push-receiver": "../../external/push-receiver", "axios": "^0.25.0", "bpmux": "^8.1.3", @@ -43,11 +45,10 @@ "query-string": "^6.14.1" }, "devDependencies": { - "@scrypted/common": "file:../../common", - "@scrypted/sdk": "file:../../sdk", "@types/debug": "^4.1.5", "@types/http-proxy": "^1.17.5", - "@types/nat-upnp": "^1.1.2" + "@types/nat-upnp": "^1.1.2", + "@types/node": "^18.11.18" }, - "version": "0.0.43" + "version": "0.0.44" } diff --git a/plugins/cloud/src/main.ts b/plugins/cloud/src/main.ts index e0b238f23..6ba0daab6 100644 --- a/plugins/cloud/src/main.ts +++ b/plugins/cloud/src/main.ts @@ -4,7 +4,8 @@ import axios from 'axios'; import bpmux from 'bpmux'; import crypto from 'crypto'; import { once } from 'events'; -import { createServer, Server } from 'http'; +import http from 'http'; +import https from 'https'; import HttpProxy from 'http-proxy'; import upnp from 'nat-upnp'; import net from 'net'; @@ -13,8 +14,10 @@ import path from 'path'; import qs from 'query-string'; import { Duplex } from 'stream'; import Url from 'url'; -import type { CORSControl, CORSControlLegacy } from '../../../server/src/services/cors'; +import type { CORSControlLegacy } from '../../../server/src/services/cors'; +import { createSelfSignedCertificate } from '../../../server/src/cert'; import { PushManager } from './push'; +import tls from 'tls'; const { deviceManager, endpointManager, systemManager } = sdk; @@ -31,7 +34,6 @@ class ScryptedPush extends ScryptedDeviceBase implements BufferConverter { this.toMimeType = ScryptedMimeTypes.Url; } - async convert(data: Buffer | string, fromMimeType: string): Promise { if (this.cloud.storageSettings.values.hostname) { return Buffer.from(`https://${this.cloud.getHostname()}${await this.cloud.getCloudMessagePath()}/${data}`); @@ -44,7 +46,8 @@ class ScryptedPush extends ScryptedDeviceBase implements BufferConverter { class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, BufferConverter, DeviceProvider, HttpRequestHandler { manager = new PushManager(DEFAULT_SENDER_ID); - server: Server; + server: http.Server; + secureServer: https.Server; proxy: HttpProxy; push: ScryptedPush; whitelisted = new Map(); @@ -87,10 +90,19 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, lastPersistedIp: { hide: true, }, + certificate: { + hide: true, + json: true, + }, + securePort: { + hide: true, + type: 'number', + }, }); upnpInterval: NodeJS.Timeout; upnpClient = upnp.createClient(); upnpStatus = 'Starting'; + securePort: number; constructor() { super(); @@ -98,6 +110,9 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, this.fromMimeType = ScryptedMimeTypes.LocalUrl; this.toMimeType = ScryptedMimeTypes.Url; + if (!this.storageSettings.values.certificate) + this.storageSettings.values.certificate = createSelfSignedCertificate(); + this.setupProxyServer(); this.setupCloudPush(); @@ -113,9 +128,6 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, }) this.updateCors(); - - this.upnpInterval = setInterval(this.refreshUpnp, 30 * 60 * 1000); - this.refreshUpnp(); } async refreshUpnp() { @@ -135,10 +147,15 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, }, private: { host: localAddress, - port: 10443, + port: this.securePort, }, ttl: 1800, }, async err => { + + this.upnpClient.getMappings(function (err, results) { + console.log('current upnp mappings', results); + }); + if (err) { this.console.error('UPNP failed', err); this.upnpStatus = 'Error: See Console'; @@ -152,7 +169,7 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, const response = await axios('https://jsonip.com'); const { ip } = response.data; - this.console.log('External IP:', ip); + this.console.log(`Mapped port https://127.0.0.1:${this.securePort} to https://${ip}:${upnpPort}`); // the ip is not sent, but should be checked to see if it changed. if (this.storageSettings.values.lastPersistedUpnpPort !== upnpPort || ip !== this.storageSettings.values.lastPersistedIp) { @@ -361,18 +378,19 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, } async setupProxyServer() { + // TODO: 1/25/2023 change this to getInsecurePublicLocalEndpoint to avoid double crypto const ep = await endpointManager.getPublicLocalEndpoint(); - const httpsTarget = new URL(ep); - httpsTarget.hostname = 'localhost'; - httpsTarget.pathname = ''; - const wssTarget = new URL(httpsTarget); - wssTarget.protocol = 'wss'; - const googleHomeTarget = new URL(httpsTarget); + const httpTarget = new URL(ep); + httpTarget.hostname = 'localhost'; + httpTarget.pathname = ''; + const wsTarget = new URL(httpTarget); + wsTarget.protocol = 'ws'; + const googleHomeTarget = new URL(httpTarget); googleHomeTarget.pathname = '/endpoint/@scrypted/google-home/public/'; - const alexaTarget = new URL(httpsTarget); + const alexaTarget = new URL(httpTarget); alexaTarget.pathname = '/endpoint/@scrypted/alexa/public/'; - this.server = createServer(async (req, res) => { + const handler = async (req: http.IncomingMessage, res: http.ServerResponse) => { const url = Url.parse(req.url); if (url.path.startsWith('/web/oauth/callback') && url.query) { const query = qs.parse(url.query); @@ -412,19 +430,36 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, } this.proxy.web(req, res, undefined, (err) => console.error(err)); - }); + } + this.server = http.createServer(handler); this.server.on('upgrade', (req, socket, head) => { - this.proxy.ws(req, socket, head, { target: wssTarget.toString(), ws: true, secure: false }); - }) - + this.proxy.ws(req, socket, head, { target: wsTarget.toString(), ws: true, secure: false }); + }); + // this can be localhost because this is server initiated loopback proxy this.server.listen(0, '127.0.0.1'); - await once(this.server, 'listening'); const port = (this.server.address() as any).port; + this.secureServer = https.createServer({ + key: this.storageSettings.values.certificate.serviceKey, + cert: this.storageSettings.values.certificate.certificate, + }, (req, res) => { + handler(req, res); + }); + this.secureServer.on('upgrade', (req, socket, head) => { + this.proxy.ws(req, socket, head, { target: wsTarget.toString(), ws: true, secure: false }); + }) + // this is the direct connection port + this.secureServer.listen(this.storageSettings.values.securePort, '0.0.0.0'); + await once(this.secureServer, 'listening'); + this.storageSettings.values.securePort = this.securePort = (this.secureServer.address() as any).port; + + this.upnpInterval = setInterval(this.refreshUpnp, 30 * 60 * 1000); + this.refreshUpnp(); + this.proxy = HttpProxy.createProxy({ - target: httpsTarget, + target: httpTarget, secure: false, }); this.proxy.on('error', () => { }); @@ -456,7 +491,9 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, backoff = Date.now(); const random = Math.random().toString(36).substring(2); this.console.log('scrypted server requested a connection:', random); - const client = net.connect(4000, SCRYPTED_SERVER); + const client = tls.connect(4001, SCRYPTED_SERVER, { + rejectUnauthorized: false, + }); client.on('close', () => this.console.log('scrypted server connection ended:', random)); const registrationId = await this.manager.registrationId; client.write(registrationId + '\n');