From ee347dd3dcd3c98d634611ad0e40133e48d3eae7 Mon Sep 17 00:00:00 2001 From: Lea Date: Mon, 19 Dec 2022 18:05:16 +0100 Subject: [PATCH 1/3] feat: dockerize image proxy --- docker-compose.yml | 12 ++++++++++++ p/Dockerfile | 7 +++++++ 2 files changed, 19 insertions(+) create mode 100644 docker-compose.yml create mode 100644 p/Dockerfile diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..6daee78f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: '3.1' + +# TODO: Dockerize the other services + +services: + proxy: + build: + context: . + dockerfile: p/Dockerfile + restart: unless-stopped + ports: + - 3000:3000 diff --git a/p/Dockerfile b/p/Dockerfile new file mode 100644 index 00000000..05132ff4 --- /dev/null +++ b/p/Dockerfile @@ -0,0 +1,7 @@ +FROM node:18 +WORKDIR /app +COPY package.json /app/ +COPY p /app/p +RUN npm install --frozen-lockfile +ENV NODE_ENV production +CMD ["node", "p/server.js"] From 9dad70b2e4a67c017c504cefbdafeaad83926a73 Mon Sep 17 00:00:00 2001 From: Lea Date: Mon, 19 Dec 2022 18:22:43 +0100 Subject: [PATCH 2/3] fix: fixed several issues with proxy - proxy no longer crashes with malformed input - use URL whitelist instead of blindly proxying everything - clean up code --- p/server.js | 71 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/p/server.js b/p/server.js index a7202254..8d385b2a 100644 --- a/p/server.js +++ b/p/server.js @@ -2,48 +2,75 @@ const fs = require("fs"); const express = require("express"); const fetch = require("node-fetch"); const htmlParser = require("node-html-parser"); +const { URL } = require("url"); + +// Array of hostnames that will be proxied +const URL_WHITELIST = [ + 'i.ytimg.com', + 'yt3.googleusercontent.com', + 'cdn.glitch.global', + 'cdn.statically.io', + 'site-assets.fontawesome.com', + 'fonts.gstatic.com', + 'yt3.ggpht.com', + 'tube.kuylar.dev', + 'lh3.googleusercontent.com', + 'is4-ssl.mzstatic.com', + 'twemoji.maxcdn.com', + 'unpkg.com', +]; const app = express(); app.use(express.json()); // for parsing application/json app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded +app.use(function (req, res, next) { + console.log(`=> ${req.method} ${req.originalUrl.slice(1)}`) + next(); +}); + app.use(function (req, res, next) { res.header("Access-Control-Allow-Origin", "*"); next(); }); -let Proxy = async (req, res) => { - const url = "https://" + req.originalUrl.slice(10); - let f = await fetch(url, { - method: req.method, - }); - if (false && f.headers.get("content-type").includes("html")) { - const body = await f.text(); - if (false && !htmlParser.valid(body)) { - console.warn(`[ERROR] Invalid HTML at ${url}`); - f.body.pipe(res); - return; +/** + * @param {express.Request} req + * @param {express.Response} res + */ +const proxy = async (req, res) => { + try { + let url; + + try { + url = new URL("https://" + req.originalUrl.slice(1)); + } catch(e) { + console.log('==> Cannot parse URL: ' + e); + return res.status(400).send('Malformed URL'); } - const root = htmlParser.parse(body); - let html = root.childNodes.filter( - (x) => x.tagName && x.tagName.toLowerCase() == "html" - )[0]; - if (!html) { - console.warn(`[ERROR] No at ${url}`); - res.send(body); + if (!URL_WHITELIST.includes(url.host)) { + console.log(`==> Refusing to proxy host ${url.host}`); + res.status(401).send(`Hostname '${url.host}' is not permitted`); return; } - res.send(html.toString()); - } else { + console.log(`==> Proxying request`); + + let f = await fetch(url, { + method: req.method, + }); + f.body.pipe(res); + } catch(e) { + console.log(`==> Error: ${e}`); + res.status(500).send('Internal server error'); } }; const listener = (req, res) => { - Proxy(req, res); + proxy(req, res); }; app.get("/", (req, res) => @@ -52,4 +79,4 @@ app.get("/", (req, res) => app.all("/*", listener); -app.listen(3000, () => {}); +app.listen(3000, () => console.log('Listening on 0.0.0.0:3000')); From c6fa9c9933c8abc7cfd4518ce543a21798cae707 Mon Sep 17 00:00:00 2001 From: Lea Date: Mon, 19 Dec 2022 19:12:23 +0100 Subject: [PATCH 3/3] chore: remove unneeded imports --- p/server.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/p/server.js b/p/server.js index 8d385b2a..7529358e 100644 --- a/p/server.js +++ b/p/server.js @@ -1,7 +1,5 @@ -const fs = require("fs"); const express = require("express"); const fetch = require("node-fetch"); -const htmlParser = require("node-html-parser"); const { URL } = require("url"); // Array of hostnames that will be proxied