parent
31ac8aff46
commit
0079380d36
44
bin/bootstrap.js
vendored
44
bin/bootstrap.js
vendored
@ -7,22 +7,13 @@ const packageJson = require('../package.json');
|
||||
const BOOTSTRAP_TYPE_SERVER = 1;
|
||||
|
||||
const version = packageJson.version;
|
||||
const usage = '--host <host> --port <port> --key <key> [...]';
|
||||
const usage = '--config <file> --host <host> --port <port> --key <key> [...]';
|
||||
|
||||
const options = [
|
||||
['-c, --config [file]', 'a json format file for configuration', ''],
|
||||
['-c, --config <file>', 'a json/js format file for configuration', ''],
|
||||
['--host <host>', 'an ip address or a hostname to bind, default: \'localhost\'', 'localhost'],
|
||||
['--port <port>', 'where to listen on, default: 1080', 1080],
|
||||
['--servers [servers]', 'a list of servers used by client, split by comma, default: \'\'', (value) => value.split(','), []],
|
||||
['--key <key>', 'a key for encryption and decryption'],
|
||||
['--frame [frame]', 'a preset used in frame middleware, default: \'origin\'', 'origin'],
|
||||
['--frame-params [crypto-params]', 'parameters for frame preset, default: \'\'', ''],
|
||||
['--crypto [crypto]', 'a preset used in crypto middleware, default: \'\'', ''],
|
||||
['--crypto-params [crypto-params]', 'parameters for crypto, default: \'aes-256-cfb\'', 'aes-256-cfb'],
|
||||
['--protocol [protocol]', 'a preset used in protocol middleware, default: \'aead\'', 'aead'],
|
||||
['--protocol-params [protocol-params]', 'parameters for protocol, default: \'aes-256-gcm,ss-subkey\'', 'aes-256-gcm,ss-subkey'],
|
||||
['--obfs [obfs]', 'a preset used in obfs middleware, default: \'\'', ''],
|
||||
['--obfs-params [obfs-params]', 'parameters for obfs, default: \'\'', ''],
|
||||
['--redirect [redirect]', 'redirect stream to here when any preset fail to process, default: \'\'', ''],
|
||||
['--log-level [log-level]', 'log level, default: \'silly\'', 'silly'],
|
||||
['--timeout [timeout]', 'time to close connection if inactive, default: 600', 600],
|
||||
@ -35,13 +26,8 @@ const examples = `
|
||||
Examples:
|
||||
|
||||
As simple as possible:
|
||||
$ blinksocks client -c config.json --watch
|
||||
|
||||
To start a server:
|
||||
$ blinksocks server --host 0.0.0.0 --port 7777 --key password
|
||||
|
||||
To start a client:
|
||||
$ blinksocks client --host localhost --port 1080 --key password --servers=node1.test.com:7777,node2.test.com:7777
|
||||
$ blinksocks client -c config.js
|
||||
$ blinksocks server -c config.js
|
||||
`;
|
||||
|
||||
/**
|
||||
@ -52,16 +38,7 @@ const examples = `
|
||||
*/
|
||||
function obtainConfig(type, options) {
|
||||
// CLI options should be able to overwrite options specified in --config
|
||||
const {host, servers, key, quiet} = options;
|
||||
const {frame, crypto, protocol, obfs, redirect} = options;
|
||||
|
||||
// renames
|
||||
const [frame_params, crypto_params, protocol_params, obfs_params] = [
|
||||
options.frameParams,
|
||||
options.cryptoParams,
|
||||
options.protocolParams,
|
||||
options.obfsParams
|
||||
];
|
||||
const {host, servers, key, presets, redirect, quiet} = options;
|
||||
|
||||
// pre-process
|
||||
const [port, log_level, timeout, watch, profile] = [
|
||||
@ -78,14 +55,7 @@ function obtainConfig(type, options) {
|
||||
port,
|
||||
servers,
|
||||
key,
|
||||
frame,
|
||||
frame_params,
|
||||
crypto,
|
||||
crypto_params,
|
||||
protocol,
|
||||
protocol_params,
|
||||
obfs,
|
||||
obfs_params,
|
||||
presets,
|
||||
redirect,
|
||||
log_level,
|
||||
timeout,
|
||||
@ -159,7 +129,7 @@ module.exports = function (type, {Hub, Config}) {
|
||||
app.run();
|
||||
process.on('SIGINT', () => app.onClose());
|
||||
} catch (err) {
|
||||
console.error(err.message);
|
||||
console.error(err);
|
||||
process.exit(-1);
|
||||
}
|
||||
};
|
||||
|
@ -21,14 +21,14 @@ module.exports = {
|
||||
"host": "localhost",
|
||||
"port": 1080,
|
||||
"servers": [],
|
||||
"key": "${random('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+<>?:|{}ABCDEFGHIJKLMNOPQRSTUVWXYZ', 16)}",
|
||||
"key": "${random('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+<>?:|{}-=[];,./ABCDEFGHIJKLMNOPQRSTUVWXYZ', 16)}",
|
||||
"presets": [{
|
||||
"name": "origin",
|
||||
"name": "ss-base",
|
||||
"params": {}
|
||||
}, {
|
||||
"name": "aead",
|
||||
"name": "ss-aead-cipher",
|
||||
"params": {
|
||||
"method": "aes-128-gcm",
|
||||
"method": "aes-256-gcm",
|
||||
"info": "ss-subkey"
|
||||
}
|
||||
}],
|
||||
@ -41,8 +41,4 @@ module.exports = {
|
||||
|
||||
const file = 'blinksocks.config.js';
|
||||
|
||||
fs.writeFile(file, js, function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
fs.writeFileSync(file, js);
|
||||
|
@ -15,21 +15,7 @@ export class Config {
|
||||
|
||||
static key;
|
||||
|
||||
static frame;
|
||||
|
||||
static frame_params;
|
||||
|
||||
static crypto;
|
||||
|
||||
static crypto_params;
|
||||
|
||||
static protocol;
|
||||
|
||||
static protocol_params;
|
||||
|
||||
static obfs;
|
||||
|
||||
static obfs_params;
|
||||
static presets;
|
||||
|
||||
static redirect;
|
||||
|
||||
@ -105,57 +91,33 @@ export class Config {
|
||||
|
||||
this.key = json.key;
|
||||
|
||||
// frame & frame_params
|
||||
// presets & presets' parameters
|
||||
|
||||
if (typeof json.frame !== 'string') {
|
||||
throw Error('\'frame\' must be a string');
|
||||
if (!Array.isArray(json.presets)) {
|
||||
throw Error('\'presets\' must be an array');
|
||||
}
|
||||
|
||||
if (typeof json.frame_params !== 'string') {
|
||||
throw Error('\'frame_params\' must be a string');
|
||||
if (json.presets.length < 1) {
|
||||
throw Error('\'presets\' must contain at least one preset');
|
||||
}
|
||||
|
||||
this.frame = json.frame || 'origin';
|
||||
this.frame_params = json.frame_params;
|
||||
for (const preset of json.presets) {
|
||||
const {name, params} = preset;
|
||||
|
||||
// crypto & crypto_params
|
||||
if (typeof name === 'undefined') {
|
||||
throw Error('\'preset.name\' must be a string');
|
||||
}
|
||||
|
||||
if (typeof json.crypto !== 'string') {
|
||||
throw Error('\'crypto\' must be a string');
|
||||
// 1. check for the existence of the preset
|
||||
const ps = require(`../presets/${preset.name}`).default;
|
||||
|
||||
// 2. check parameters, but ignore the first preset
|
||||
if (name !== json.presets[0].name) {
|
||||
delete new ps(params || {});
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof json.crypto_params !== 'string') {
|
||||
throw Error('\'crypto_params\' must be a string');
|
||||
}
|
||||
|
||||
this.crypto = json.crypto || 'none';
|
||||
this.crypto_params = json.crypto_params;
|
||||
|
||||
// protocol & protocol_params
|
||||
|
||||
if (typeof json.protocol !== 'string') {
|
||||
throw Error('\'protocol\' must be a string');
|
||||
}
|
||||
|
||||
if (typeof json.protocol_params !== 'string') {
|
||||
throw Error('\'protocol_params\' must be a string');
|
||||
}
|
||||
|
||||
this.protocol = json.protocol || 'none';
|
||||
this.protocol_params = json.protocol_params;
|
||||
|
||||
// obfs & obfs_params
|
||||
|
||||
if (typeof json.obfs !== 'string') {
|
||||
throw Error('\'obfs\' must be a string');
|
||||
}
|
||||
|
||||
if (typeof json.obfs_params !== 'string') {
|
||||
throw Error('\'obfs_params\' must be a string');
|
||||
}
|
||||
|
||||
this.obfs = json.obfs || 'none';
|
||||
this.obfs_params = json.obfs_params;
|
||||
this.presets = json.presets;
|
||||
|
||||
// redirect
|
||||
|
||||
@ -211,17 +173,7 @@ export class Config {
|
||||
|
||||
global.__KEY__ = this.key;
|
||||
|
||||
global.__FRAME__ = this.frame;
|
||||
global.__FRAME_PARAMS__ = this.frame_params;
|
||||
|
||||
global.__CRYPTO__ = this.crypto;
|
||||
global.__CRYPTO_PARAMS__ = this.crypto_params;
|
||||
|
||||
global.__PROTOCOL__ = this.protocol;
|
||||
global.__PROTOCOL_PARAMS__ = this.protocol_params;
|
||||
|
||||
global.__OBFS__ = this.obfs;
|
||||
global.__OBFS_PARAMS__ = this.obfs_params;
|
||||
global.__PRESETS__ = this.presets;
|
||||
|
||||
global.__REDIRECT__ = this.redirect;
|
||||
global.__TIMEOUT__ = this.timeout;
|
||||
|
@ -4,11 +4,6 @@ import logger from 'winston';
|
||||
export const MIDDLEWARE_DIRECTION_UPWARD = 0;
|
||||
export const MIDDLEWARE_DIRECTION_DOWNWARD = 1;
|
||||
|
||||
export const MIDDLEWARE_TYPE_FRAME = 0;
|
||||
export const MIDDLEWARE_TYPE_CRYPTO = 1;
|
||||
export const MIDDLEWARE_TYPE_PROTOCOL = 2;
|
||||
export const MIDDLEWARE_TYPE_OBFS = 3;
|
||||
|
||||
/**
|
||||
* abstraction of middleware
|
||||
*/
|
||||
@ -69,23 +64,14 @@ export class Middleware extends EventEmitter {
|
||||
|
||||
/**
|
||||
* create an instance of Middleware
|
||||
* @param type
|
||||
* @param props
|
||||
* @param name
|
||||
* @param params
|
||||
* @returns {Middleware}
|
||||
*/
|
||||
export function createMiddleware(type, props = []) {
|
||||
const [preset, params] = {
|
||||
[MIDDLEWARE_TYPE_FRAME]: [`frame/${__FRAME__}`, __FRAME_PARAMS__],
|
||||
[MIDDLEWARE_TYPE_CRYPTO]: [`crypto/${__CRYPTO__}`, __CRYPTO_PARAMS__],
|
||||
[MIDDLEWARE_TYPE_PROTOCOL]: [`protocol/${__PROTOCOL__}`, __PROTOCOL_PARAMS__],
|
||||
[MIDDLEWARE_TYPE_OBFS]: [`obfs/${__OBFS__}`, __OBFS_PARAMS__]
|
||||
}[type];
|
||||
|
||||
export function createMiddleware(name, params = {}) {
|
||||
try {
|
||||
const ImplClass = require(`../presets/${preset}`).default;
|
||||
const _params = Array.isArray(params) ? params : params.split(',').filter((param) => param.length > 0);
|
||||
|
||||
const impl = new ImplClass(...props.concat(_params));
|
||||
const ImplClass = require(`../presets/${name}`).default;
|
||||
const impl = new ImplClass(params);
|
||||
|
||||
checkMiddleware(ImplClass.name, impl);
|
||||
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
MIDDLEWARE_DIRECTION_UPWARD,
|
||||
MIDDLEWARE_DIRECTION_DOWNWARD
|
||||
} from './middleware';
|
||||
import {PROCESSING_FAILED} from '../presets/actions';
|
||||
import {PROCESSING_FAILED} from '../presets/defs';
|
||||
|
||||
export class Pipe extends EventEmitter {
|
||||
|
||||
|
@ -8,10 +8,6 @@ import {Profile} from './profile';
|
||||
import {
|
||||
MIDDLEWARE_DIRECTION_UPWARD,
|
||||
MIDDLEWARE_DIRECTION_DOWNWARD,
|
||||
MIDDLEWARE_TYPE_FRAME,
|
||||
MIDDLEWARE_TYPE_CRYPTO,
|
||||
MIDDLEWARE_TYPE_PROTOCOL,
|
||||
MIDDLEWARE_TYPE_OBFS,
|
||||
createMiddleware
|
||||
} from './middleware';
|
||||
|
||||
@ -19,7 +15,7 @@ import {Utils} from '../utils';
|
||||
import {
|
||||
SOCKET_CONNECT_TO_DST,
|
||||
PROCESSING_FAILED
|
||||
} from '../presets/actions';
|
||||
} from '../presets/defs';
|
||||
|
||||
import {
|
||||
UdpRequestMessage
|
||||
@ -252,12 +248,12 @@ export class Socket {
|
||||
}
|
||||
};
|
||||
this._pipe = new Pipe(pipeProps);
|
||||
this._pipe.setMiddlewares(MIDDLEWARE_DIRECTION_UPWARD, [
|
||||
createMiddleware(MIDDLEWARE_TYPE_FRAME, [addr]),
|
||||
createMiddleware(MIDDLEWARE_TYPE_CRYPTO),
|
||||
createMiddleware(MIDDLEWARE_TYPE_PROTOCOL),
|
||||
createMiddleware(MIDDLEWARE_TYPE_OBFS),
|
||||
]);
|
||||
this._pipe.setMiddlewares(MIDDLEWARE_DIRECTION_UPWARD,
|
||||
__PRESETS__.map((preset, i) => createMiddleware(preset.name, {
|
||||
...preset.params,
|
||||
...(i === 0 ? addr : {})
|
||||
}))
|
||||
);
|
||||
this._pipe.on(`next_${MIDDLEWARE_DIRECTION_UPWARD}`, (buf) => this.send(buf, __IS_CLIENT__));
|
||||
this._pipe.on(`next_${MIDDLEWARE_DIRECTION_DOWNWARD}`, (buf) => this.send(buf, __IS_SERVER__));
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
export const SOCKET_CONNECT_TO_DST = 'socket/connect/to/dst';
|
||||
export const PROCESSING_FAILED = 'processing/failed';
|
@ -1,21 +0,0 @@
|
||||
import {IPreset} from '../interface';
|
||||
|
||||
export default class NoneCrypto extends IPreset {
|
||||
|
||||
clientOut({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
serverIn({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
serverOut({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
clientIn({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
export const SOCKET_CONNECT_TO_DST = 'socket/connect/to/dst';
|
||||
export const PROCESSING_FAILED = 'processing/failed';
|
||||
|
||||
export class IPreset {
|
||||
|
||||
/**
|
@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import readline from 'readline';
|
||||
import crypto from 'crypto';
|
||||
import {IPreset} from '../interface';
|
||||
import {IPreset} from './defs';
|
||||
|
||||
class Faker {
|
||||
|
||||
@ -61,11 +61,15 @@ class Faker {
|
||||
* Wrap packet with pre-shared HTTP header.
|
||||
*
|
||||
* @params
|
||||
* file (String): A text file which contains several HTTP header paris.
|
||||
* file: A text file which contains several HTTP header paris.
|
||||
*
|
||||
* @examples
|
||||
* "obfs": "http"
|
||||
* "obfs_params": "http-fake.txt"
|
||||
* {
|
||||
* "name": "http",
|
||||
* "params": {
|
||||
* "file": "http-fake.txt"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @protocol
|
||||
*
|
||||
@ -83,7 +87,7 @@ class Faker {
|
||||
* | Variable |
|
||||
* +----------------------------+
|
||||
*/
|
||||
export default class HttpObfs extends IPreset {
|
||||
export default class HttpPreset extends IPreset {
|
||||
|
||||
_isHandshakeDone = false;
|
||||
|
||||
@ -91,10 +95,10 @@ export default class HttpObfs extends IPreset {
|
||||
|
||||
_response = null;
|
||||
|
||||
constructor(file) {
|
||||
constructor({file}) {
|
||||
super();
|
||||
if (typeof file === 'undefined') {
|
||||
throw Error('\'obfs_params\' requires at least one parameter.');
|
||||
throw Error('\'file\' parameter is required.');
|
||||
}
|
||||
this._file = file;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
import {IPreset} from '../interface';
|
||||
|
||||
export default class NoneObfs extends IPreset {
|
||||
|
||||
clientOut({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
serverIn({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
serverOut({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
clientIn({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
import {IPreset} from '../interface';
|
||||
|
||||
export default class NoneProtocol extends IPreset {
|
||||
|
||||
clientOut({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
serverIn({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
serverOut({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
clientIn({buffer}) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import crypto from 'crypto';
|
||||
import {IPreset} from '../interface';
|
||||
import {Utils, BYTE_ORDER_LE, AdvancedBuffer} from '../../utils';
|
||||
import {IPreset} from './defs';
|
||||
import {Utils, BYTE_ORDER_LE, AdvancedBuffer} from '../utils';
|
||||
|
||||
const NONCE_LEN = 12;
|
||||
const TAG_LEN = 16;
|
||||
@ -72,12 +72,17 @@ function HKDF(salt, ikm, info, length) {
|
||||
* AEAD ciphers simultaneously provide confidentiality, integrity, and authenticity.
|
||||
*
|
||||
* @params
|
||||
* cipher: The encryption/decryption method.
|
||||
* method: The encryption/decryption method.
|
||||
* info: An info for HKDF.
|
||||
*
|
||||
* @examples
|
||||
* "protocol": "aead"
|
||||
* "protocol_params": "aes-128-gcm,ss-subkey"
|
||||
* {
|
||||
* "name": "ss-aead-cipher",
|
||||
* "params": {
|
||||
* "method": "aes-128-gcm",
|
||||
* "info": "ss-subkey"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @protocol
|
||||
*
|
||||
@ -115,7 +120,7 @@ function HKDF(salt, ikm, info, length) {
|
||||
* https://nodejs.org/dist/latest-v6.x/docs/api/crypto.html#crypto_cipher_getauthtag
|
||||
* https://nodejs.org/dist/latest-v6.x/docs/api/crypto.html#crypto_decipher_setauthtag_buffer
|
||||
*/
|
||||
export default class AeadProtocol extends IPreset {
|
||||
export default class SSAeadCipherPreset extends IPreset {
|
||||
|
||||
_cipherName = '';
|
||||
|
||||
@ -131,15 +136,15 @@ export default class AeadProtocol extends IPreset {
|
||||
|
||||
_adBuf = null;
|
||||
|
||||
constructor(cipher, info) {
|
||||
constructor({method, info}) {
|
||||
super();
|
||||
if (typeof cipher === 'undefined' || cipher === '') {
|
||||
throw Error('\'protocol_params\' requires [cipher] parameter.');
|
||||
if (typeof method === 'undefined' || method === '') {
|
||||
throw Error('\'method\' must be set.');
|
||||
}
|
||||
if (!ciphers.includes(cipher)) {
|
||||
throw Error(`cipher \'${cipher}\' is not supported.`);
|
||||
if (!ciphers.includes(method)) {
|
||||
throw Error(`method \'${method}\' is not supported.`);
|
||||
}
|
||||
this._cipherName = cipher;
|
||||
this._cipherName = method;
|
||||
this._info = Buffer.from(info);
|
||||
this._adBuf = new AdvancedBuffer({getPacketLength: this.onReceiving.bind(this)});
|
||||
this._adBuf.on('data', this.onChunkReceived.bind(this));
|
@ -1,15 +1,13 @@
|
||||
import net from 'net';
|
||||
import ip from 'ip';
|
||||
import logger from 'winston';
|
||||
import {IPreset} from '../interface';
|
||||
import {SOCKET_CONNECT_TO_DST} from '../actions';
|
||||
import {Utils} from '../../utils';
|
||||
import {IPreset, SOCKET_CONNECT_TO_DST} from './defs';
|
||||
import {Utils} from '../utils';
|
||||
|
||||
import {
|
||||
ATYP_V4,
|
||||
ATYP_V6,
|
||||
ATYP_DOMAIN
|
||||
} from '../../proxies/common';
|
||||
} from '../proxies/common';
|
||||
|
||||
/**
|
||||
* @description
|
||||
@ -19,8 +17,10 @@ import {
|
||||
* no
|
||||
*
|
||||
* @examples
|
||||
* "frame": "origin"
|
||||
* "frame_params": ""
|
||||
* {
|
||||
* "name": "ss-base",
|
||||
* "params": {}
|
||||
* }
|
||||
*
|
||||
* @protocol
|
||||
*
|
||||
@ -43,7 +43,7 @@ import {
|
||||
* 2. When ATYP is 0x03, DST.ADDR[0] is len(DST.ADDR).
|
||||
* 3. When ATYP is 0x04, DST.ADDR is a 16 bytes ipv6 address.
|
||||
*/
|
||||
export default class OriginFrame extends IPreset {
|
||||
export default class SSBasePreset extends IPreset {
|
||||
|
||||
_isHandshakeDone = false;
|
||||
|
||||
@ -78,18 +78,14 @@ export default class OriginFrame extends IPreset {
|
||||
}
|
||||
}
|
||||
|
||||
serverIn({buffer, next, broadcast}) {
|
||||
serverIn({buffer, next, broadcast, fail}) {
|
||||
if (!this._isHandshakeDone) {
|
||||
if (buffer.length < 7) {
|
||||
logger.error(`invalid length: ${buffer.length}`);
|
||||
fail(`invalid length: ${buffer.length}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const atyp = buffer[0];
|
||||
if (![ATYP_DOMAIN, ATYP_V4, ATYP_V6].includes(atyp)) {
|
||||
logger.error(`invalid atyp: ${atyp}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let addr, port; // string
|
||||
let offset = 3;
|
||||
@ -102,7 +98,7 @@ export default class OriginFrame extends IPreset {
|
||||
break;
|
||||
case ATYP_V6:
|
||||
if (buffer.length < 19) {
|
||||
logger.error(`invalid length: ${buffer.length}`);
|
||||
fail(`invalid length: ${buffer.length}`);
|
||||
return;
|
||||
}
|
||||
addr = ip.toString(buffer.slice(1, 16));
|
||||
@ -112,7 +108,7 @@ export default class OriginFrame extends IPreset {
|
||||
case ATYP_DOMAIN:
|
||||
const domainLen = buffer[1];
|
||||
if (buffer.length < domainLen + 4) {
|
||||
logger.error(`invalid length: ${buffer.length}`);
|
||||
fail(`invalid length: ${buffer.length}`);
|
||||
return;
|
||||
}
|
||||
addr = buffer.slice(2, 2 + domainLen).toString();
|
||||
@ -120,7 +116,7 @@ export default class OriginFrame extends IPreset {
|
||||
offset += domainLen + 1;
|
||||
break;
|
||||
default:
|
||||
logger.error(`invalid atyp: ${atyp}`);
|
||||
fail(`invalid atyp: ${atyp}`);
|
||||
return;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import crypto from 'crypto';
|
||||
import {IPreset} from '../interface';
|
||||
import {Utils} from '../../utils';
|
||||
import {IPreset} from './defs';
|
||||
import {Utils} from '../utils';
|
||||
|
||||
const IV_LEN = 16;
|
||||
|
||||
@ -20,11 +20,15 @@ const ciphers = [
|
||||
* Perform encrypt/decrypt using Node.js 'crypto' module(OpenSSL wrappers).
|
||||
*
|
||||
* @params
|
||||
* cipher (String): Which cipher is picked from OpenSSL library.
|
||||
* method: A cipher picked from OpenSSL library.
|
||||
*
|
||||
* @examples
|
||||
* "crypto": "openssl"
|
||||
* "crypto_params": "aes-256-cfb"
|
||||
* {
|
||||
* "name": "ss-stream-cipher",
|
||||
* "params": {
|
||||
* "method": "aes-256-cfb"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @protocol
|
||||
*
|
||||
@ -52,7 +56,7 @@ const ciphers = [
|
||||
* https://www.openssl.org/docs/man1.0.2/crypto/EVP_BytesToKey.html
|
||||
* https://github.com/shadowsocks/shadowsocks/blob/master/shadowsocks/cryptor.py#L53
|
||||
*/
|
||||
export default class OpenSSLCrypto extends IPreset {
|
||||
export default class SSStreamCipherPreset extends IPreset {
|
||||
|
||||
_cipherName = '';
|
||||
|
||||
@ -62,16 +66,18 @@ export default class OpenSSLCrypto extends IPreset {
|
||||
|
||||
_decipher = null;
|
||||
|
||||
constructor(cipherName) {
|
||||
constructor({method}) {
|
||||
super();
|
||||
if (typeof cipherName !== 'string' || cipherName === '') {
|
||||
throw Error('\'crypto_params\' requires [cipher] parameter.');
|
||||
if (typeof method !== 'string' || method === '') {
|
||||
throw Error('\'method\' must be set');
|
||||
}
|
||||
if (!ciphers.includes(cipherName)) {
|
||||
throw Error(`cipher \'${cipherName}\' is not supported.`);
|
||||
if (!ciphers.includes(method)) {
|
||||
throw Error(`method \'${method}\' is not supported.`);
|
||||
}
|
||||
this._cipherName = method;
|
||||
if (global.__KEY__) {
|
||||
this._key = Utils.EVP_BytesToKey(__KEY__, this._cipherName.split('-')[1] / 8, IV_LEN);
|
||||
}
|
||||
this._cipherName = cipherName;
|
||||
this._key = Utils.EVP_BytesToKey(__KEY__, this._cipherName.split('-')[1] / 8, IV_LEN);
|
||||
}
|
||||
|
||||
beforeOut({buffer}) {
|
Loading…
Reference in New Issue
Block a user