Add support for SOCKS4/5 proxy

pull/13/head
Kelvin Schoofs 7 years ago
parent 79d2ed9d97
commit 196a276f52

@ -4,6 +4,8 @@ import { parse as parseJsonc, ParseError } from 'jsonc-parser';
import * as path from 'path'; import * as path from 'path';
import { Client, ConnectConfig } from 'ssh2'; import { Client, ConnectConfig } from 'ssh2';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as proxy from './proxy';
import { getSession as getPuttySession } from './putty'; import { getSession as getPuttySession } from './putty';
import SSHFileSystem, { EMPTY_FILE_SYSTEM } from './sshFileSystem'; import SSHFileSystem, { EMPTY_FILE_SYSTEM } from './sshFileSystem';
import { catchingPromise, toPromise } from './toPromise'; import { catchingPromise, toPromise } from './toPromise';
@ -15,11 +17,18 @@ async function assertFs(man: Manager, uri: vscode.Uri) {
// throw new Error(`A SSH filesystem with the name '${uri.authority}' doesn't exists`); // throw new Error(`A SSH filesystem with the name '${uri.authority}' doesn't exists`);
} }
export interface ProxyConfig {
type: 'socks4' | 'socks5';
host: string;
port: number;
}
export interface FileSystemConfig extends ConnectConfig { export interface FileSystemConfig extends ConnectConfig {
name: string; name: string;
label?: string; label?: string;
root?: string; root?: string;
putty?: string | boolean; putty?: string | boolean;
proxy?: ProxyConfig;
} }
export enum ConfigStatus { export enum ConfigStatus {
@ -226,6 +235,17 @@ export class Manager implements vscode.FileSystemProvider, vscode.TreeDataProvid
} }
} }
if (config.password) config.agent = undefined; if (config.password) config.agent = undefined;
switch (config.proxy && config.proxy.type) {
case null:
case undefined:
break;
case 'socks4':
case 'socks5':
config = await proxy.socks(config);
break;
default:
return reject(new Error(`Unknown proxy method`));
}
const client = new Client(); const client = new Client();
client.on('ready', () => { client.on('ready', () => {
client.sftp((err, sftp) => { client.sftp((err, sftp) => {

@ -0,0 +1,36 @@
import * as dns from 'dns';
import { SocksClient } from 'socks';
import { FileSystemConfig } from './manager';
import { toPromise } from './toPromise';
export async function socks(config: FileSystemConfig): Promise<FileSystemConfig> {
if (!config.proxy) throw new Error(`Missing field 'config.proxy'`);
if (!config.proxy.host) throw new Error(`Missing field 'config.proxy.host'`);
if (!config.proxy.port) throw new Error(`Missing field 'config.proxy.port'`);
if (!config.proxy.type) throw new Error(`Missing field 'config.proxy.type'`);
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 toPromise<string[]>(cb => dns.resolve(config.proxy!.host, cb)))[0];
if (!ipaddress) throw new Error(`Couldn't resolve '${config.proxy.host}'`);
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,
},
});
config.sock = con.socket as NodeJS.ReadableStream;
return config;
} catch (e) {
throw new Error(`Error while connecting to the the proxy: ${e.message}`);
}
}

@ -11,6 +11,7 @@ const winreg = new Winreg({
export type NumberAsBoolean = 0 | 1; export type NumberAsBoolean = 0 | 1;
export interface PuttySession { export interface PuttySession {
[key: string]: string | number | undefined; [key: string]: string | number | undefined;
// General settings
name: string; name: string;
hostname: string; hostname: string;
protocol: string; protocol: string;
@ -19,6 +20,11 @@ export interface PuttySession {
usernamefromenvironment: NumberAsBoolean; usernamefromenvironment: NumberAsBoolean;
tryagent: NumberAsBoolean; tryagent: NumberAsBoolean;
publickeyfile?: string; publickeyfile?: string;
// Proxy settings
proxyhost?: string;
proxyport: number;
proxylocalhost: NumberAsBoolean;
proxymethod: number; // Key of ['None', 'SOCKS 4', 'SOCKS 5', 'HTTP', 'Telnet', 'Local'] // Only checked first 3
} }
function valueFromItem(item: Winreg.RegistryItem) { function valueFromItem(item: Winreg.RegistryItem) {

Loading…
Cancel
Save