From 47ea989bbd3a3e38838e2a17deda2d29c5fb2fb4 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Thu, 4 Dec 2025 15:20:47 +0100 Subject: [PATCH] Reduce connect timeout for tunnel for known instance metadata hosts --- .../src/registryProxy/tunnelRequestHandler.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/packages/safe-chain/src/registryProxy/tunnelRequestHandler.js b/packages/safe-chain/src/registryProxy/tunnelRequestHandler.js index 4b756d7..4a08d4b 100644 --- a/packages/safe-chain/src/registryProxy/tunnelRequestHandler.js +++ b/packages/safe-chain/src/registryProxy/tunnelRequestHandler.js @@ -1,6 +1,9 @@ import * as net from "net"; import { ui } from "../environment/userInteraction.js"; +/** @type {string[]} */ +let timedoutEndpoints = []; + /** * @param {import("http").IncomingMessage} req * @param {import("http").ServerResponse} clientSocket @@ -38,6 +41,14 @@ export function tunnelRequest(req, clientSocket, head) { function tunnelRequestToDestination(req, clientSocket, head) { const { port, hostname } = new URL(`http://${req.url}`); + 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}` + ); + return; + } + const serverSocket = net.connect( Number.parseInt(port) || 443, hostname, @@ -49,6 +60,16 @@ function tunnelRequestToDestination(req, clientSocket, head) { } ); + 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` + ); + clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n"); + }); + clientSocket.on("error", () => { // This can happen if the client TCP socket sends RST instead of FIN. // Not subscribing to 'error' event will cause node to throw and crash. @@ -145,3 +166,16 @@ function tunnelRequestViaProxy(req, clientSocket, head, proxyUrl) { } }); } + +const imdsEndpoints = [ + "metadata.google.internal", + "metadata.goog", + "169.254.169.254", + "192.0.2.1", +]; +function getConnectTimeout(/** @type {string} */ host) { + if (imdsEndpoints.includes(host)) { + return 3000; + } + return 30000; +}