Skip to content

Instantly share code, notes, and snippets.

@eirikb
Last active October 25, 2021 18:41
Show Gist options
  • Save eirikb/05c9937f013c002abb15639f3543b9e7 to your computer and use it in GitHub Desktop.
Save eirikb/05c9937f013c002abb15639f3543b9e7 to your computer and use it in GitHub Desktop.
Insecureproxy: Client -> [http] -> Insecureproxy -> [https] -> Proxy -> [https] -> Web
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