perf: 上传到主机,支持socks代理

pull/199/head
xiaojunnuo 2024-09-29 11:50:59 +08:00
parent df88a936a5
commit d91026dc4f
4 changed files with 56 additions and 3 deletions

View File

@ -70,6 +70,8 @@
"querystring": "^0.2.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^5.0.5",
"socks": "^2.8.3",
"socks-proxy-agent": "^8.0.4",
"ssh2": "^1.15.0",
"strip-ansi": "^7.1.0",
"svg-captcha": "^1.4.0",

View File

@ -60,7 +60,7 @@ export class AccessService extends BaseService<AccessEntity> implements IAccessS
const value = json[key];
const accessInputDefine = accessDefine.input[key];
if (!accessInputDefine) {
throw new ValidateException(`授权类型${accessType}不存在字段${key}`);
continue;
}
if (!accessInputDefine.encrypt || !value || typeof value !== 'string') {
//定义无需加密、value为空、不是字符串 这些不需要加密

View File

@ -18,7 +18,7 @@ export class SshAccess implements IAccess, ConnectConfig {
host!: string;
@AccessInput({
title: '端口',
value: '22',
value: 22,
component: {
name: 'a-input-number',
placeholder: '22',
@ -64,6 +64,17 @@ export class SshAccess implements IAccess, ConnectConfig {
})
passphrase!: string;
@AccessInput({
title: '代理',
helper: '代理配置格式socks5://$username:$password@$host:$port',
component: {
name: 'a-input',
vModel: 'value',
},
encrypt: false,
})
socksProxy!: string;
@AccessInput({
title: '是否Windows',
helper: '如果是Windows主机请勾选此项',

View File

@ -5,10 +5,13 @@ import * as _ from 'lodash-es';
import { ILogger } from '@certd/pipeline';
import { SshAccess } from '../access/index.js';
import stripAnsi from 'strip-ansi';
import { SocksClient } from 'socks';
import { SocksProxy, SocksProxyType } from 'socks/typings/common/constants.js';
export class AsyncSsh2Client {
conn: ssh2.Client;
logger: ILogger;
connConf: ssh2.ConnectConfig;
connConf: SshAccess & ssh2.ConnectConfig;
windows = false;
encoding: string;
constructor(connConf: SshAccess, logger: ILogger) {
@ -27,6 +30,23 @@ export class AsyncSsh2Client {
async connect() {
this.logger.info(`开始连接,${this.connConf.host}:${this.connConf.port}`);
if (this.connConf.socksProxy) {
this.logger.info(`使用代理${this.connConf.socksProxy}`);
if (typeof this.connConf.port === 'string') {
this.connConf.port = parseInt(this.connConf.port);
}
const proxyOption: SocksProxy = this.parseSocksProxyFromUri(this.connConf.socksProxy);
const info = await SocksClient.createConnection({
proxy: proxyOption,
command: 'connect',
destination: {
host: this.connConf.host,
port: this.connConf.port,
},
});
this.logger.info('代理连接成功');
this.connConf.sock = info.socket;
}
return new Promise((resolve, reject) => {
try {
const conn = new ssh2.Client();
@ -160,6 +180,26 @@ export class AsyncSsh2Client {
this.conn.end();
}
}
private parseSocksProxyFromUri(socksProxyUri: string): SocksProxy {
const url = new URL(socksProxyUri);
let type: SocksProxyType = 5;
if (url.protocol.startsWith('socks4')) {
type = 4;
}
const proxy: SocksProxy = {
host: url.hostname,
port: parseInt(url.port),
type,
};
if (url.username) {
proxy.userId = url.username;
}
if (url.password) {
proxy.password = url.password;
}
return proxy;
}
}
export class SshClient {