mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 20:20:49 +00:00
Add upstream proxy support
This commit is contained in:
parent
60543308f4
commit
a6980d5108
4 changed files with 76 additions and 0 deletions
1
package-lock.json
generated
1
package-lock.json
generated
|
|
@ -4886,6 +4886,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abbrev": "3.0.1",
|
"abbrev": "3.0.1",
|
||||||
"chalk": "5.4.1",
|
"chalk": "5.4.1",
|
||||||
|
"https-proxy-agent": "7.0.6",
|
||||||
"make-fetch-happen": "14.0.3",
|
"make-fetch-happen": "14.0.3",
|
||||||
"node-forge": "1.3.1",
|
"node-forge": "1.3.1",
|
||||||
"npm-registry-fetch": "18.0.2",
|
"npm-registry-fetch": "18.0.2",
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abbrev": "3.0.1",
|
"abbrev": "3.0.1",
|
||||||
"chalk": "5.4.1",
|
"chalk": "5.4.1",
|
||||||
|
"https-proxy-agent": "7.0.6",
|
||||||
"make-fetch-happen": "14.0.3",
|
"make-fetch-happen": "14.0.3",
|
||||||
"node-forge": "1.3.1",
|
"node-forge": "1.3.1",
|
||||||
"npm-registry-fetch": "18.0.2",
|
"npm-registry-fetch": "18.0.2",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import https from "https";
|
import https from "https";
|
||||||
import { generateCertForHost } from "./certUtils.js";
|
import { generateCertForHost } from "./certUtils.js";
|
||||||
|
import { HttpsProxyAgent } from "https-proxy-agent";
|
||||||
|
|
||||||
export function mitmConnect(req, clientSocket, isAllowed) {
|
export function mitmConnect(req, clientSocket, isAllowed) {
|
||||||
const { hostname } = new URL(`http://${req.url}`);
|
const { hostname } = new URL(`http://${req.url}`);
|
||||||
|
|
@ -75,6 +76,11 @@ function createProxyRequest(hostname, req, res) {
|
||||||
|
|
||||||
delete options.headers.host;
|
delete options.headers.host;
|
||||||
|
|
||||||
|
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
|
||||||
|
if (httpsProxy) {
|
||||||
|
options.agent = new HttpsProxyAgent(httpsProxy);
|
||||||
|
}
|
||||||
|
|
||||||
const proxyReq = https.request(options, (proxyRes) => {
|
const proxyReq = https.request(options, (proxyRes) => {
|
||||||
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
||||||
proxyRes.pipe(res);
|
proxyRes.pipe(res);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,16 @@ import * as net from "net";
|
||||||
import { ui } from "../environment/userInteraction.js";
|
import { ui } from "../environment/userInteraction.js";
|
||||||
|
|
||||||
export function tunnelRequest(req, clientSocket, head) {
|
export function tunnelRequest(req, clientSocket, head) {
|
||||||
|
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
|
||||||
|
|
||||||
|
if (httpsProxy) {
|
||||||
|
tunnelRequestViaProxy(req, clientSocket, head, httpsProxy);
|
||||||
|
} else {
|
||||||
|
tunnelRequestToDestination(req, clientSocket, head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tunnelRequestToDestination(req, clientSocket, head) {
|
||||||
const { port, hostname } = new URL(`http://${req.url}`);
|
const { port, hostname } = new URL(`http://${req.url}`);
|
||||||
|
|
||||||
const serverSocket = net.connect(port || 443, hostname, () => {
|
const serverSocket = net.connect(port || 443, hostname, () => {
|
||||||
|
|
@ -18,3 +28,61 @@ export function tunnelRequest(req, clientSocket, head) {
|
||||||
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
|
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tunnelRequestViaProxy(req, clientSocket, head, proxyUrl) {
|
||||||
|
const { port, hostname } = new URL(`http://${req.url}`);
|
||||||
|
const proxy = new URL(proxyUrl);
|
||||||
|
|
||||||
|
// Connect to proxy server
|
||||||
|
const proxySocket = net.connect({
|
||||||
|
host: proxy.hostname,
|
||||||
|
port: proxy.port,
|
||||||
|
});
|
||||||
|
|
||||||
|
proxySocket.on("connect", () => {
|
||||||
|
// Send CONNECT request to proxy
|
||||||
|
const connectRequest = [
|
||||||
|
`CONNECT ${hostname}:${port || 443} HTTP/1.1`,
|
||||||
|
`Host: ${hostname}:${port || 443}`,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\r\n");
|
||||||
|
|
||||||
|
proxySocket.write(connectRequest);
|
||||||
|
});
|
||||||
|
|
||||||
|
let isConnected = false;
|
||||||
|
proxySocket.once("data", (data) => {
|
||||||
|
const response = data.toString();
|
||||||
|
|
||||||
|
// Check if CONNECT succeeded (HTTP/1.1 200)
|
||||||
|
if (response.startsWith("HTTP/1.1 200")) {
|
||||||
|
isConnected = true;
|
||||||
|
clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
|
||||||
|
proxySocket.write(head);
|
||||||
|
proxySocket.pipe(clientSocket);
|
||||||
|
clientSocket.pipe(proxySocket);
|
||||||
|
} else {
|
||||||
|
ui.writeError(
|
||||||
|
`Safe-chain: proxy CONNECT failed: ${response.split("\r\n")[0]}`
|
||||||
|
);
|
||||||
|
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
|
||||||
|
proxySocket.end();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
proxySocket.on("error", (err) => {
|
||||||
|
if (!isConnected) {
|
||||||
|
ui.writeError(
|
||||||
|
`Safe-chain: error connecting to proxy ${proxy.hostname}:${
|
||||||
|
proxy.port || 8080
|
||||||
|
} - ${err.message}`
|
||||||
|
);
|
||||||
|
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
clientSocket.on("error", () => {
|
||||||
|
proxySocket.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue