From f1f4b3b377d6c00a720fee93bf4be8ed3ac675e6 Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Wed, 30 Mar 2022 01:49:45 +0800 Subject: [PATCH] Add reverse proxy setting page for controlling cloudflared --- package.json | 2 +- .../cloudflared-socket-handler.js | 69 +++++++++-- src/components/settings/ReverseProxy.vue | 111 ++++++++++++++++++ src/mixins/socket.js | 13 ++ src/pages/Settings.vue | 3 + src/router.js | 5 + 6 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 src/components/settings/ReverseProxy.vue diff --git a/package.json b/package.json index 24558dc5d..bb7b1e570 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "jsonwebtoken": "~8.5.1", "jwt-decode": "^3.1.2", "limiter": "^2.1.0", - "node-cloudflared-tunnel": "~1.0.0", + "node-cloudflared-tunnel": "~1.0.6", "nodemailer": "~6.6.5", "notp": "~2.0.3", "password-hash": "~1.2.2", diff --git a/server/socket-handlers/cloudflared-socket-handler.js b/server/socket-handlers/cloudflared-socket-handler.js index 95dd4d80b..f7c69ed2a 100644 --- a/server/socket-handlers/cloudflared-socket-handler.js +++ b/server/socket-handlers/cloudflared-socket-handler.js @@ -1,19 +1,72 @@ -const { checkLogin } = require("../util-server"); +const { checkLogin, setSetting, setting } = require("../util-server"); +const { CloudflaredTunnel } = require("node-cloudflared-tunnel"); +const { io } = require("../server"); const prefix = "cloudflared_"; +const cloudflared = new CloudflaredTunnel(); + +let isRunning; + +cloudflared.change = (running, message) => { + io.to("cloudflared").emit(prefix + "running", running); + io.to("cloudflared").emit(prefix + "message", message); + isRunning = running; + +}; + +cloudflared.error = (errorMessage) => { + io.to("cloudflared").emit(prefix + "errorMessage", errorMessage); +}; module.exports.cloudflaredSocketHandler = (socket) => { - socket.on(prefix + "start", async (callback) => { + socket.on(prefix + "join", async () => { try { checkLogin(socket); + socket.join("cloudflared"); + io.to(socket.userID).emit(prefix + "installed", cloudflared.checkInstalled()); + io.to(socket.userID).emit(prefix + "running", isRunning); + io.to(socket.userID).emit(prefix + "token", await setting("cloudflaredTunnelToken")); + } catch (error) { } + }); - } catch (error) { - callback({ - ok: false, - msg: error.message, - }); - } + socket.on(prefix + "leave", async () => { + try { + checkLogin(socket); + socket.leave("cloudflared"); + } catch (error) { } + }); + + socket.on(prefix + "start", async (token) => { + try { + checkLogin(socket); + if (token && typeof token === "string") { + token = token.trim(); + + // try to strip out "cloudflared.exe service install" + let array = token.split(" "); + if (array.length > 1) { + for (let i = 0; i < array.length - 1; i++) { + if (array[i] === "install") { + token = array[i + 1]; + } + } + } + + await setSetting("cloudflaredTunnelToken", token); + cloudflared.token = token; + } else { + cloudflared.token = null; + } + cloudflared.start(); + } catch (error) { } + }); + + socket.on(prefix + "stop", async () => { + try { + checkLogin(socket); + cloudflared.stop(); + } catch (error) { } }); }; diff --git a/src/components/settings/ReverseProxy.vue b/src/components/settings/ReverseProxy.vue new file mode 100644 index 000000000..fe41644b6 --- /dev/null +++ b/src/components/settings/ReverseProxy.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/src/mixins/socket.js b/src/mixins/socket.js index 7d1bbea51..f2c4ff6d8 100644 --- a/src/mixins/socket.js +++ b/src/mixins/socket.js @@ -42,6 +42,13 @@ export default { statusPageList: [], connectionErrorMsg: "Cannot connect to the socket server. Reconnecting...", showReverseProxyGuide: true, + cloudflared: { + cloudflareTunnelToken: "", + installed: null, + running: false, + message: "", + errorMessage: "", + } }; }, @@ -231,6 +238,12 @@ export default { this.socket.firstConnect = false; }); + // cloudflared + socket.on("cloudflared_installed", (res) => this.cloudflared.installed = res); + socket.on("cloudflared_running", (res) => this.cloudflared.running = res); + socket.on("cloudflared_message", (res) => this.cloudflared.message = res); + socket.on("cloudflared_errorMessage", (res) => this.cloudflared.errorMessage = res); + socket.on("cloudflared_token", (res) => this.cloudflared.cloudflareTunnelToken = res); }, storage() { diff --git a/src/pages/Settings.vue b/src/pages/Settings.vue index 5b54e4247..bd8ade5aa 100644 --- a/src/pages/Settings.vue +++ b/src/pages/Settings.vue @@ -75,6 +75,9 @@ export default { notifications: { title: this.$t("Notifications"), }, + "reverse-proxy": { + title: this.$t("Reverse Proxy"), + }, "monitor-history": { title: this.$t("Monitor History"), }, diff --git a/src/router.js b/src/router.js index f59192d3e..7ab759397 100644 --- a/src/router.js +++ b/src/router.js @@ -14,6 +14,7 @@ import Entry from "./pages/Entry.vue"; import Appearance from "./components/settings/Appearance.vue"; import General from "./components/settings/General.vue"; import Notifications from "./components/settings/Notifications.vue"; +import ReverseProxy from "./components/settings/ReverseProxy.vue"; import MonitorHistory from "./components/settings/MonitorHistory.vue"; import Security from "./components/settings/Security.vue"; import Backup from "./components/settings/Backup.vue"; @@ -83,6 +84,10 @@ const routes = [ path: "notifications", component: Notifications, }, + { + path: "reverse-proxy", + component: ReverseProxy, + }, { path: "monitor-history", component: MonitorHistory,