You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vscode-sshfs/src/proxy.ts

76 lines
2.8 KiB

import * as dns from 'dns';
import { request } from 'http';
import { SocksClient } from 'socks';
import type { FileSystemConfig } from './fileSystemConfig';
import { Logging } from './logging';
import { toPromise, validatePort } from './utils';
async function resolveHostname(hostname: string): Promise<string> {
return toPromise<string>(cb => dns.lookup(hostname, cb)).then((ip) => {
Logging.debug(`Resolved hostname "${hostname}" to: ${ip}`);
return ip;
});
}
function validateConfig(config: FileSystemConfig) {
if (!config.proxy) throw new Error(`Missing field 'config.proxy'`);
if (!config.proxy.type) throw new Error(`Missing field 'config.proxy.type'`);
if (!config.proxy.host) throw new Error(`Missing field 'config.proxy.host'`);
if (!config.proxy.port) throw new Error(`Missing field 'config.proxy.port'`);
config.proxy.port = validatePort(config.proxy.port);
}
export async function socks(config: FileSystemConfig): Promise<NodeJS.ReadableStream> {
Logging.info(`Creating socks proxy connection for ${config.name}`);
validateConfig(config);
if (config.proxy!.type !== 'socks4' && config.proxy!.type !== 'socks5') {
throw new Error(`Expected 'config.proxy.type' to be 'socks4' or 'socks5'`);
}
try {
const ipaddress = (await resolveHostname(config.proxy!.host));
if (!ipaddress) throw new Error(`Couldn't resolve '${config.proxy!.host}'`);
Logging.debug(`\tConnecting to ${config.host}:${config.port} over ${config.proxy!.type} proxy at ${ipaddress}:${config.proxy!.port}`);
const con = await SocksClient.createConnection({
command: 'connect',
destination: {
host: config.host!,
port: config.port!,
},
proxy: {
ipaddress,
port: config.proxy!.port,
type: config.proxy!.type === 'socks4' ? 4 : 5,
},
});
return con.socket as NodeJS.ReadableStream;
} catch (e) {
throw new Error(`Error while connecting to the the proxy: ${e.message}`);
}
}
export function http(config: FileSystemConfig): Promise<NodeJS.ReadableStream> {
Logging.info(`Creating http proxy connection for ${config.name}`);
validateConfig(config);
return new Promise<NodeJS.ReadableStream>((resolve, reject) => {
if (config.proxy!.type !== 'http') {
reject(new Error(`Expected config.proxy.type' to be 'http'`));
}
try {
Logging.debug(`\tConnecting to ${config.host}:${config.port} over http proxy at ${config.proxy!.host}:${config.proxy!.port}`);
const req = request({
port: config.proxy!.port,
hostname: config.proxy!.host,
method: 'CONNECT',
path: `${config.host}:${config.port}`,
});
req.end();
req.on('connect', (res, socket) => {
resolve(socket as NodeJS.ReadableStream);
});
} catch (e) {
reject(new Error(`Error while connecting to the the proxy: ${e.message}`));
}
});
}