mirror of https://github.com/certd/certd
perf: 上传到主机,支持socks代理
parent
df88a936a5
commit
d91026dc4f
|
@ -70,6 +70,8 @@
|
||||||
"querystring": "^0.2.1",
|
"querystring": "^0.2.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
|
"socks": "^2.8.3",
|
||||||
|
"socks-proxy-agent": "^8.0.4",
|
||||||
"ssh2": "^1.15.0",
|
"ssh2": "^1.15.0",
|
||||||
"strip-ansi": "^7.1.0",
|
"strip-ansi": "^7.1.0",
|
||||||
"svg-captcha": "^1.4.0",
|
"svg-captcha": "^1.4.0",
|
||||||
|
|
|
@ -60,7 +60,7 @@ export class AccessService extends BaseService<AccessEntity> implements IAccessS
|
||||||
const value = json[key];
|
const value = json[key];
|
||||||
const accessInputDefine = accessDefine.input[key];
|
const accessInputDefine = accessDefine.input[key];
|
||||||
if (!accessInputDefine) {
|
if (!accessInputDefine) {
|
||||||
throw new ValidateException(`授权类型${accessType}不存在字段${key}`);
|
continue;
|
||||||
}
|
}
|
||||||
if (!accessInputDefine.encrypt || !value || typeof value !== 'string') {
|
if (!accessInputDefine.encrypt || !value || typeof value !== 'string') {
|
||||||
//定义无需加密、value为空、不是字符串 这些不需要加密
|
//定义无需加密、value为空、不是字符串 这些不需要加密
|
||||||
|
|
|
@ -18,7 +18,7 @@ export class SshAccess implements IAccess, ConnectConfig {
|
||||||
host!: string;
|
host!: string;
|
||||||
@AccessInput({
|
@AccessInput({
|
||||||
title: '端口',
|
title: '端口',
|
||||||
value: '22',
|
value: 22,
|
||||||
component: {
|
component: {
|
||||||
name: 'a-input-number',
|
name: 'a-input-number',
|
||||||
placeholder: '22',
|
placeholder: '22',
|
||||||
|
@ -64,6 +64,17 @@ export class SshAccess implements IAccess, ConnectConfig {
|
||||||
})
|
})
|
||||||
passphrase!: string;
|
passphrase!: string;
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: '代理',
|
||||||
|
helper: '代理配置,格式:socks5://$username:$password@$host:$port',
|
||||||
|
component: {
|
||||||
|
name: 'a-input',
|
||||||
|
vModel: 'value',
|
||||||
|
},
|
||||||
|
encrypt: false,
|
||||||
|
})
|
||||||
|
socksProxy!: string;
|
||||||
|
|
||||||
@AccessInput({
|
@AccessInput({
|
||||||
title: '是否Windows',
|
title: '是否Windows',
|
||||||
helper: '如果是Windows主机,请勾选此项',
|
helper: '如果是Windows主机,请勾选此项',
|
||||||
|
|
|
@ -5,10 +5,13 @@ import * as _ from 'lodash-es';
|
||||||
import { ILogger } from '@certd/pipeline';
|
import { ILogger } from '@certd/pipeline';
|
||||||
import { SshAccess } from '../access/index.js';
|
import { SshAccess } from '../access/index.js';
|
||||||
import stripAnsi from 'strip-ansi';
|
import stripAnsi from 'strip-ansi';
|
||||||
|
import { SocksClient } from 'socks';
|
||||||
|
import { SocksProxy, SocksProxyType } from 'socks/typings/common/constants.js';
|
||||||
|
|
||||||
export class AsyncSsh2Client {
|
export class AsyncSsh2Client {
|
||||||
conn: ssh2.Client;
|
conn: ssh2.Client;
|
||||||
logger: ILogger;
|
logger: ILogger;
|
||||||
connConf: ssh2.ConnectConfig;
|
connConf: SshAccess & ssh2.ConnectConfig;
|
||||||
windows = false;
|
windows = false;
|
||||||
encoding: string;
|
encoding: string;
|
||||||
constructor(connConf: SshAccess, logger: ILogger) {
|
constructor(connConf: SshAccess, logger: ILogger) {
|
||||||
|
@ -27,6 +30,23 @@ export class AsyncSsh2Client {
|
||||||
|
|
||||||
async connect() {
|
async connect() {
|
||||||
this.logger.info(`开始连接,${this.connConf.host}:${this.connConf.port}`);
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const conn = new ssh2.Client();
|
const conn = new ssh2.Client();
|
||||||
|
@ -160,6 +180,26 @@ export class AsyncSsh2Client {
|
||||||
this.conn.end();
|
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 {
|
export class SshClient {
|
||||||
|
|
Loading…
Reference in New Issue