Last active
October 25, 2021 18:41
-
-
Save eirikb/05c9937f013c002abb15639f3543b9e7 to your computer and use it in GitHub Desktop.
Insecureproxy: Client -> [http] -> Insecureproxy -> [https] -> Proxy -> [https] -> Web
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const http = require("http"); | |
const https = require("https"); | |
const fs = require("fs"); | |
const auth = `Basic ${Buffer.from( | |
process.env.PROXY_USER + ":" + process.env.PROXY_PASS | |
).toString("base64")}`; | |
function proxy(id, url, method, headers, data, origRes, withCa) { | |
const parts = url.split("/").slice(2); | |
return new Promise((resolve, reject) => { | |
http | |
.request({ | |
host: process.env.PROXY_HOST, | |
port: process.env.PROXY_PORT, | |
method: "CONNECT", | |
path: `${parts[0]}:443`, | |
headers: { | |
"Proxy-Authorization": auth, | |
}, | |
}) | |
.on("connect", (res, socket) => { | |
if (res.statusCode !== 200) { | |
reject(`Proxy fail: ${res.statusCode} ${res.statusMessage}`); | |
return; | |
} | |
const agent = new https.Agent({ socket }); | |
const req = https | |
.request( | |
{ | |
method, | |
headers, | |
host: parts[0], | |
path: "/" + parts.slice(1).join("/"), | |
...(withCa | |
? { | |
ca: fs.readFileSync(process.env.PROXY_CA_PATH), | |
} | |
: {}), | |
agent, | |
}, | |
(res) => { | |
if (res.headers.location) { | |
res.headers.location = res.headers.location.replace( | |
/^https:/, | |
"http:" | |
); | |
} | |
console.log(id, "Result:", res.statusCode, res.statusMessage); | |
origRes.writeHead(res.statusCode, res.headers); | |
origRes.headers = res.headers; | |
const convertResult = process.argv.some( | |
(arg) => arg === "-convert-result" | |
); | |
const textIsh = | |
convertResult && | |
/(text|json)/i.test(res.headers["content-type"]); | |
res.on("data", (chunk) => { | |
if (textIsh) { | |
origRes.write( | |
chunk.toString().replace(/https:\/\//gi, "http://") | |
); | |
} else { | |
origRes.write(chunk); | |
} | |
}); | |
res.on("error", reject); | |
res.on("end", () => resolve()); | |
} | |
) | |
.on("error", reject); | |
if (data) { | |
req.write(data, () => req.end()); | |
} else { | |
req.end(); | |
} | |
}) | |
.on("error", reject) | |
.end(); | |
}); | |
} | |
let id = 0; | |
http | |
.createServer((req, res) => { | |
id++; | |
const url = req.url; | |
const method = req.method; | |
const headers = req.headers; | |
console.log(id, method, url); | |
const chunks = []; | |
req.on("data", (chunk) => chunks.push(chunk)); | |
req.on("end", () => { | |
const data = chunks.length > 0 ? Buffer.concat(chunks) : null; | |
if (data) console.log(id, "data length", data.length); | |
proxy(id, url, method, headers, data, res, true) | |
.catch((err) => { | |
console.log(id, "error:", err.message); | |
return proxy(id, url, method, headers, data, res, false); | |
}) | |
.catch((err) => { | |
console.log(id, "final error:", err); | |
res.end(err.toString()); | |
}) | |
.finally(() => { | |
console.log(id, "OK!"); | |
res.end(); | |
}); | |
}); | |
}) | |
.listen(6660, () => console.log("Listening on 6660")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment