mirror of https://github.com/certd/certd
perf: 上传到主机,支持socks代理
parent
df88a936a5
commit
d91026dc4f
|
@ -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",
|
||||
|
|
|
@ -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为空、不是字符串 这些不需要加密
|
||||
|
|
|
@ -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主机,请勾选此项',
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue