UNPKG

@zkp2p/reclaim-witness-sdk

Version:

<div> <div> <img src="https://raw.githubusercontent.com/reclaimprotocol/.github/main/assets/banners/Attestor-Core.png" /> </div> </div>

175 lines 13.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeTcpTunnel = void 0; const https_proxy_agent_1 = require("https-proxy-agent"); const net_1 = require("net"); const config_1 = require("../../config"); const dns_1 = require("../../server/utils/dns"); const iso_1 = require("../../server/utils/iso"); const utils_1 = require("../../utils"); const env_1 = require("../../utils/env"); const HTTPS_PROXY_URL = (0, env_1.getEnvVariable)('HTTPS_PROXY_URL'); /** * Builds a TCP tunnel to the given host and port. * If a geolocation is provided -- an HTTPS proxy is used * to connect to the host. * * HTTPS proxy essentially creates an opaque tunnel to the * host using the CONNECT method. Any data can be sent through * this tunnel to the end host. * https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT * * The tunnel also retains a transcript of all messages sent and received. */ const makeTcpTunnel = async ({ onClose, onMessage, logger, ...opts }) => { const transcript = []; const socket = await connectTcp({ ...opts, logger }); let closed = false; socket.on('data', message => { if (closed) { logger.warn('socket is closed, dropping message'); return; } onMessage === null || onMessage === void 0 ? void 0 : onMessage(message); transcript.push({ sender: 'server', message }); }); socket.once('error', onSocketClose); socket.once('close', () => onSocketClose(undefined)); return { socket, transcript, createRequest: opts, async write(data) { transcript.push({ sender: 'client', message: data }); await new Promise((resolve, reject) => { socket.write(data, err => { if (err) { reject(err); } else { resolve(); } }); }); }, close(err) { if (closed) { return; } socket.destroy(err); } }; function onSocketClose(err) { if (closed) { return; } logger.debug({ err }, 'closing socket'); closed = true; onClose === null || onClose === void 0 ? void 0 : onClose(err); onClose = undefined; } }; exports.makeTcpTunnel = makeTcpTunnel; async function connectTcp({ host, port, geoLocation, logger }) { let connectTimeout; let socket; try { await new Promise(async (resolve, reject) => { try { // add a timeout to ensure the connection doesn't hang // and cause our gateway to send out a 504 connectTimeout = setTimeout(() => reject(new utils_1.AttestorError('ERROR_NETWORK_ERROR', 'Server connection timed out')), config_1.CONNECTION_TIMEOUT_MS); socket = await getSocket({ host, port, geoLocation, logger }); socket.once('connect', resolve); socket.once('error', reject); socket.once('end', () => (reject(new utils_1.AttestorError('ERROR_NETWORK_ERROR', 'connection closed')))); } catch (err) { reject(err); } }); logger.debug({ addr: `${host}:${port}` }, 'connected'); return socket; } catch (err) { socket === null || socket === void 0 ? void 0 : socket.end(); throw err; } finally { clearTimeout(connectTimeout); } } async function getSocket(opts) { var _a; const { logger } = opts; try { return await _getSocket(opts); } catch (err) { // see if the proxy is blocking the connection // due to their own arbitrary rules, // if so -- we resolve hostname first & // connect directly via address to // avoid proxy knowing which host we're connecting to if (!(err instanceof utils_1.AttestorError) || ((_a = err.data) === null || _a === void 0 ? void 0 : _a.code) !== 403) { throw err; } const addrs = await (0, dns_1.resolveHostnames)(opts.host); logger.info({ addrs, host: opts.host }, 'failed to connect due to restricted IP, trying via raw addr'); for (const addr of addrs) { try { return await _getSocket({ ...opts, host: addr }); } catch (err) { logger.error({ addr, err }, 'failed to connect to host'); } } throw err; } } async function _getSocket({ host, port, geoLocation, logger }) { const socket = new net_1.Socket(); if (geoLocation && !HTTPS_PROXY_URL) { logger.warn({ geoLocation }, 'geoLocation provided but no proxy URL found'); geoLocation = ''; } if (!geoLocation) { socket.connect({ host, port, }); return socket; } if (!(0, iso_1.isValidCountryCode)(geoLocation)) { throw utils_1.AttestorError.badRequest(`Geolocation "${geoLocation}" is invalid. Must be 2 letter ISO country code`, { geoLocation }); } const agentUrl = HTTPS_PROXY_URL.replace('{{geoLocation}}', (geoLocation === null || geoLocation === void 0 ? void 0 : geoLocation.toLowerCase()) || ''); const agent = new https_proxy_agent_1.HttpsProxyAgent(agentUrl); const waitForProxyRes = new Promise(resolve => { // @ts-ignore socket.once('proxyConnect', resolve); }); const proxySocket = await agent.connect( // ignore, because https-proxy-agent // expects an http request object // @ts-ignore socket, { host, port, timeout: config_1.CONNECTION_TIMEOUT_MS }); const res = await waitForProxyRes; if (res.statusCode !== 200) { logger.error({ geoLocation, res }, 'Proxy geo location failed'); throw new utils_1.AttestorError('ERROR_PROXY_ERROR', `Proxy via geo location "${geoLocation}" failed with status code: ${res.statusCode}, message: ${res.statusText}`, { code: res.statusCode, message: res.statusText, }); } process.nextTick(() => { // ensure connect event is emitted // so it can be captured by the caller proxySocket.emit('connect'); }); return proxySocket; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFrZS10Y3AtdHVubmVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZlci90dW5uZWxzL21ha2UtdGNwLXR1bm5lbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5REFBbUQ7QUFFbkQsNkJBQTRCO0FBQzVCLHVDQUFrRDtBQUVsRCw4Q0FBdUQ7QUFDdkQsOENBQXlEO0FBR3pELHFDQUF5QztBQUN6Qyx1Q0FBOEM7QUFFOUMsTUFBTSxlQUFlLEdBQUcsSUFBQSxvQkFBYyxFQUFDLGlCQUFpQixDQUFDLENBQUE7QUFLekQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSSxNQUFNLGFBQWEsR0FBaUQsS0FBSyxFQUFDLEVBQ2hGLE9BQU8sRUFDUCxTQUFTLEVBQ1QsTUFBTSxFQUNOLEdBQUcsSUFBSSxFQUNQLEVBQUUsRUFBRTtJQUNKLE1BQU0sVUFBVSxHQUFzQyxFQUFFLENBQUE7SUFDeEQsTUFBTSxNQUFNLEdBQUcsTUFBTSxVQUFVLENBQUMsRUFBRSxHQUFHLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO0lBRXBELElBQUksTUFBTSxHQUFHLEtBQUssQ0FBQTtJQUdsQixNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsRUFBRTtRQUMzQixJQUFHLE1BQU0sRUFBRSxDQUFDO1lBQ1gsTUFBTSxDQUFDLElBQUksQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFBO1lBQ2pELE9BQU07UUFDUCxDQUFDO1FBRUQsU0FBUyxhQUFULFNBQVMsdUJBQVQsU0FBUyxDQUFHLE9BQU8sQ0FBQyxDQUFBO1FBQ3BCLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUE7SUFDL0MsQ0FBQyxDQUFDLENBQUE7SUFFRixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FBQTtJQUNuQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9B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