mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Add tests and clarifying comments
This commit is contained in:
parent
22b93e91f6
commit
57a0e88fa4
4 changed files with 188 additions and 32 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import * as net from "net";
|
||||
import { ui } from "../environment/userInteraction.js";
|
||||
import { isImdsEndpoint } from "./isImdsEndpoint.js";
|
||||
|
||||
/** @type {string[]} */
|
||||
let timedoutEndpoints = [];
|
||||
|
|
@ -40,12 +41,19 @@ export function tunnelRequest(req, clientSocket, head) {
|
|||
*/
|
||||
function tunnelRequestToDestination(req, clientSocket, head) {
|
||||
const { port, hostname } = new URL(`http://${req.url}`);
|
||||
const isImds = isImdsEndpoint(hostname);
|
||||
|
||||
if (timedoutEndpoints.includes(hostname)) {
|
||||
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
|
||||
ui.writeError(
|
||||
`Safe-chain: Closing connection because previously timedout connect to ${hostname}`
|
||||
);
|
||||
if (isImds) {
|
||||
ui.writeVerbose(
|
||||
`Safe-chain: Closing connection because previously timedout connect to ${hostname}`
|
||||
);
|
||||
} else {
|
||||
ui.writeError(
|
||||
`Safe-chain: Closing connection because previously timedout connect to ${hostname}`
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -60,13 +68,24 @@ function tunnelRequestToDestination(req, clientSocket, head) {
|
|||
}
|
||||
);
|
||||
|
||||
// Set explicit connection timeout to avoid waiting for OS default (~2 minutes).
|
||||
// IMDS endpoints get shorter timeout (3s) since they're commonly unreachable outside cloud environments.
|
||||
const connectTimeout = getConnectTimeout(hostname);
|
||||
serverSocket.setTimeout(connectTimeout);
|
||||
|
||||
serverSocket.on("timeout", () => {
|
||||
timedoutEndpoints.push(hostname);
|
||||
ui.writeError(
|
||||
`Safe-chain: connect to ${hostname}:${port} timed out after ${connectTimeout}ms`
|
||||
);
|
||||
// Suppress error logging for IMDS endpoints - timeouts are expected when not in cloud
|
||||
if (isImdsEndpoint(hostname)) {
|
||||
ui.writeVerbose(
|
||||
`Safe-chain: connect to ${hostname}:${port || 443} timed out after ${connectTimeout}ms`
|
||||
);
|
||||
} else {
|
||||
ui.writeError(
|
||||
`Safe-chain: connect to ${hostname}:${port || 443} timed out after ${connectTimeout}ms`
|
||||
);
|
||||
}
|
||||
serverSocket.destroy(); // Clean up socket to prevent event loop hanging
|
||||
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
|
||||
});
|
||||
|
||||
|
|
@ -79,9 +98,15 @@ function tunnelRequestToDestination(req, clientSocket, head) {
|
|||
});
|
||||
|
||||
serverSocket.on("error", (err) => {
|
||||
ui.writeError(
|
||||
`Safe-chain: error connecting to ${hostname}:${port} - ${err.message}`
|
||||
);
|
||||
if (isImdsEndpoint(hostname)) {
|
||||
ui.writeVerbose(
|
||||
`Safe-chain: error connecting to ${hostname}:${port} - ${err.message}`
|
||||
);
|
||||
} else {
|
||||
ui.writeError(
|
||||
`Safe-chain: error connecting to ${hostname}:${port} - ${err.message}`
|
||||
);
|
||||
}
|
||||
if (clientSocket.writable) {
|
||||
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
|
||||
}
|
||||
|
|
@ -167,13 +192,13 @@ function tunnelRequestViaProxy(req, clientSocket, head, proxyUrl) {
|
|||
});
|
||||
}
|
||||
|
||||
const imdsEndpoints = [
|
||||
"metadata.google.internal",
|
||||
"metadata.goog",
|
||||
"169.254.169.254",
|
||||
];
|
||||
/**
|
||||
* Returns appropriate connection timeout for a host.
|
||||
* - IMDS endpoints: 3s (fail fast when outside cloud, reduce 5min delay to ~20s)
|
||||
* - Other endpoints: 30s (allow for slow networks while preventing indefinite hangs)
|
||||
*/
|
||||
function getConnectTimeout(/** @type {string} */ host) {
|
||||
if (imdsEndpoints.includes(host)) {
|
||||
if (isImdsEndpoint(host)) {
|
||||
return 3000;
|
||||
}
|
||||
return 30000;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue