[英]SFTP through HTTP proxy using ssh2-sftp-client library in Node.js
我需要使用 Node.js 库ssh2-sftp-client传输文件。 我的问题是我需要通过 HTTP 代理连接。 该文档有一个 SOCKS 代理的步骤。 我想知道如何使用 HTTP 代理来实现这一点。
我的版本基于您链接中的解决方案。 所有学分 go 到https://github.com/lmdc45
import {Injectable, Logger} from '@nestjs/common';
import * as Client from 'ssh2-sftp-client'
import * as fs from "fs";
import {ConfigService} from "@nestjs/config";
import * as http from "http";
import {SocksClient} from "socks";
import {Socket} from "net";
import {SocksClientOptions} from "socks/typings/common/constants";
export type SftpProxyConfig = { targetHost: string, targetPort: number, proxyType: 'http' | 'socks4' | 'socks5', proxyHost: string, proxyPort: number }
@Injectable()
export class SftpService {
private readonly logger = new Logger(SftpService.name);
constructor(
private readonly configService: ConfigService
) {}
async doSftpAction(
connectionOptions?: Client.ConnectOptions
) {
const sftp = new Client();
const connectionInfo = connectionOptions ? connectionOptions : await this.getSFTPConnectionInfo();
let sftpWrapper;
try {
sftpWrapper = await sftp.connect(connectionInfo);
// Here comes your code
} catch (error) {
this.logger.error(error.message, error);
throw new Error(error.message);
} finally {
if (sftpWrapper) {
await sftp.end();
}
}
}
private async getSFTPConnectionInfo(): Promise<Client.ConnectOptions> {
const host = this.configService.get<string>('SFTP_HOST');
const port = this.configService.get<number>('SFTP_PORT');
const connectionOptions: Client.ConnectOptions = {host, port};
const username = this.configService.get<string>('SFTP_USER');
const password = this.configService.get<string>('SFTP_PASSWORD');
const privateKey = this.configService.get<string>('SFTP_SSH_KEY');
const passphrase = this.configService.get<string>('SFTP_SSH_PASSPHRASE');
const proxyHost = this.configService.get<string>('SFTP_PROXY_HOST');
const proxyPort = this.configService.get<number>('SFTP_PROXY_PORT');
const proxyType = this.configService.get<'http' | 'socks4' | 'socks5'>('SFTP_PROXY_TYPE')
const debug = this.configService.get('SFTP_DEBUG_LOG') || false;
if (username)
connectionOptions.username = username;
if (password)
connectionOptions.password = password;
else if (privateKey) {
connectionOptions.privateKey = fs.readFileSync(this.configService.get<string>('SFTP_SSH_KEY'));
if (passphrase)
connectionOptions.passphrase = passphrase;
}
if (proxyHost && proxyPort && proxyType)
connectionOptions.sock = await this.getProxy({
targetHost: host,
targetPort: port,
proxyHost,
proxyPort,
proxyType
});
connectionOptions.debug = JSON.parse(debug) ? information => this.logger.log(information) : undefined;
return connectionOptions;
}
public async getProxy(config: SftpProxyConfig): Promise<NodeJS.ReadableStream> {
return (config.proxyType === 'http' ?
await this.getHttpProxy(config) :
await this.getSocksProxy(config)) as NodeJS.ReadableStream;
}
private async getHttpProxy(config: SftpProxyConfig):Promise<Socket>{
// Make a request to a tunneling proxy
const res = new Promise<Socket>((resolve, reject) => {
const options = {
port: config.proxyPort,
host: config.proxyHost,
method: 'CONNECT',
path: `${config.targetHost}:${config.targetPort}`
};
const req = http.request(options);
req.end();
req.on('connect', (res, socket, head) => {
this.logger.log(`Status Code: ${res.statusCode}`);
resolve(socket);
});
});
return res;
}
private async getSocksProxy(config: SftpProxyConfig): Promise<Socket> {
const options = {
proxy: {
host: config.proxyHost, // ipv4 or ipv6 or hostname
port: config.proxyPort,
type: config.proxyType === 'socks4' ? 4 : 5 // Proxy version (4 or 5)
},
command: 'connect', // SOCKS command (createConnection factory function only supports the connect command)
destination: {
host: config.targetHost,
port: config.targetPort
}
};
const info = await SocksClient.createConnection(options as SocksClientOptions);
return info.socket;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.