refactor: replace ctx with config
refactor: set static config for preset
This commit is contained in:
parent
d63f0bfddc
commit
d355ed9065
@ -194,19 +194,19 @@ describe('Config#init', () => {
|
||||
log_max_days: 30
|
||||
};
|
||||
|
||||
it('should ctx set correctly', () => {
|
||||
const ctx = new Config(clientConf);
|
||||
expect(ctx.LOCAL_PROTOCOL).toBe('tcp');
|
||||
expect(ctx.LOCAL_HOST).toBe('localhost');
|
||||
expect(ctx.LOCAL_PORT).toBe(1080);
|
||||
expect(ctx.IS_CLIENT).toBe(true);
|
||||
expect(ctx.IS_SERVER).toBe(false);
|
||||
expect(ctx.SERVERS.length).toBe(1);
|
||||
expect(ctx.TIMEOUT).toBe(600 * 1e3);
|
||||
expect(ctx.WORKERS).toBe(0);
|
||||
expect(ctx.LOG_LEVEL).toBe('warn');
|
||||
expect(ctx.LOG_PATH.endsWith('blinksocks.log')).toBe(true);
|
||||
expect(ctx.LOG_MAX_DAYS).toBe(30);
|
||||
it('should config set correctly', () => {
|
||||
const config = new Config(clientConf);
|
||||
expect(config.local_protocol).toBe('tcp');
|
||||
expect(config.local_host).toBe('localhost');
|
||||
expect(config.local_port).toBe(1080);
|
||||
expect(config.is_client).toBe(true);
|
||||
expect(config.is_server).toBe(false);
|
||||
expect(config.servers.length).toBe(1);
|
||||
expect(config.timeout).toBe(600 * 1e3);
|
||||
expect(config.workers).toBe(0);
|
||||
expect(config.log_level).toBe('warn');
|
||||
expect(config.log_path.endsWith('blinksocks.log')).toBe(true);
|
||||
expect(config.log_max_days).toBe(30);
|
||||
});
|
||||
|
||||
});
|
||||
@ -223,11 +223,11 @@ describe('Config#initServer', () => {
|
||||
tls_key: 'mock_key.pem'
|
||||
};
|
||||
|
||||
it('should ctx set correctly', () => {
|
||||
const ctx = new Config(serverConf);
|
||||
expect(ctx.TRANSPORT).toBe('tls');
|
||||
expect(ctx.TLS_CERT).toBeDefined();
|
||||
expect(ctx.TLS_KEY).toBeDefined();
|
||||
it('should config set correctly', () => {
|
||||
const config = new Config(serverConf);
|
||||
expect(config.transport).toBe('tls');
|
||||
expect(config.tls_cert).toBeDefined();
|
||||
expect(config.tls_key).toBeDefined();
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -7,128 +7,128 @@ import url from 'url';
|
||||
import qs from 'qs';
|
||||
import winston from 'winston';
|
||||
import isPlainObject from 'lodash.isplainobject';
|
||||
import {getPresetClassByName, IPresetAddressing} from '../presets';
|
||||
import {DNSCache, isValidHostname, isValidPort, logger, DNS_DEFAULT_EXPIRE} from '../utils';
|
||||
import { getPresetClassByName, IPresetAddressing } from '../presets';
|
||||
import { DNSCache, isValidHostname, isValidPort, logger, DNS_DEFAULT_EXPIRE } from '../utils';
|
||||
|
||||
function loadFileSync(file) {
|
||||
return fs.readFileSync(path.resolve(process.cwd(), file));
|
||||
}
|
||||
|
||||
export class Config {
|
||||
LOCAL_PROTOCOL = null;
|
||||
LOCAL_HOST = null;
|
||||
LOCAL_PORT = null;
|
||||
local_protocol = null;
|
||||
local_host = null;
|
||||
local_port = null;
|
||||
|
||||
SERVERS = null;
|
||||
IS_CLIENT = null;
|
||||
IS_SERVER = null;
|
||||
servers = null;
|
||||
is_client = null;
|
||||
is_server = null;
|
||||
|
||||
FORWARD_HOST = null;
|
||||
FORWARD_PORT = null;
|
||||
forward_host = null;
|
||||
forward_port = null;
|
||||
|
||||
TIMEOUT = null;
|
||||
REDIRECT = null;
|
||||
WORKERS = null;
|
||||
timeout = null;
|
||||
redirect = null;
|
||||
workers = null;
|
||||
|
||||
DNS_EXPIRE = null;
|
||||
DNS_DEFAULT_EXPIRE = null;
|
||||
DNS = null;
|
||||
dns_expire = null;
|
||||
dns = null;
|
||||
|
||||
TRANSPORT = null;
|
||||
SERVER_HOST = null;
|
||||
SERVER_PORT = null;
|
||||
TLS_CERT = null;
|
||||
KEY = null;
|
||||
transport = null;
|
||||
server_host = null;
|
||||
server_port = null;
|
||||
tls_cert = null;
|
||||
tls_key = null;
|
||||
key = null;
|
||||
|
||||
PRESETS = null;
|
||||
UDP_PRESETS = null;
|
||||
presets = null;
|
||||
udp_presets = null;
|
||||
|
||||
MUX = null;
|
||||
MUX_CONCURRENCY = null;
|
||||
|
||||
LOG_PATH = null;
|
||||
LOG_LEVEL = null;
|
||||
LOG_MAX_DAYS = null;
|
||||
mux = null;
|
||||
mux_concurrency = null;
|
||||
|
||||
constructor(json){
|
||||
const {protocol, hostname, port, query} = url.parse(json.service);
|
||||
this.LOCAL_PROTOCOL = protocol.slice(0, -1);
|
||||
this.LOCAL_HOST = hostname;
|
||||
this.LOCAL_PORT = +port;
|
||||
log_path = null;
|
||||
log_level = null;
|
||||
log_max_days = null;
|
||||
|
||||
constructor(json) {
|
||||
const { protocol, hostname, port, query } = url.parse(json.service);
|
||||
this.local_protocol = protocol.slice(0, -1);
|
||||
this.local_host = hostname;
|
||||
this.local_port = +port;
|
||||
|
||||
if (json.servers !== undefined) {
|
||||
this.SERVERS = json.servers.filter((server) => !!server.enabled);
|
||||
this.IS_CLIENT = true;
|
||||
this.IS_SERVER = false;
|
||||
this.servers = json.servers.filter((server) => !!server.enabled);
|
||||
this.is_client = true;
|
||||
this.is_server = false;
|
||||
} else {
|
||||
this.IS_CLIENT = false;
|
||||
this.IS_SERVER = true;
|
||||
this.is_client = false;
|
||||
this.is_server = true;
|
||||
}
|
||||
|
||||
this._initLogger(json);
|
||||
|
||||
if (this.IS_SERVER) {
|
||||
this._initServer(json);
|
||||
if (this.is_server) {
|
||||
this.initServer(json);
|
||||
}
|
||||
|
||||
if (this.IS_CLIENT && this.LOCAL_PROTOCOL === 'tcp') {
|
||||
const {forward} = qs.parse(query);
|
||||
const {hostname, port} = url.parse('tcp://' + forward);
|
||||
this.FORWARD_HOST = hostname;
|
||||
this.FORWARD_PORT = +port;
|
||||
if (this.is_client && this.local_protocol === 'tcp') {
|
||||
const { forward } = qs.parse(query);
|
||||
const { hostname, port } = url.parse('tcp://' + forward);
|
||||
this.forward_host = hostname;
|
||||
this.forward_port = +port;
|
||||
}
|
||||
|
||||
this.TIMEOUT = (json.timeout !== undefined) ? json.timeout * 1e3 : 600 * 1e3;
|
||||
this.REDIRECT = (json.redirect !== '') ? json.redirect : null;
|
||||
this.WORKERS = (json.workers !== undefined) ? json.workers : 0;
|
||||
this.DNS_EXPIRE = (json.dns_expire !== undefined) ? json.dns_expire * 1e3 : DNS_DEFAULT_EXPIRE;
|
||||
this.timeout = (json.timeout !== undefined) ? json.timeout * 1e3 : 600 * 1e3;
|
||||
this.redirect = (json.redirect !== '') ? json.redirect : null;
|
||||
this.workers = (json.workers !== undefined) ? json.workers : 0;
|
||||
this.dns_expire = (json.dns_expire !== undefined) ? json.dns_expire * 1e3 : DNS_DEFAULT_EXPIRE;
|
||||
|
||||
// dns
|
||||
if (json.dns !== undefined && json.dns.length > 0) {
|
||||
this.DNS = json.dns;
|
||||
this.dns = json.dns;
|
||||
dns.setServers(json.dns);
|
||||
}
|
||||
|
||||
// dns-cache
|
||||
DNSCache.init(this.DNS_EXPIRE);
|
||||
DNSCache.init(this.dns_expire);
|
||||
}
|
||||
|
||||
_initServer(server) {
|
||||
initServer(server) {
|
||||
// service
|
||||
const {protocol, hostname, port} = url.parse(server.service);
|
||||
this.TRANSPORT = protocol.slice(0, -1);
|
||||
this.SERVER_HOST = hostname;
|
||||
this.SERVER_PORT = +port;
|
||||
const { protocol, hostname, port } = url.parse(server.service);
|
||||
this.transport = protocol.slice(0, -1);
|
||||
this.server_host = hostname;
|
||||
this.server_port = +port;
|
||||
|
||||
// preload tls_cert or tls_key
|
||||
if (this.TRANSPORT === 'tls') {
|
||||
if (this.transport === 'tls') {
|
||||
logger.info(`[config] loading ${server.tls_cert}`);
|
||||
this.TLS_CERT = loadFileSync(server.tls_cert);
|
||||
if (this.IS_SERVER) {
|
||||
this.tls_cert = loadFileSync(server.tls_cert);
|
||||
if (this.is_server) {
|
||||
logger.info(`[config] loading ${server.tls_key}`);
|
||||
this.TLS_KEY = loadFileSync(server.tls_key);
|
||||
this.tls_key = loadFileSync(server.tls_key);
|
||||
}
|
||||
}
|
||||
|
||||
this.KEY = server.key;
|
||||
this.PRESETS = server.presets;
|
||||
this.UDP_PRESETS = server.presets;
|
||||
this.key = server.key;
|
||||
this.presets = server.presets;
|
||||
this.udp_presets = server.presets;
|
||||
|
||||
// mux
|
||||
this.MUX = !!server.mux;
|
||||
if (this.IS_CLIENT) {
|
||||
this.MUX_CONCURRENCY = server.mux_concurrency || 10;
|
||||
this.mux = !!server.mux;
|
||||
if (this.is_client) {
|
||||
this.mux_concurrency = server.mux_concurrency || 10;
|
||||
}
|
||||
|
||||
// remove unnecessary presets
|
||||
if (this.MUX) {
|
||||
this.PRESETS = this.PRESETS.filter(
|
||||
({name}) => !IPresetAddressing.isPrototypeOf(getPresetClassByName(name))
|
||||
if (this.mux) {
|
||||
this.presets = this.presets.filter(
|
||||
({ name }) => !IPresetAddressing.isPrototypeOf(getPresetClassByName(name))
|
||||
);
|
||||
}
|
||||
|
||||
// pre-init presets
|
||||
for (const {name, params = {}} of server.presets) {
|
||||
for (const { name, params = {} } of server.presets) {
|
||||
const clazz = getPresetClassByName(name);
|
||||
clazz.checked = false;
|
||||
clazz.checkParams(params);
|
||||
@ -148,12 +148,12 @@ export class Config {
|
||||
}
|
||||
|
||||
// log_path, log_level, log_max_days
|
||||
this.LOG_PATH = isFile ? absolutePath : path.join(absolutePath, `bs-${this.IS_CLIENT ? 'client' : 'server'}.log`);
|
||||
this.LOG_LEVEL = (json.log_level !== undefined) ? json.log_level : 'info';
|
||||
this.LOG_MAX_DAYS = (json.log_max_days !== undefined) ? json.log_max_days : 0;
|
||||
this.log_path = isFile ? absolutePath : path.join(absolutePath, `bs-${this.is_client ? 'client' : 'server'}.log`);
|
||||
this.log_level = (json.log_level !== undefined) ? json.log_level : 'info';
|
||||
this.log_max_days = (json.log_max_days !== undefined) ? json.log_max_days : 0;
|
||||
|
||||
logger.configure({
|
||||
level: this.LOG_LEVEL,
|
||||
level: this.log_level,
|
||||
transports: [
|
||||
new (winston.transports.Console)({
|
||||
colorize: true,
|
||||
@ -162,9 +162,9 @@ export class Config {
|
||||
new (require('winston-daily-rotate-file'))({
|
||||
json: false,
|
||||
eol: os.EOL,
|
||||
filename: this.LOG_PATH,
|
||||
level: this.LOG_LEVEL,
|
||||
maxDays: this.LOG_MAX_DAYS
|
||||
filename: this.log_path,
|
||||
level: this.log_level,
|
||||
maxDays: this.log_max_days
|
||||
})
|
||||
]
|
||||
});
|
||||
@ -188,7 +188,7 @@ export class Config {
|
||||
throw Error('"service" must be provided as "<protocol>://<host>:<port>[?params]"');
|
||||
}
|
||||
|
||||
const {protocol: _protocol, hostname, port, query} = url.parse(json.service);
|
||||
const { protocol: _protocol, hostname, port, query } = url.parse(json.service);
|
||||
|
||||
// service.protocol
|
||||
if (typeof _protocol !== 'string') {
|
||||
@ -216,14 +216,14 @@ export class Config {
|
||||
|
||||
// service.query
|
||||
if (protocol === 'tcp') {
|
||||
const {forward} = qs.parse(query);
|
||||
const { forward } = qs.parse(query);
|
||||
|
||||
// ?forward
|
||||
if (!forward) {
|
||||
throw Error('require "?forward=<host>:<port>" parameter in service when using "tcp" on client side');
|
||||
}
|
||||
|
||||
const {hostname, port} = url.parse('tcp://' + forward);
|
||||
const { hostname, port } = url.parse('tcp://' + forward);
|
||||
if (!isValidHostname(hostname)) {
|
||||
throw Error('service.?forward.host is invalid');
|
||||
}
|
||||
@ -278,7 +278,7 @@ export class Config {
|
||||
throw Error('"service" must be provided as "<protocol>://<host>:<port>[?params]"');
|
||||
}
|
||||
|
||||
const {protocol: _protocol, hostname, port} = url.parse(server.service);
|
||||
const { protocol: _protocol, hostname, port } = url.parse(server.service);
|
||||
|
||||
// service.protocol
|
||||
if (typeof _protocol !== 'string') {
|
||||
@ -343,7 +343,7 @@ export class Config {
|
||||
|
||||
// presets[].parameters
|
||||
for (const preset of server.presets) {
|
||||
const {name, params} = preset;
|
||||
const { name, params } = preset;
|
||||
if (typeof name !== 'string') {
|
||||
throw Error('"server.presets[].name" must be a string');
|
||||
}
|
||||
@ -361,7 +361,7 @@ export class Config {
|
||||
static _testCommon(common) {
|
||||
// timeout
|
||||
if (common.timeout !== undefined) {
|
||||
const {timeout} = common;
|
||||
const { timeout } = common;
|
||||
if (typeof timeout !== 'number') {
|
||||
throw Error('"timeout" must be a number');
|
||||
}
|
||||
@ -390,7 +390,7 @@ export class Config {
|
||||
|
||||
// log_max_days
|
||||
if (common.log_max_days !== undefined) {
|
||||
const {log_max_days} = common;
|
||||
const { log_max_days } = common;
|
||||
if (typeof log_max_days !== 'number') {
|
||||
throw Error('"log_max_days" must a number');
|
||||
}
|
||||
@ -401,7 +401,7 @@ export class Config {
|
||||
|
||||
// workers
|
||||
if (common.workers !== undefined) {
|
||||
const {workers} = common;
|
||||
const { workers } = common;
|
||||
if (typeof workers !== 'number') {
|
||||
throw Error('"workers" must be a number');
|
||||
}
|
||||
@ -415,7 +415,7 @@ export class Config {
|
||||
|
||||
// dns
|
||||
if (common.dns !== undefined) {
|
||||
const {dns} = common;
|
||||
const { dns } = common;
|
||||
if (!Array.isArray(dns)) {
|
||||
throw Error('"dns" must be an array');
|
||||
}
|
||||
@ -428,7 +428,7 @@ export class Config {
|
||||
|
||||
// dns_expire
|
||||
if (common.dns_expire !== undefined) {
|
||||
const {dns_expire} = common;
|
||||
const { dns_expire } = common;
|
||||
if (typeof dns_expire !== 'number') {
|
||||
throw Error('"dns_expire" must be a number');
|
||||
}
|
||||
|
@ -35,10 +35,10 @@ export class Hub {
|
||||
|
||||
_udpRelays = null; // LRU cache
|
||||
|
||||
_ctx = null;
|
||||
_config = null;
|
||||
|
||||
constructor(config) {
|
||||
this._ctx = new Config(config);
|
||||
this._config = new Config(config);
|
||||
this._onConnection = this._onConnection.bind(this);
|
||||
this._udpRelays = LRU({
|
||||
max: 500,
|
||||
@ -50,14 +50,14 @@ export class Hub {
|
||||
terminate(callback) {
|
||||
// relays
|
||||
this._udpRelays.reset();
|
||||
if (this._ctx.MUX) {
|
||||
if (this._config.mux) {
|
||||
this._muxRelays.forEach((relay) => relay.destroy());
|
||||
this._muxRelays.clear();
|
||||
}
|
||||
this._tcpRelays.forEach((relay) => relay.destroy());
|
||||
this._tcpRelays.clear();
|
||||
// balancer
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
Balancer.destroy();
|
||||
logger.info(`[balancer-${this._wkId}] stopped`);
|
||||
}
|
||||
@ -73,8 +73,8 @@ export class Hub {
|
||||
if (this._tcpServer !== null) {
|
||||
this.terminate();
|
||||
}
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
Balancer.start(this._ctx.SERVERS);
|
||||
if (this._config.is_client) {
|
||||
Balancer.start(this._config.servers);
|
||||
logger.info(`[balancer-${this._wkId}] started`);
|
||||
this._switchServer();
|
||||
}
|
||||
@ -87,7 +87,7 @@ export class Hub {
|
||||
}
|
||||
|
||||
async _createServer() {
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
this._tcpServer = await this._createServerOnClient();
|
||||
} else {
|
||||
this._tcpServer = await this._createServerOnServer();
|
||||
@ -98,30 +98,30 @@ export class Hub {
|
||||
async _createServerOnClient() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let server = null;
|
||||
switch (this._ctx.LOCAL_PROTOCOL) {
|
||||
switch (this._config.local_protocol) {
|
||||
case 'tcp':
|
||||
server = tcp.createServer({forwardHost: this._ctx.FORWARD_HOST, forwardPort: this._ctx.FORWARD_PORT});
|
||||
server = tcp.createServer({forwardHost: this._config.forward_host, forwardPort: this._config.forward_port});
|
||||
break;
|
||||
case 'socks':
|
||||
case 'socks5':
|
||||
case 'socks4':
|
||||
case 'socks4a':
|
||||
server = socks.createServer({bindAddress: this._ctx.LOCAL_HOST, bindPort: this._ctx.LOCAL_PORT});
|
||||
server = socks.createServer({bindAddress: this._config.local_host, bindPort: this._config.local_port});
|
||||
break;
|
||||
case 'http':
|
||||
case 'https':
|
||||
server = http.createServer();
|
||||
break;
|
||||
default:
|
||||
return reject(Error(`unsupported protocol: "${this._ctx.LOCAL_PROTOCOL}"`));
|
||||
return reject(Error(`unsupported protocol: "${this._config.local_protocol}"`));
|
||||
}
|
||||
const address = {
|
||||
host: this._ctx.LOCAL_HOST,
|
||||
port: this._ctx.LOCAL_PORT
|
||||
host: this._config.local_host,
|
||||
port: this._config.local_port
|
||||
};
|
||||
server.on('proxyConnection', this._onConnection);
|
||||
server.listen(address, () => {
|
||||
const service = `${this._ctx.LOCAL_PROTOCOL}://${this._ctx.LOCAL_HOST}:${this._ctx.LOCAL_PORT}`;
|
||||
const service = `${this._config.local_protocol}://${this._config.local_host}:${this._config.local_port}`;
|
||||
logger.info(`[hub-${this._wkId}] blinksocks client is running at ${service}`);
|
||||
resolve(server);
|
||||
});
|
||||
@ -131,15 +131,15 @@ export class Hub {
|
||||
async _createServerOnServer() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const address = {
|
||||
host: this._ctx.LOCAL_HOST,
|
||||
port: this._ctx.LOCAL_PORT
|
||||
host: this._config.local_host,
|
||||
port: this._config.local_port
|
||||
};
|
||||
const onListening = (server) => {
|
||||
const service = `${this._ctx.LOCAL_PROTOCOL}://${this._ctx.LOCAL_HOST}:${this._ctx.LOCAL_PORT}`;
|
||||
const service = `${this._config.local_protocol}://${this._config.local_host}:${this._config.local_port}`;
|
||||
logger.info(`[hub-${this._wkId}] blinksocks server is running at ${service}`);
|
||||
resolve(server);
|
||||
};
|
||||
switch (this._ctx.LOCAL_PROTOCOL) {
|
||||
switch (this._config.local_protocol) {
|
||||
case 'tcp': {
|
||||
const server = net.createServer();
|
||||
server.on('connection', this._onConnection);
|
||||
@ -160,13 +160,13 @@ export class Hub {
|
||||
break;
|
||||
}
|
||||
case 'tls': {
|
||||
const server = tls.createServer({key: [this._ctx.TLS_KEY], cert: [this._ctx.TLS_CERT]});
|
||||
const server = tls.createServer({key: [this._config.tls_key], cert: [this._config.tls_cert]});
|
||||
server.on('secureConnection', this._onConnection);
|
||||
server.listen(address, () => onListening(server));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return reject(Error(`unsupported protocol: "${this._ctx.LOCAL_PROTOCOL}"`));
|
||||
return reject(Error(`unsupported protocol: "${this._config.local_protocol}"`));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -180,7 +180,7 @@ export class Hub {
|
||||
const {address, port} = rinfo;
|
||||
let proxyRequest = null;
|
||||
let packet = msg;
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
const parsed = socks.parseSocks5UdpRequest(msg);
|
||||
if (parsed === null) {
|
||||
logger.warn(`[hub] [${address}:${port}] drop invalid udp packet: ${dumpHex(msg)}`);
|
||||
@ -219,7 +219,7 @@ export class Hub {
|
||||
})(server.close);
|
||||
|
||||
// monkey patch for Socket.send() to meet Socks5 protocol
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
server.send = ((send) => (data, port, host, isSs, ...args) => {
|
||||
let packet = null;
|
||||
if (isSs) {
|
||||
@ -232,8 +232,8 @@ export class Hub {
|
||||
})(server.send);
|
||||
}
|
||||
|
||||
server.bind({address: this._ctx.LOCAL_HOST, port: this._ctx.LOCAL_PORT}, () => {
|
||||
const service = `udp://${this._ctx.LOCAL_HOST}:${this._ctx.LOCAL_PORT}`;
|
||||
server.bind({address: this._config.local_host, port: this._config.local_port}, () => {
|
||||
const service = `udp://${this._config.local_host}:${this._config.local_port}`;
|
||||
logger.info(`[hub-${this._wkId}] blinksocks udp server is running at ${service}`);
|
||||
resolve(server);
|
||||
});
|
||||
@ -242,7 +242,7 @@ export class Hub {
|
||||
|
||||
_onConnection(socket, proxyRequest = null) {
|
||||
logger.verbose(`[hub] [${socket.remoteAddress}:${socket.remotePort}] connected`);
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
this._switchServer();
|
||||
}
|
||||
const context = {
|
||||
@ -255,8 +255,8 @@ export class Hub {
|
||||
};
|
||||
|
||||
let muxRelay = null, cid = null;
|
||||
if (this._ctx.MUX) {
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
if (this._config.mux) {
|
||||
if (this._config.is_client) {
|
||||
cid = makeConnID();
|
||||
muxRelay = this._getMuxRelayOnClient(context, cid);
|
||||
context.muxRelay = muxRelay;
|
||||
@ -269,8 +269,8 @@ export class Hub {
|
||||
const relay = this._createRelay(context);
|
||||
|
||||
// setup association between relay and muxRelay
|
||||
if (this._ctx.MUX) {
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
if (this._config.mux) {
|
||||
if (this._config.is_client) {
|
||||
relay.id = cid; // NOTE: this cid will be used in mux preset
|
||||
muxRelay.addSubRelay(relay);
|
||||
} else {
|
||||
@ -316,25 +316,25 @@ export class Hub {
|
||||
_createRelay(context, isMux = false) {
|
||||
const props = {
|
||||
context: context,
|
||||
transport: this._ctx.TRANSPORT,
|
||||
presets: this._ctx.PRESETS
|
||||
transport: this._config.transport,
|
||||
presets: this._config.presets
|
||||
};
|
||||
if (isMux) {
|
||||
return new MuxRelay(props, this._ctx);
|
||||
return new MuxRelay(props, this._config);
|
||||
}
|
||||
if (this._ctx.MUX) {
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
return new Relay({...props, transport: 'mux', presets: []}, this._ctx);
|
||||
if (this._config.mux) {
|
||||
if (this._config.is_client) {
|
||||
return new Relay({...props, transport: 'mux', presets: []}, this._config);
|
||||
} else {
|
||||
return new MuxRelay(props, this._ctx);
|
||||
return new MuxRelay(props, this._config);
|
||||
}
|
||||
} else {
|
||||
return new Relay(props, this._ctx);
|
||||
return new Relay(props, this._config);
|
||||
}
|
||||
}
|
||||
|
||||
_createUdpRelay(context) {
|
||||
return new Relay({transport: 'udp', context, presets: this._ctx.UDP_PRESETS}, this._ctx);
|
||||
return new Relay({transport: 'udp', context, presets: this._config.udp_presets}, this._config);
|
||||
}
|
||||
|
||||
_selectMuxRelay() {
|
||||
@ -343,7 +343,7 @@ export class Hub {
|
||||
if (concurrency < 1) {
|
||||
return null;
|
||||
}
|
||||
if (concurrency < this._ctx.MUX_CONCURRENCY && getRandomInt(0, 1) === 0) {
|
||||
if (concurrency < this._config.mux_concurrency && getRandomInt(0, 1) === 0) {
|
||||
return null;
|
||||
}
|
||||
return relays.get([...relays.keys()][getRandomInt(0, concurrency - 1)]);
|
||||
@ -352,8 +352,8 @@ export class Hub {
|
||||
_switchServer() {
|
||||
const server = Balancer.getFastest();
|
||||
if (server) {
|
||||
Config.initServer(server);
|
||||
logger.info(`[balancer-${this._wkId}] use server: ${this._ctx.SERVER_HOST}:${this._ctx.SERVER_PORT}`);
|
||||
this._config.initServer(server);
|
||||
logger.info(`[balancer-${this._wkId}] use server: ${this._config.server_host}:${this._config.server_port}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,13 @@ import {kebabCase} from '../utils';
|
||||
|
||||
const staticPresetCache = new Map(/* 'ClassName': <preset> */);
|
||||
|
||||
function createPreset(name, params = {}, ctx) {
|
||||
function createPreset(name, params = {}, config) {
|
||||
const ImplClass = getPresetClassByName(name);
|
||||
const createOne = () => {
|
||||
ImplClass.checkParams(params, ctx);
|
||||
ImplClass.onInit(params, ctx);
|
||||
return new ImplClass(params, ctx);
|
||||
ImplClass.config = config;
|
||||
ImplClass.checkParams(params);
|
||||
ImplClass.onInit(params);
|
||||
return new ImplClass(params);
|
||||
};
|
||||
let preset = null;
|
||||
if (IPresetStatic.isPrototypeOf(ImplClass)) {
|
||||
@ -32,16 +33,15 @@ function createPreset(name, params = {}, ctx) {
|
||||
export class Middleware extends EventEmitter {
|
||||
|
||||
_impl = null;
|
||||
_ctx = null;
|
||||
_config = null;
|
||||
|
||||
constructor(preset, ctx) {
|
||||
constructor(preset, config) {
|
||||
super();
|
||||
console.log(this._ctx)
|
||||
this._ctx = ctx;
|
||||
this._config = config;
|
||||
this.onPresetNext = this.onPresetNext.bind(this);
|
||||
this.onPresetBroadcast = this.onPresetBroadcast.bind(this);
|
||||
this.onPresetFail = this.onPresetFail.bind(this);
|
||||
this._impl = createPreset(preset.name, preset.params || {}, this._ctx);
|
||||
this._impl = createPreset(preset.name, preset.params || {}, this._config);
|
||||
this._impl.next = this.onPresetNext;
|
||||
this._impl.broadcast = this.onPresetBroadcast;
|
||||
this._impl.fail = this.onPresetFail;
|
||||
@ -108,7 +108,7 @@ export class Middleware extends EventEmitter {
|
||||
// clientXXX, serverXXX
|
||||
const nextLifeCycleHook = (buf/* , isReverse = false */) => {
|
||||
const args = {buffer: buf, next, broadcast, direct, fail};
|
||||
const ret = this._ctx.IS_CLIENT ? this._impl[`client${type}`](args, extraArgs) : this._impl[`server${type}`](args, extraArgs);
|
||||
const ret = this._config.is_client ? this._impl[`client${type}`](args, extraArgs) : this._impl[`server${type}`](args, extraArgs);
|
||||
if (ret instanceof Buffer) {
|
||||
next(ret);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ export class MuxRelay extends Relay {
|
||||
'tls': [TlsInbound, TlsOutbound],
|
||||
'ws': [WsInbound, WsOutbound],
|
||||
};
|
||||
const [Inbound, Outbound] = this._globalCtx.IS_CLIENT ? [MuxInbound, mapping[transport][1]] : [mapping[transport][0], MuxOutbound];
|
||||
const [Inbound, Outbound] = this._config.is_client ? [MuxInbound, mapping[transport][1]] : [mapping[transport][0], MuxOutbound];
|
||||
return {Inbound, Outbound};
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ export class MuxRelay extends Relay {
|
||||
logger.error(`[mux-${this.id}] fail to dispatch data frame(size=${data.length}), no such sub connection(cid=${cid})`);
|
||||
return;
|
||||
}
|
||||
if (this._globalCtx.IS_CLIENT || relay.isOutboundReady()) {
|
||||
if (this._config.is_client || relay.isOutboundReady()) {
|
||||
relay.decode(data);
|
||||
} else {
|
||||
// TODO: find a way to avoid using relay._pendingFrames
|
||||
|
@ -21,7 +21,7 @@ export class Pipe extends EventEmitter {
|
||||
|
||||
_presets = null;
|
||||
|
||||
_ctx = null;
|
||||
_config = null;
|
||||
|
||||
get destroyed() {
|
||||
return this._destroyed;
|
||||
@ -31,9 +31,9 @@ export class Pipe extends EventEmitter {
|
||||
return this._presets;
|
||||
}
|
||||
|
||||
constructor({presets, isUdp = false}, ctx) {
|
||||
constructor({presets, isUdp = false}, config) {
|
||||
super();
|
||||
this._ctx = ctx;
|
||||
this._config = config;
|
||||
this.broadcast = this.broadcast.bind(this);
|
||||
this.onReadProperty = this.onReadProperty.bind(this);
|
||||
this.createMiddlewares(presets);
|
||||
@ -143,7 +143,7 @@ export class Pipe extends EventEmitter {
|
||||
}
|
||||
|
||||
_createMiddleware(preset) {
|
||||
const middleware = new Middleware(preset, this._ctx);
|
||||
const middleware = new Middleware(preset, this._config);
|
||||
this._attachEvents(middleware);
|
||||
// set readProperty()
|
||||
const impl = middleware.getImplement();
|
||||
|
@ -54,7 +54,7 @@ export class Relay extends EventEmitter {
|
||||
|
||||
_destroyed = false;
|
||||
|
||||
_globalCtx = null;
|
||||
_config = null;
|
||||
|
||||
get id() {
|
||||
return this._id;
|
||||
@ -65,9 +65,9 @@ export class Relay extends EventEmitter {
|
||||
this._ctx.cid = id;
|
||||
}
|
||||
|
||||
constructor({transport, context, presets = []}, ctx) {
|
||||
constructor({transport, context, presets = []}, config) {
|
||||
super();
|
||||
this._globalCtx = ctx;
|
||||
this._config = config;
|
||||
this.updatePresets = this.updatePresets.bind(this);
|
||||
this.onBroadcast = this.onBroadcast.bind(this);
|
||||
this.onEncoded = this.onEncoded.bind(this);
|
||||
@ -85,8 +85,8 @@ export class Relay extends EventEmitter {
|
||||
};
|
||||
// bounds
|
||||
const {Inbound, Outbound} = this.getBounds(transport);
|
||||
const inbound = new Inbound({context: this._ctx, globalContext: this._globalCtx});
|
||||
const outbound = new Outbound({context: this._ctx, globalContext: this._globalCtx});
|
||||
const inbound = new Inbound({context: this._ctx, globalContext: this._config});
|
||||
const outbound = new Outbound({context: this._ctx, globalContext: this._config});
|
||||
this._inbound = inbound;
|
||||
this._outbound = outbound;
|
||||
// outbound
|
||||
@ -130,7 +130,7 @@ export class Relay extends EventEmitter {
|
||||
if (transport === 'udp') {
|
||||
[Inbound, Outbound] = [UdpInbound, UdpOutbound];
|
||||
} else {
|
||||
[Inbound, Outbound] = this._globalCtx.IS_CLIENT ? [TcpInbound, mapping[transport][1]] : [mapping[transport][0], TcpOutbound];
|
||||
[Inbound, Outbound] = this._config.is_client ? [TcpInbound, mapping[transport][1]] : [mapping[transport][0], TcpOutbound];
|
||||
}
|
||||
return {Inbound, Outbound};
|
||||
}
|
||||
@ -167,7 +167,7 @@ export class Relay extends EventEmitter {
|
||||
if (type === CONNECT_TO_REMOTE) {
|
||||
const remote = `${this._remoteInfo.host}:${this._remoteInfo.port}`;
|
||||
const target = `${action.payload.host}:${action.payload.port}`;
|
||||
if (this._globalCtx.MUX && this._globalCtx.IS_CLIENT && this._transport !== 'udp') {
|
||||
if (this._config.mux && this._config.is_client && this._transport !== 'udp') {
|
||||
logger.info(`[relay-${this.id}] [${remote}] request over mux-${this._ctx.muxRelay.id}: ${target}`);
|
||||
return;
|
||||
}
|
||||
@ -196,7 +196,7 @@ export class Relay extends EventEmitter {
|
||||
type: CONNECTION_CREATED,
|
||||
payload: {transport, ...this._remoteInfo}
|
||||
});
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
this._pipe.broadcast(null, {
|
||||
type: CONNECT_TO_REMOTE,
|
||||
payload: {...proxyRequest, keepAlive: true} // keep previous connection alive, don't re-connect
|
||||
@ -207,7 +207,7 @@ export class Relay extends EventEmitter {
|
||||
}
|
||||
|
||||
onEncoded(buffer) {
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
this._outbound.write(buffer);
|
||||
} else {
|
||||
this._inbound.write(buffer);
|
||||
@ -215,7 +215,7 @@ export class Relay extends EventEmitter {
|
||||
}
|
||||
|
||||
onDecoded(buffer) {
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
this._inbound.write(buffer);
|
||||
} else {
|
||||
this._outbound.write(buffer);
|
||||
@ -271,7 +271,7 @@ export class Relay extends EventEmitter {
|
||||
* create pipes for both data forward and backward
|
||||
*/
|
||||
createPipe(presets) {
|
||||
const pipe = new Pipe({presets, isUdp: this._transport === 'udp'}, this._globalCtx);
|
||||
const pipe = new Pipe({presets, isUdp: this._transport === 'udp'}, this._config);
|
||||
pipe.on('broadcast', this.onBroadcast.bind(this)); // if no action were caught by presets
|
||||
pipe.on(`post_${PIPE_ENCODE}`, this.onEncoded);
|
||||
pipe.on(`post_${PIPE_DECODE}`, this.onDecoded);
|
||||
@ -294,7 +294,7 @@ export class Relay extends EventEmitter {
|
||||
this._remoteInfo = null;
|
||||
this._proxyRequest = null;
|
||||
this._destroyed = true;
|
||||
this._globalCtx = null;
|
||||
this._config = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,11 +118,11 @@ export default class AeadRandomCipherPreset extends IPreset {
|
||||
}
|
||||
}
|
||||
|
||||
static onInit({method, info = DEFAULT_INFO, factor = DEFAULT_FACTOR}, {KEY}) {
|
||||
static onInit({method, info = DEFAULT_INFO, factor = DEFAULT_FACTOR}) {
|
||||
AeadRandomCipherPreset.cipherName = method;
|
||||
AeadRandomCipherPreset.info = Buffer.from(info);
|
||||
AeadRandomCipherPreset.factor = factor;
|
||||
AeadRandomCipherPreset.rawKey = Buffer.from(KEY);
|
||||
AeadRandomCipherPreset.rawKey = Buffer.from(AeadRandomCipherPreset.config.key);
|
||||
AeadRandomCipherPreset.keySaltSize = ciphers[method];
|
||||
}
|
||||
|
||||
|
@ -76,8 +76,6 @@ export default class AutoConfPreset extends IPreset {
|
||||
|
||||
_header = null;
|
||||
|
||||
_ctx = null;
|
||||
|
||||
static suites = [];
|
||||
|
||||
static checkParams({suites}) {
|
||||
@ -86,11 +84,6 @@ export default class AutoConfPreset extends IPreset {
|
||||
}
|
||||
}
|
||||
|
||||
constructor(_, ctx) {
|
||||
super();
|
||||
this._ctx = ctx;
|
||||
}
|
||||
|
||||
static async onInit({suites: uri}) {
|
||||
logger.info(`[auto-conf] loading suites from: ${uri}`);
|
||||
let suites = [];
|
||||
@ -118,7 +111,7 @@ export default class AutoConfPreset extends IPreset {
|
||||
createRequestHeader(suites) {
|
||||
const sid = crypto.randomBytes(2);
|
||||
const utc = ntb(getCurrentTimestampInt(), 4, BYTE_ORDER_LE);
|
||||
const key = EVP_BytesToKey(Buffer.from(this._ctx.KEY).toString('base64') + hash('md5', sid).toString('base64'), 16, 16);
|
||||
const key = EVP_BytesToKey(Buffer.from(AutoConfPreset.config.key).toString('base64') + hash('md5', sid).toString('base64'), 16, 16);
|
||||
const cipher = crypto.createCipheriv('rc4', key, NOOP);
|
||||
const enc_utc = cipher.update(utc);
|
||||
const request_hmac = hmac('md5', key, Buffer.concat([sid, enc_utc]));
|
||||
@ -156,7 +149,7 @@ export default class AutoConfPreset extends IPreset {
|
||||
}
|
||||
const sid = buffer.slice(0, 2);
|
||||
const request_hmac = buffer.slice(6, 22);
|
||||
const key = EVP_BytesToKey(Buffer.from(this._ctx.KEY).toString('base64') + hash('md5', sid).toString('base64'), 16, 16);
|
||||
const key = EVP_BytesToKey(Buffer.from(AutoConfPreset.config.KEY).toString('base64') + hash('md5', sid).toString('base64'), 16, 16);
|
||||
const hmac_calc = hmac('md5', key, buffer.slice(0, 6));
|
||||
if (!hmac_calc.equals(request_hmac)) {
|
||||
return fail(`unexpected hmac of client request, dump=${dumpHex(buffer)}`);
|
||||
|
@ -78,8 +78,6 @@ export default class BaseAuthPreset extends IPresetAddressing {
|
||||
|
||||
_port = null; // buffer
|
||||
|
||||
_ctx = null;
|
||||
|
||||
static checkParams({method = DEFAULT_HASH_METHOD}) {
|
||||
const methods = Object.keys(HMAC_METHODS);
|
||||
if (!methods.includes(method)) {
|
||||
@ -87,18 +85,17 @@ export default class BaseAuthPreset extends IPresetAddressing {
|
||||
}
|
||||
}
|
||||
|
||||
static onInit({method = DEFAULT_HASH_METHOD}, {KEY}) {
|
||||
static onInit({method = DEFAULT_HASH_METHOD}) {
|
||||
BaseAuthPreset.hmacMethod = method;
|
||||
BaseAuthPreset.hmacLen = HMAC_METHODS[method];
|
||||
BaseAuthPreset.hmacKey = EVP_BytesToKey(KEY, 16, 16);
|
||||
BaseAuthPreset.hmacKey = EVP_BytesToKey(BaseAuthPreset.config.key, 16, 16);
|
||||
}
|
||||
|
||||
constructor(_, ctx) {
|
||||
constructor() {
|
||||
super();
|
||||
this._ctx = ctx;
|
||||
const {hmacKey: key} = BaseAuthPreset;
|
||||
const iv = hash('md5', Buffer.from(ctx.KEY + 'base-auth'));
|
||||
if (ctx.IS_CLIENT) {
|
||||
const iv = hash('md5', Buffer.from(BaseAuthPreset.config.key + 'base-auth'));
|
||||
if (BaseAuthPreset.config.is_client) {
|
||||
this._cipher = crypto.createCipheriv('aes-128-cfb', key, iv);
|
||||
} else {
|
||||
this._decipher = crypto.createDecipheriv('aes-128-cfb', key, iv);
|
||||
@ -114,7 +111,7 @@ export default class BaseAuthPreset extends IPresetAddressing {
|
||||
}
|
||||
|
||||
onNotified(action) {
|
||||
if (this._ctx.IS_CLIENT && action.type === CONNECT_TO_REMOTE) {
|
||||
if (BaseAuthPreset.config.is_client && action.type === CONNECT_TO_REMOTE) {
|
||||
const {host, port} = action.payload;
|
||||
this._host = Buffer.from(host);
|
||||
this._port = numberToBuffer(port);
|
||||
|
@ -110,6 +110,13 @@ export class IPreset {
|
||||
*/
|
||||
static checked = false;
|
||||
|
||||
|
||||
/**
|
||||
* server config
|
||||
* @type {Config}
|
||||
*/
|
||||
static config = null;
|
||||
|
||||
/**
|
||||
* will become true after onInit()
|
||||
* @type {boolean}
|
||||
@ -120,7 +127,7 @@ export class IPreset {
|
||||
* check params passed to the preset, if any errors, should throw directly
|
||||
* @param params
|
||||
*/
|
||||
static checkParams(params, ctx) {
|
||||
static checkParams(params) {
|
||||
|
||||
}
|
||||
|
||||
@ -128,7 +135,7 @@ export class IPreset {
|
||||
* you can make some cache in this function
|
||||
* @param params
|
||||
*/
|
||||
static onInit(params, ctx) {
|
||||
static onInit(params) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -126,13 +126,13 @@ export default class SsAeadCipherPreset extends IPreset {
|
||||
}
|
||||
}
|
||||
|
||||
static onInit({method}, {KEY}) {
|
||||
static onInit({method}) {
|
||||
const [keySize, saltSize, nonceSize] = ciphers[method];
|
||||
SsAeadCipherPreset.cipherName = method;
|
||||
SsAeadCipherPreset.keySize = keySize;
|
||||
SsAeadCipherPreset.saltSize = saltSize;
|
||||
SsAeadCipherPreset.nonceSize = nonceSize;
|
||||
SsAeadCipherPreset.evpKey = EVP_BytesToKey(KEY, keySize, 16);
|
||||
SsAeadCipherPreset.evpKey = EVP_BytesToKey(SsAeadCipherPreset.config.key, keySize, 16);
|
||||
SsAeadCipherPreset.isUseLibSodium = Object.keys(libsodium_functions).includes(method);
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,6 @@ export default class SsBasePreset extends IPresetAddressing {
|
||||
|
||||
_headSize = 0;
|
||||
|
||||
_ctx = null;
|
||||
|
||||
get headSize() {
|
||||
return this._headSize;
|
||||
}
|
||||
@ -85,13 +83,8 @@ export default class SsBasePreset extends IPresetAddressing {
|
||||
this._port = null;
|
||||
}
|
||||
|
||||
constructor(_, ctx) {
|
||||
super();
|
||||
this._ctx = ctx;
|
||||
}
|
||||
|
||||
onNotified(action) {
|
||||
if (this._ctx.IS_CLIENT && action.type === CONNECT_TO_REMOTE) {
|
||||
if (SsBasePreset.config.is_client && action.type === CONNECT_TO_REMOTE) {
|
||||
const {host, port} = action.payload;
|
||||
const type = getHostType(host);
|
||||
this._atyp = type;
|
||||
|
@ -97,14 +97,14 @@ export default class SsStreamCipherPreset extends IPreset {
|
||||
return this._iv;
|
||||
}
|
||||
|
||||
constructor({method}, {KEY}) {
|
||||
constructor({method}) {
|
||||
super();
|
||||
const [keySize, ivSize] = ciphers[method];
|
||||
const iv = crypto.randomBytes(ivSize);
|
||||
this._algorithm = ['rc4-md5', 'rc4-md5-6'].includes(method) ? 'rc4' : method;
|
||||
this._keySize = keySize;
|
||||
this._ivSize = ivSize;
|
||||
this._key = EVP_BytesToKey(KEY, keySize, ivSize);
|
||||
this._key = EVP_BytesToKey(SsStreamCipherPreset.config.key, keySize, ivSize);
|
||||
this._iv = method === 'rc4-md5-6' ? iv.slice(0, 6) : iv;
|
||||
}
|
||||
|
||||
|
@ -102,8 +102,8 @@ export default class SsrAuthAes128Preset extends IPreset {
|
||||
|
||||
_adBuf = null;
|
||||
|
||||
static onInit({KEY}) {
|
||||
SsrAuthAes128Preset.userKey = EVP_BytesToKey(KEY, 16, 16);
|
||||
static onInit() {
|
||||
SsrAuthAes128Preset.userKey = EVP_BytesToKey(SsrAuthAes128Preset.config.key, 16, 16);
|
||||
SsrAuthAes128Preset.clientId = crypto.randomBytes(4);
|
||||
SsrAuthAes128Preset.connectionId = getRandomInt(0, 0x00ffffff);
|
||||
}
|
||||
|
@ -143,16 +143,13 @@ export default class SsrAuthChainPreset extends IPreset {
|
||||
|
||||
_adBuf = null;
|
||||
|
||||
_ctx = null;
|
||||
|
||||
static onInit() {
|
||||
SsrAuthChainPreset.clientId = crypto.randomBytes(4);
|
||||
SsrAuthChainPreset.connectionId = getRandomInt(0, 0x00ffffff);
|
||||
}
|
||||
|
||||
constructor(_, ctx) {
|
||||
constructor() {
|
||||
super();
|
||||
this._ctx = ctx;
|
||||
this._rngClient = xorshift128plus();
|
||||
this._rngServer = xorshift128plus();
|
||||
this._adBuf = new AdvancedBuffer({getPacketLength: this.onReceiving.bind(this)});
|
||||
@ -235,17 +232,17 @@ export default class SsrAuthChainPreset extends IPreset {
|
||||
|
||||
createChunks(buffer) {
|
||||
const userKey = this._userKey;
|
||||
const max_payload_size = this._ctx.IS_CLIENT ? 2800 : (this._tcpMss - this._overhead);
|
||||
const max_payload_size = SsrAuthChainPreset.config.is_client ? 2800 : (this._tcpMss - this._overhead);
|
||||
return getChunks(buffer, max_payload_size).map((payload) => {
|
||||
let _payload = payload;
|
||||
if (this._ctx.IS_SERVER && this._encodeChunkId === 1) {
|
||||
if (SsrAuthChainPreset.config.is_server && this._encodeChunkId === 1) {
|
||||
_payload = Buffer.concat([ntb(this._tcpMss, 2, BYTE_ORDER_LE), payload]);
|
||||
}
|
||||
const rc4_enc_payload = this._cipher.update(_payload);
|
||||
const hash = this._ctx.IS_CLIENT ? this._lastClientHash : this._lastServerHash;
|
||||
const hash = SsrAuthChainPreset.config.is_client ? this._lastClientHash : this._lastServerHash;
|
||||
const size = rc4_enc_payload.length ^ hash.slice(-2).readUInt16LE(0);
|
||||
// generate two pieces of random bytes
|
||||
const rng = this._ctx.IS_CLIENT ? this._rngClient : this._rngServer;
|
||||
const rng = SsrAuthChainPreset.config.is_client ? this._rngClient : this._rngServer;
|
||||
const random_bytes_len = this.getRandomBytesLengthForTcp(hash, _payload.length, rng);
|
||||
const random_bytes = crypto.randomBytes(random_bytes_len);
|
||||
const random_divide_pos = random_bytes_len > 0 ? rng.next().mod(8589934609).mod(random_bytes_len).toNumber() : 0;
|
||||
@ -256,7 +253,7 @@ export default class SsrAuthChainPreset extends IPreset {
|
||||
const hmac_key = Buffer.concat([userKey, ntb(this._encodeChunkId, 4, BYTE_ORDER_LE)]);
|
||||
const chunk_hmac = hmac('md5', hmac_key, chunk);
|
||||
chunk = Buffer.concat([chunk, chunk_hmac.slice(0, 2)]);
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
if (SsrAuthChainPreset.config.is_client) {
|
||||
this._lastClientHash = chunk_hmac;
|
||||
} else {
|
||||
this._lastServerHash = chunk_hmac;
|
||||
@ -353,9 +350,9 @@ export default class SsrAuthChainPreset extends IPreset {
|
||||
if (buffer.length < 2 || this._adBuf === null) {
|
||||
return; // too short to get size
|
||||
}
|
||||
const hash = this._ctx.IS_CLIENT ? this._lastServerHash : this._lastClientHash;
|
||||
const hash = SsrAuthChainPreset.config.is_client ? this._lastServerHash : this._lastClientHash;
|
||||
const payload_len = buffer.readUInt16LE(0) ^ hash.readUInt16LE(14);
|
||||
const rng = this._ctx.IS_CLIENT ? this._rngServer : this._rngClient;
|
||||
const rng = SsrAuthChainPreset.config.is_client ? this._rngServer : this._rngClient;
|
||||
const random_bytes_len = this.getRandomBytesLengthForTcp(hash, payload_len, rng);
|
||||
const chunk_size = 2 + random_bytes_len + payload_len + 2;
|
||||
if (chunk_size >= 4096) {
|
||||
@ -379,9 +376,9 @@ export default class SsrAuthChainPreset extends IPreset {
|
||||
return fail(`unexpected chunk hmac, chunk=${dumpHex(chunk)}`);
|
||||
}
|
||||
// drop random_bytes, get encrypted payload
|
||||
const hash = this._ctx.IS_CLIENT ? this._lastServerHash : this._lastClientHash;
|
||||
const hash = SsrAuthChainPreset.config.is_client ? this._lastServerHash : this._lastClientHash;
|
||||
const payload_len = chunk.readUInt16LE(0) ^ hash.readUInt16LE(14);
|
||||
const rng = this._ctx.IS_CLIENT ? this._rngServer : this._rngClient;
|
||||
const rng = SsrAuthChainPreset.config.is_client ? this._rngServer : this._rngClient;
|
||||
const random_bytes_len = this.getRandomBytesLengthForTcp(hash, payload_len, rng);
|
||||
let enc_payload = null;
|
||||
if (random_bytes_len > 0) {
|
||||
@ -393,12 +390,12 @@ export default class SsrAuthChainPreset extends IPreset {
|
||||
// decrypt payload
|
||||
let payload = this._decipher.update(enc_payload);
|
||||
// update hash
|
||||
if (this._ctx.IS_CLIENT) {
|
||||
if (SsrAuthChainPreset.config.is_client) {
|
||||
this._lastServerHash = new_hash;
|
||||
} else {
|
||||
this._lastClientHash = new_hash;
|
||||
}
|
||||
if (this._ctx.IS_CLIENT && this._decodeChunkId === 1) {
|
||||
if (SsrAuthChainPreset.config.is_client && this._decodeChunkId === 1) {
|
||||
this._tcpMss = payload.readUInt16LE(0);
|
||||
payload = payload.slice(2);
|
||||
}
|
||||
|
@ -29,13 +29,6 @@ export default class TrackerPreset extends IPreset {
|
||||
_targetHost;
|
||||
_targetPort;
|
||||
|
||||
_ctx = null;
|
||||
|
||||
constructor(_, ctx) {
|
||||
super();
|
||||
this._ctx = ctx;
|
||||
}
|
||||
|
||||
onNotified({type, payload}) {
|
||||
switch (type) {
|
||||
case CONNECTION_CREATED: {
|
||||
@ -102,7 +95,7 @@ export default class TrackerPreset extends IPreset {
|
||||
if (strs.length > TRACK_MAX_SIZE) {
|
||||
strs = strs.slice(0, perSize).concat([' ... ']).concat(strs.slice(-perSize));
|
||||
}
|
||||
const summary = this._ctx.IS_CLIENT ? `out/in = ${up}/${dp}, ${ub}b/${db}b` : `in/out = ${dp}/${up}, ${db}b/${ub}b`;
|
||||
const summary = TrackerPreset.config.is_client ? `out/in = ${up}/${dp}, ${ub}b/${db}b` : `in/out = ${dp}/${up}, ${db}b/${ub}b`;
|
||||
logger.info(`[tracker:${this._transport}] summary(${summary}) abstract(${strs.join(' ')})`);
|
||||
}
|
||||
|
||||
|
@ -192,8 +192,6 @@ export default class V2rayVmessPreset extends IPresetAddressing {
|
||||
_cipherNonce = 0;
|
||||
_decipherNonce = 0;
|
||||
|
||||
_ctx = null;
|
||||
|
||||
static checkParams({id, security = 'aes-128-gcm'}) {
|
||||
if (Buffer.from(id.split('-').join(''), 'hex').length !== 16) {
|
||||
throw Error('id is not a valid uuid');
|
||||
@ -204,9 +202,9 @@ export default class V2rayVmessPreset extends IPresetAddressing {
|
||||
}
|
||||
}
|
||||
|
||||
static onInit({id, security = 'aes-128-gcm'}, {IS_CLIENT}) {
|
||||
static onInit({id, security = 'aes-128-gcm'}) {
|
||||
V2rayVmessPreset.uuid = Buffer.from(id.split('-').join(''), 'hex');
|
||||
if (IS_CLIENT) {
|
||||
if (V2rayVmessPreset.config.is_client) {
|
||||
V2rayVmessPreset.security = securityTypes[security];
|
||||
}
|
||||
setInterval(() => V2rayVmessPreset.updateAuthCache(), 1e3);
|
||||
@ -233,9 +231,8 @@ export default class V2rayVmessPreset extends IPresetAddressing {
|
||||
this.userHashCache = newItems;
|
||||
}
|
||||
|
||||
constructor(_, ctx) {
|
||||
constructor() {
|
||||
super();
|
||||
this._ctx = ctx;
|
||||
this._adBuf = new AdvancedBuffer({getPacketLength: this.onReceiving.bind(this)});
|
||||
this._adBuf.on('data', this.onChunkReceived.bind(this));
|
||||
}
|
||||
@ -257,7 +254,7 @@ export default class V2rayVmessPreset extends IPresetAddressing {
|
||||
}
|
||||
|
||||
onNotified(action) {
|
||||
if (this._ctx.IS_CLIENT && action.type === CONNECT_TO_REMOTE) {
|
||||
if (V2rayVmessPreset.config.is_client && action.type === CONNECT_TO_REMOTE) {
|
||||
const {host, port} = action.payload;
|
||||
const type = getAddrType(host);
|
||||
this._atyp = type;
|
||||
@ -272,7 +269,7 @@ export default class V2rayVmessPreset extends IPresetAddressing {
|
||||
beforeOut({buffer}) {
|
||||
if (!this._isHeaderSent) {
|
||||
this._isHeaderSent = true;
|
||||
const header = this._ctx.IS_CLIENT ? this.createRequestHeader() : this.createResponseHeader();
|
||||
const header = V2rayVmessPreset.config.is_client ? this.createRequestHeader() : this.createResponseHeader();
|
||||
const chunks = this.getBufferChunks(buffer);
|
||||
return Buffer.concat([header, ...chunks]);
|
||||
} else {
|
||||
|
@ -5,12 +5,12 @@ import EventEmitter from 'events';
|
||||
class Bound extends EventEmitter {
|
||||
|
||||
_ctx = null;
|
||||
_globalCtx = null;
|
||||
_config = null;
|
||||
|
||||
constructor({context, globalContext}) {
|
||||
constructor({context, config}) {
|
||||
super();
|
||||
this._ctx = context;
|
||||
this._globalCtx = globalContext;
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
get ctx() {
|
||||
|
@ -7,7 +7,7 @@ export class MuxInbound extends Inbound {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onDrain = this.onDrain.bind(this);
|
||||
if (this._globalCtx.IS_SERVER) {
|
||||
if (this._config.is_server) {
|
||||
const inbound = this.ctx.muxRelay.getInbound();
|
||||
inbound.on('drain', this.onDrain);
|
||||
} else {
|
||||
@ -20,7 +20,7 @@ export class MuxInbound extends Inbound {
|
||||
}
|
||||
|
||||
get bufferSize() {
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
const totalBufferSize = 0;
|
||||
// const subRelays = this.ctx.thisRelay.getSubRelays();
|
||||
// if (subRelays) {
|
||||
@ -70,7 +70,7 @@ export class MuxInbound extends Inbound {
|
||||
}
|
||||
|
||||
write(buffer) {
|
||||
if (this._globalCtx.IS_SERVER) {
|
||||
if (this._config.is_server) {
|
||||
const {muxRelay, cid} = this.ctx;
|
||||
muxRelay.encode(buffer, {cid});
|
||||
}
|
||||
@ -83,7 +83,7 @@ export class MuxInbound extends Inbound {
|
||||
|
||||
close() {
|
||||
const doClose = () => {
|
||||
if (this._globalCtx.IS_SERVER) {
|
||||
if (this._config.is_server) {
|
||||
const {muxRelay, cid} = this.ctx;
|
||||
const inbound = muxRelay.getInbound();
|
||||
if (inbound) {
|
||||
@ -112,7 +112,7 @@ export class MuxOutbound extends Outbound {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onDrain = this.onDrain.bind(this);
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
const outbound = this.ctx.muxRelay.getOutbound();
|
||||
outbound.on('drain', this.onDrain);
|
||||
} else {
|
||||
@ -121,7 +121,7 @@ export class MuxOutbound extends Outbound {
|
||||
}
|
||||
|
||||
get bufferSize() {
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
const outbound = this.ctx.muxRelay.getOutbound();
|
||||
if (outbound) {
|
||||
return outbound.bufferSize;
|
||||
@ -148,7 +148,7 @@ export class MuxOutbound extends Outbound {
|
||||
}
|
||||
|
||||
write(buffer) {
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
const {muxRelay, proxyRequest, cid} = this.ctx;
|
||||
if (this._isFirstFrame) {
|
||||
this._isFirstFrame = false;
|
||||
@ -166,7 +166,7 @@ export class MuxOutbound extends Outbound {
|
||||
|
||||
close() {
|
||||
const doClose = () => {
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
const {muxRelay, cid} = this.ctx;
|
||||
const outbound = muxRelay.getOutbound();
|
||||
if (outbound) {
|
||||
|
@ -35,7 +35,7 @@ export class TcpInbound extends Inbound {
|
||||
this._socket.on('timeout', this.onTimeout);
|
||||
this._socket.on('end', this.onHalfClose);
|
||||
this._socket.on('close', this.onClose);
|
||||
this._socket.setTimeout && this._socket.setTimeout(this._globalCtx.TIMEOUT);
|
||||
this._socket.setTimeout && this._socket.setTimeout(this._config.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ export class TcpInbound extends Inbound {
|
||||
}
|
||||
|
||||
onReceive(buffer) {
|
||||
const direction = this._globalCtx.IS_CLIENT ? PIPE_ENCODE : PIPE_DECODE;
|
||||
const direction = this._config.is_client ? PIPE_ENCODE : PIPE_DECODE;
|
||||
this.ctx.pipe.feed(direction, buffer);
|
||||
// throttle receiving data to reduce memory grow:
|
||||
// https://github.com/blinksocks/blinksocks/issues/60
|
||||
@ -85,7 +85,7 @@ export class TcpInbound extends Inbound {
|
||||
}
|
||||
|
||||
onTimeout() {
|
||||
logger.warn(`[${this.name}] [${this.remote}] timeout: no I/O on the connection for ${this._globalCtx.TIMEOUT / 1e3}s`);
|
||||
logger.warn(`[${this.name}] [${this.remote}] timeout: no I/O on the connection for ${this._config.timeout / 1e3}s`);
|
||||
this.onClose();
|
||||
}
|
||||
|
||||
@ -153,16 +153,16 @@ export class TcpInbound extends Inbound {
|
||||
logger.error(`[${this.name}] [${this.remote}] preset "${name}" fail to process: ${message}`);
|
||||
|
||||
// close connection directly on client side
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
logger.warn(`[${this.name}] [${this.remote}] connection closed`);
|
||||
this.onClose();
|
||||
}
|
||||
|
||||
// for server side, redirect traffic if "redirect" is set, otherwise, close connection after a random timeout
|
||||
if (this._globalCtx.IS_SERVER && !this._globalCtx.MUX) {
|
||||
if (this._globalCtx.REDIRECT) {
|
||||
if (this._config.is_server && !this._config.mux) {
|
||||
if (this._config.redirect) {
|
||||
const {orgData} = action.payload;
|
||||
const [host, port] = this._globalCtx.REDIRECT.split(':');
|
||||
const [host, port] = this._config.redirect.split(':');
|
||||
|
||||
logger.warn(`[${this.name}] [${this.remote}] connection is redirecting to: ${host}:${port}`);
|
||||
|
||||
@ -189,11 +189,11 @@ export class TcpInbound extends Inbound {
|
||||
}
|
||||
|
||||
onPresetPauseRecv() {
|
||||
this._globalCtx.IS_SERVER && (this._socket && this._socket.pause())
|
||||
this._config.is_server && (this._socket && this._socket.pause())
|
||||
}
|
||||
|
||||
onPresetResumeRecv() {
|
||||
this._globalCtx.IS_SERVER && (this._socket && this._socket.resume());
|
||||
this._config.is_server && (this._socket && this._socket.resume());
|
||||
}
|
||||
|
||||
}
|
||||
@ -237,7 +237,7 @@ export class TcpOutbound extends Outbound {
|
||||
}
|
||||
|
||||
onReceive(buffer) {
|
||||
const direction = this._globalCtx.IS_CLIENT ? PIPE_DECODE : PIPE_ENCODE;
|
||||
const direction = this._config.is_client ? PIPE_DECODE : PIPE_ENCODE;
|
||||
this.ctx.pipe.feed(direction, buffer);
|
||||
// throttle receiving data to reduce memory grow:
|
||||
// https://github.com/blinksocks/blinksocks/issues/60
|
||||
@ -260,7 +260,7 @@ export class TcpOutbound extends Outbound {
|
||||
}
|
||||
|
||||
onTimeout() {
|
||||
logger.warn(`[${this.name}] [${this.remote}] timeout: no I/O on the connection for ${this._globalCtx.TIMEOUT / 1e3}s`);
|
||||
logger.warn(`[${this.name}] [${this.remote}] timeout: no I/O on the connection for ${this._config.timeout / 1e3}s`);
|
||||
this.onClose();
|
||||
}
|
||||
|
||||
@ -318,17 +318,17 @@ export class TcpOutbound extends Outbound {
|
||||
const {host, port, keepAlive, onConnected} = action.payload;
|
||||
if (!keepAlive || !this._socket) {
|
||||
try {
|
||||
if (this._globalCtx.IS_SERVER) {
|
||||
if (this._config.is_server) {
|
||||
await this.connect({host, port});
|
||||
}
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
await this.connect({host: this._globalCtx.SERVER_HOST, port: this._globalCtx.SERVER_PORT});
|
||||
if (this._config.is_client) {
|
||||
await this.connect({host: this._config.server_host, port: this._config.server_port});
|
||||
}
|
||||
this._socket.on('connect', () => {
|
||||
if (typeof onConnected === 'function') {
|
||||
onConnected((buffer) => {
|
||||
if (buffer) {
|
||||
const type = this._globalCtx.IS_CLIENT ? PIPE_ENCODE : PIPE_DECODE;
|
||||
const type = this._config.is_client ? PIPE_ENCODE : PIPE_DECODE;
|
||||
this.ctx.pipe.feed(type, buffer, {cid: this.ctx.proxyRequest.cid, host, port});
|
||||
}
|
||||
});
|
||||
@ -345,11 +345,11 @@ export class TcpOutbound extends Outbound {
|
||||
}
|
||||
|
||||
onPresetPauseSend() {
|
||||
this._globalCtx.IS_SERVER && (this._socket && this._socket.pause());
|
||||
this._config.is_server && (this._socket && this._socket.pause());
|
||||
}
|
||||
|
||||
onPresetResumeSend() {
|
||||
this._globalCtx.IS_SERVER && (this._socket && this._socket.resume());
|
||||
this._config.is_server && (this._socket && this._socket.resume());
|
||||
}
|
||||
|
||||
async connect({host, port}) {
|
||||
@ -364,7 +364,7 @@ export class TcpOutbound extends Outbound {
|
||||
this._socket.on('timeout', this.onTimeout);
|
||||
this._socket.on('data', this.onReceive);
|
||||
this._socket.on('drain', this.onDrain);
|
||||
this._socket.setTimeout(this._globalCtx.TIMEOUT);
|
||||
this._socket.setTimeout(this._config.timeout);
|
||||
}
|
||||
|
||||
async _connect({host, port}) {
|
||||
|
@ -29,7 +29,7 @@ export class TlsOutbound extends TcpOutbound {
|
||||
// overwrite _connect of tcp outbound using tls.connect()
|
||||
async _connect({host, port}) {
|
||||
logger.info(`[tls:outbound] [${this.remote}] connecting to tls://${host}:${port}`);
|
||||
return tls.connect({host, port, ca: [this._globalCtx.TLS_CERT]});
|
||||
return tls.connect({host, port, ca: [this._config.tls_cert]});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ export class UdpInbound extends Inbound {
|
||||
}
|
||||
|
||||
onReceive(buffer, rinfo) {
|
||||
const type = this._globalCtx.IS_CLIENT ? PIPE_ENCODE : PIPE_DECODE;
|
||||
const type = this._config.is_client ? PIPE_ENCODE : PIPE_DECODE;
|
||||
this._rinfo = rinfo;
|
||||
this.ctx.pipe.feed(type, buffer);
|
||||
}
|
||||
@ -51,7 +51,7 @@ export class UdpInbound extends Inbound {
|
||||
logger.warn(`[udp:inbound] [${this.remote}]:`, err);
|
||||
}
|
||||
};
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
if (this._config.is_client) {
|
||||
const isSs = this.ctx.pipe.presets.some(({name}) => ['ss-base'].includes(name));
|
||||
this._socket.send(buffer, port, address, isSs, onSendError);
|
||||
} else {
|
||||
@ -85,7 +85,7 @@ export class UdpOutbound extends Outbound {
|
||||
}
|
||||
|
||||
onReceive(buffer) {
|
||||
const type = this._globalCtx.IS_CLIENT ? PIPE_DECODE : PIPE_ENCODE;
|
||||
const type = this._config.is_client ? PIPE_DECODE : PIPE_ENCODE;
|
||||
this.ctx.pipe.feed(type, buffer);
|
||||
}
|
||||
|
||||
@ -121,11 +121,11 @@ export class UdpOutbound extends Outbound {
|
||||
|
||||
onConnectToRemote(action) {
|
||||
const {host, port, onConnected} = action.payload;
|
||||
if (this._globalCtx.IS_CLIENT) {
|
||||
this._targetHost = this._globalCtx.SERVER_HOST;
|
||||
this._targetPort = this._globalCtx.SERVER_PORT;
|
||||
if (this._config.is_client) {
|
||||
this._targetHost = this._config.server_host;
|
||||
this._targetPort = this._config.server_port;
|
||||
}
|
||||
if (this._globalCtx.IS_SERVER) {
|
||||
if (this._config.is_server) {
|
||||
this._targetHost = host;
|
||||
this._targetPort = port;
|
||||
if (typeof onConnected === 'function') {
|
||||
|
@ -5,13 +5,15 @@ import {Middleware} from '../../src/core/middleware';
|
||||
|
||||
|
||||
export class PresetRunner extends EventEmitter {
|
||||
_ctx = null;
|
||||
_config = null;
|
||||
|
||||
constructor({name, params = {}}, context = {}) {
|
||||
constructor({name, params = {}}, config = {}) {
|
||||
super();
|
||||
this._ctx = context;
|
||||
getPresetClassByName(name).checkParams(params);
|
||||
this.middleware = new Middleware({name, params}, context);
|
||||
this._config = config;
|
||||
const clazz = getPresetClassByName(name);
|
||||
clazz.config = config;
|
||||
clazz.checkParams(params);
|
||||
this.middleware = new Middleware({name, params}, config);
|
||||
}
|
||||
|
||||
notify(action) {
|
||||
@ -32,7 +34,7 @@ export class PresetRunner extends EventEmitter {
|
||||
this.middleware.on('fail', reject);
|
||||
this.middleware.on('broadcast', (name, action) => this.emit('broadcast', action));
|
||||
this.middleware.write({
|
||||
direction: this._ctx.IS_CLIENT ? PIPE_ENCODE : PIPE_DECODE,
|
||||
direction: this._config.is_client ? PIPE_ENCODE : PIPE_DECODE,
|
||||
buffer: data,
|
||||
direct: resolve,
|
||||
isUdp
|
||||
@ -50,7 +52,7 @@ export class PresetRunner extends EventEmitter {
|
||||
this.middleware.on('fail', reject);
|
||||
this.middleware.on('broadcast', (name, action) => this.emit('broadcast', action));
|
||||
this.middleware.write({
|
||||
direction: this._ctx.IS_CLIENT ? PIPE_DECODE : PIPE_ENCODE,
|
||||
direction: this._config.is_client ? PIPE_DECODE : PIPE_ENCODE,
|
||||
buffer: data,
|
||||
direct: resolve,
|
||||
isUdp
|
||||
|
@ -14,8 +14,8 @@ test('running on both client and server', async () => {
|
||||
acl: path.join(__dirname, 'acl.txt')
|
||||
}
|
||||
}, {
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
await sleep(20);
|
||||
|
@ -7,9 +7,9 @@ test('running on client and server', async () => {
|
||||
method: 'aes-128-gcm'
|
||||
}
|
||||
}, {
|
||||
KEY: 'secret',
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
key: 'secret',
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
const packet_1 = await runner.forward('12');
|
||||
|
@ -5,9 +5,9 @@ test('tcp relay on client and server', async () => {
|
||||
let runner = new PresetRunner({
|
||||
name: 'base-auth'
|
||||
}, {
|
||||
KEY: 'secret',
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
key: 'secret',
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
// client
|
||||
@ -36,9 +36,9 @@ test('tcp relay on client and server', async () => {
|
||||
runner = new PresetRunner({
|
||||
name: 'base-auth'
|
||||
}, {
|
||||
KEY: 'secret',
|
||||
IS_CLIENT: false,
|
||||
IS_SERVER: true
|
||||
key: 'secret',
|
||||
is_client: false,
|
||||
is_server: true
|
||||
});
|
||||
|
||||
runner.on('broadcast', (action) => {
|
||||
@ -61,9 +61,9 @@ test('udp relay on client and server', async () => {
|
||||
let runner = new PresetRunner({
|
||||
name: 'base-auth'
|
||||
}, {
|
||||
KEY: 'secret',
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
key: 'secret',
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
// client
|
||||
@ -86,9 +86,9 @@ test('udp relay on client and server', async () => {
|
||||
runner = new PresetRunner({
|
||||
name: 'base-auth'
|
||||
}, {
|
||||
KEY: 'secret',
|
||||
IS_CLIENT: false,
|
||||
IS_SERVER: true
|
||||
key: 'secret',
|
||||
is_client: false,
|
||||
is_server: true
|
||||
});
|
||||
|
||||
runner.on('broadcast', (action) => {
|
||||
|
@ -4,8 +4,8 @@ test('running on both client and server', async () => {
|
||||
const runner = new PresetRunner({
|
||||
name: 'obfs-random-padding'
|
||||
}, {
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
const chunk = await runner.forward('12');
|
||||
|
@ -7,9 +7,9 @@ test('tcp relay on client and server', async () => {
|
||||
method: 'aes-128-gcm'
|
||||
}
|
||||
}, {
|
||||
KEY: 'secret',
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
key: 'secret',
|
||||
is_client: true,
|
||||
is_serevr: false
|
||||
});
|
||||
|
||||
const packet_1 = await runner.forward('12');
|
||||
@ -38,9 +38,9 @@ test('udp relay on client and server', async () => {
|
||||
method: 'aes-128-gcm'
|
||||
}
|
||||
}, {
|
||||
KEY: 'secret',
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
key: 'secret',
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
const packet = await runner.forwardUdp('12');
|
||||
|
@ -5,8 +5,8 @@ test('running on client', async () => {
|
||||
const runner = new PresetRunner({
|
||||
name: 'ss-base'
|
||||
}, {
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
runner.notify({
|
||||
@ -40,8 +40,8 @@ test('running on server', async () => {
|
||||
const runner = new PresetRunner({
|
||||
name: 'ss-base'
|
||||
}, {
|
||||
IS_CLIENT: false,
|
||||
IS_SERVER: true
|
||||
is_client: false,
|
||||
is_server: true
|
||||
});
|
||||
|
||||
runner.on('broadcast', (action) => {
|
||||
|
@ -7,9 +7,9 @@ test('tcp relay on client and server', async () => {
|
||||
method: 'aes-128-ctr'
|
||||
}
|
||||
}, {
|
||||
KEY: 'secret',
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
key: 'secret',
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
// should add 16 more bytes at the beginning
|
||||
@ -35,9 +35,9 @@ test('udp relay on client and server', async () => {
|
||||
method: 'rc4-md5-6'
|
||||
}
|
||||
}, {
|
||||
KEY: 'secret',
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
key: 'secret',
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
expect(await runner.forwardUdp('1')).toHaveLength(6 + 1);
|
||||
|
@ -13,8 +13,8 @@ test('running on both client and server', async () => {
|
||||
save_interval: 1
|
||||
}
|
||||
}, {
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
runner.notify({type: CONNECTION_CREATED});
|
||||
|
@ -5,8 +5,8 @@ test('tcp relay on client and server', async () => {
|
||||
const runner = new PresetRunner({
|
||||
name: 'tracker'
|
||||
}, {
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
const actionPayload = {
|
||||
@ -33,8 +33,8 @@ test('udp relay on client and server', async () => {
|
||||
const runner = new PresetRunner({
|
||||
name: 'tracker'
|
||||
}, {
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
expect(await runner.forwardUdp('12')).toMatchSnapshot();
|
||||
|
@ -9,8 +9,8 @@ test('running on client', async () => {
|
||||
security: 'aes-128-gcm'
|
||||
}
|
||||
}, {
|
||||
IS_CLIENT: true,
|
||||
IS_SERVER: false
|
||||
is_client: true,
|
||||
is_server: false
|
||||
});
|
||||
|
||||
runner.notify({
|
||||
@ -40,8 +40,8 @@ test('running on server', async () => {
|
||||
id: 'a3482e88-686a-4a58-8126-99c9df64b7bf'
|
||||
}
|
||||
}, {
|
||||
IS_CLIENT: false,
|
||||
IS_SERVER: true
|
||||
is_client: false,
|
||||
is_server: true
|
||||
});
|
||||
|
||||
// fail on wrong data
|
||||
|
Loading…
Reference in New Issue
Block a user