From 2d0beabe9a7d51e70eb629fe7368c39b3598cef5 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:40:11 -0700 Subject: [PATCH] Enhancement: more reliable wg-easy widget by custom proxy, use password header (#3966) --- src/utils/proxy/handlers/credentialed.js | 2 + src/widgets/wgeasy/component.jsx | 6 +- src/widgets/wgeasy/proxy.js | 85 ------------------------ src/widgets/wgeasy/widget.js | 10 ++- 4 files changed, 13 insertions(+), 90 deletions(-) delete mode 100644 src/widgets/wgeasy/proxy.js diff --git a/src/utils/proxy/handlers/credentialed.js b/src/utils/proxy/handlers/credentialed.js index f09d0fe94..398220753 100644 --- a/src/utils/proxy/handlers/credentialed.js +++ b/src/utils/proxy/handlers/credentialed.js @@ -88,6 +88,8 @@ export default async function credentialedProxyHandler(req, res, map) { if (widget.key) { headers.Cookie = `authenticated=${widget.key}`; } + } else if (widget.type === "wgeasy") { + headers.Authorization = widget.password; } else { headers["X-API-Key"] = `${widget.key}`; } diff --git a/src/widgets/wgeasy/component.jsx b/src/widgets/wgeasy/component.jsx index 624002c4f..125b92bfa 100644 --- a/src/widgets/wgeasy/component.jsx +++ b/src/widgets/wgeasy/component.jsx @@ -5,14 +5,14 @@ import useWidgetAPI from "utils/proxy/use-widget-api"; export default function Component({ service }) { const { widget } = service; - const { data: infoData, error: infoError } = useWidgetAPI(widget); + const { data: infoData, error: infoError } = useWidgetAPI(widget, "client"); if (!widget.fields) { widget.fields = ["connected", "enabled", "total"]; } - if (infoError) { - return ; + if (infoError || infoData?.statusCode > 400) { + return ; } if (!infoData) { diff --git a/src/widgets/wgeasy/proxy.js b/src/widgets/wgeasy/proxy.js deleted file mode 100644 index 53c646e22..000000000 --- a/src/widgets/wgeasy/proxy.js +++ /dev/null @@ -1,85 +0,0 @@ -import cache from "memory-cache"; - -import getServiceWidget from "utils/config/service-helpers"; -import { formatApiCall } from "utils/proxy/api-helpers"; -import { httpProxy } from "utils/proxy/http"; -import widgets from "widgets/widgets"; -import createLogger from "utils/logger"; - -const proxyName = "wgeasyProxyHandler"; -const logger = createLogger(proxyName); -const sessionSIDCacheKey = `${proxyName}__sessionSID`; - -async function login(widget, service) { - const url = formatApiCall(widgets[widget.type].api, { ...widget, endpoint: "session" }); - const [, , , responseHeaders] = await httpProxy(url, { - method: "POST", - body: JSON.stringify({ password: widget.password }), - headers: { - "Content-Type": "application/json", - }, - }); - - try { - let connectSidCookie = responseHeaders["set-cookie"]; - if (!connectSidCookie) { - const sid = cache.get(`${sessionSIDCacheKey}.${service}`); - if (sid) { - return sid; - } - } - connectSidCookie = connectSidCookie - .find((cookie) => cookie.startsWith("connect.sid=")) - .split(";")[0] - .replace("connect.sid=", ""); - cache.put(`${sessionSIDCacheKey}.${service}`, connectSidCookie); - return connectSidCookie; - } catch (e) { - logger.error(`Error logging into wg-easy, error: ${e}`); - cache.del(`${sessionSIDCacheKey}.${service}`); - return null; - } -} - -export default async function wgeasyProxyHandler(req, res) { - const { group, service } = req.query; - - if (group && service) { - const widget = await getServiceWidget(group, service); - - if (!widgets?.[widget.type]?.api) { - return res.status(403).json({ error: "Service does not support API calls" }); - } - - if (widget) { - let sid = cache.get(`${sessionSIDCacheKey}.${service}`); - if (!sid) { - sid = await login(widget, service); - if (!sid) { - return res.status(500).json({ error: "Failed to authenticate with Wg-Easy" }); - } - } - const [, , data] = await httpProxy( - formatApiCall(widgets[widget.type].api, { ...widget, endpoint: "wireguard/client" }), - { - headers: { - "Content-Type": "application/json", - Cookie: `connect.sid=${sid}`, - }, - }, - ); - - const parsedData = JSON.parse(data); - - if (parsedData.statusCode > 400) { - return res - .status(parsedData.statusCode) - .json({ error: { message: "Error communicating with Wg-Easy", data: parsedData } }); - } - - return res.json(parsedData); - } - } - - return res.status(400).json({ error: "Invalid proxy service type" }); -} diff --git a/src/widgets/wgeasy/widget.js b/src/widgets/wgeasy/widget.js index 7f7d69d7e..c85c26920 100644 --- a/src/widgets/wgeasy/widget.js +++ b/src/widgets/wgeasy/widget.js @@ -1,8 +1,14 @@ -import wgeasyProxyHandler from "./proxy"; +import credentialedProxyHandler from "utils/proxy/handlers/credentialed"; const widget = { api: "{url}/api/{endpoint}", - proxyHandler: wgeasyProxyHandler, + proxyHandler: credentialedProxyHandler, + + mappings: { + client: { + endpoint: "wireguard/client", + }, + }, }; export default widget;