ssr-helper
Advanced tools
Comparing version
@@ -11,7 +11,9 @@ #!/usr/bin/env node | ||
if (!config.has('default')) config.set('default', []) // Default set | ||
if (localConfig.size === 0) localConfig.store = { | ||
local_address: '127.0.0.1', | ||
local_port: 1080, | ||
timeout: 300, | ||
workers: 1 | ||
if (localConfig.size === 0) { | ||
localConfig.store = { | ||
local_address: '127.0.0.1', | ||
local_port: 1080, | ||
timeout: 300, | ||
workers: 1 | ||
} | ||
} // Local Config Default set | ||
@@ -18,0 +20,0 @@ |
const SsrNet = require('../lib/net') | ||
const SsrNet = require("../lib/net") | ||
let p = Promise.resolve(); | ||
let p = Promise.resolve() | ||
require('../lib/select')(false).then(res => { | ||
let routes = res.servers[res.group]; | ||
//console.log(routes); | ||
for (let route of routes) { | ||
p = p.then((resolve) => { | ||
console.log(`test route ${route.server}:${route.server_port}`); | ||
return SsrNet.delayTest(route.server, route.server_port) | ||
.catch(() => { | ||
//ignore test error,continue loop | ||
}).then(() => { | ||
//测试后 | ||
console.log("");//newline | ||
}) | ||
let routes = res.servers[res.group] | ||
// console.log(routes); | ||
for (let route of routes) { | ||
p = p.then((resolve) => { | ||
console.log(`test route ${route.server}:${route.server_port}`) | ||
return SsrNet.delayTest(route.server, route.server_port) | ||
.catch(() => { | ||
// ignore test error,continue loop | ||
}).then(() => { | ||
// 测试后 | ||
console.log('')// newline | ||
}) | ||
} | ||
}) | ||
} | ||
}) |
@@ -0,3 +1,45 @@ | ||
const queryString = require('query-string') | ||
var QRCode = require('qrcode-terminal') | ||
function base64encode (o) { | ||
return o ? Buffer.from(o).toString('base64') : '' | ||
} | ||
function encodeCore (t) { | ||
const q = queryString.stringify({ | ||
group: base64encode(t.group), | ||
remarks: base64encode(t.remarks), | ||
protoparam: base64encode(t.protocolparam) || undefined, | ||
obfsparam: base64encode(t.obfsparam) || undefined | ||
}) | ||
return 'ssr://' + base64encode(`${t.server}:${t.server_port}:${t.protocol}:${t.method}:${t.obfs}:${base64encode(t.password)}/?${q}`) | ||
/* t = Buffer.from(t.toString(), 'base64').toString().split('/') | ||
let t1 = t[0].split(':') | ||
let tConfig = { | ||
server: t1[0], | ||
server_port: parseInt(t1[1]), | ||
password: Buffer.from(t1[5], 'base64').toString(), | ||
method: t1[3], | ||
obfs: t1[4], | ||
protocol: t1[2] | ||
} | ||
Object.assign(tConfig, queryString.parse(t[1])) | ||
// 解析 Base64 编码的分组、备注 | ||
tConfig.group = !tConfig.group ? 'Unknown' : Buffer.from(tConfig.group, 'base64').toString() | ||
tConfig.remarks = !tConfig.remarks ? 'Unknown Server' : Buffer.from(tConfig.remarks, 'base64').toString() | ||
// 解析 Base64 编码的混淆参数 | ||
tConfig.obfsparam = !tConfig.obfsparam ? '' : Buffer.from(tConfig.obfsparam, 'base64').toString() | ||
tConfig.protoparam = !tConfig.protoparam ? '' : Buffer.from(tConfig.protoparam, 'base64').toString() | ||
// console.log(tConfig) | ||
return tConfig */ | ||
} | ||
require('../lib/select')().then(res => { | ||
const url = encodeCore(res.servers[res.group][res.server]) | ||
console.log(res.servers[res.group][res.server]) | ||
console.log('SSR URL:', url) | ||
QRCode.generate(url, {small: true}) | ||
}) |
@@ -1,1 +0,16 @@ | ||
require('../lib/exec')('restart') | ||
const Program = require('commander') | ||
const Exec = require('../lib/exec') | ||
const Dynamic = require('../lib/dynamic') | ||
Program.option('-d, --dynamic [filename]', 'Dynamic config file.for docker or other use') | ||
.parse(process.argv) | ||
if (Program.dynamic) { | ||
if (Program.dynamic === true) { | ||
console.warn('please add filename option') | ||
process.exit() | ||
} | ||
let configFile = Dynamic.generateConfigFile(Program.dynamic) | ||
Exec('restart', false, configFile.path) | ||
} else { | ||
Exec('restart') | ||
} |
@@ -1,1 +0,17 @@ | ||
require('../lib/exec')('start') | ||
const Dynamic = require('../lib/dynamic') | ||
const Program = require('commander') | ||
const Exec = require('../lib/exec') | ||
Program.option('-d, --dynamic [filename]', 'Dynamic config file.for docker or other use') | ||
.parse(process.argv) | ||
if (Program.dynamic) { | ||
if (Program.dynamic === true) { | ||
console.warn('please add filename option') | ||
process.exit() | ||
} | ||
let configFile = Dynamic.generateConfigFile(Program.dynamic) | ||
Exec('start', false, configFile.path, false) | ||
} else { | ||
Exec('start') | ||
} |
@@ -1,1 +0,16 @@ | ||
require('../lib/exec')('stop') | ||
const Program = require('commander') | ||
const Exec = require('../lib/exec') | ||
const Dynamic = require('../lib/dynamic') | ||
Program.option('-d, --dynamic [filename]', 'Dynamic config file.for docker or other use') | ||
.parse(process.argv) | ||
if (Program.dynamic) { | ||
if (Program.dynamic === true) { | ||
console.warn('please add filename option') | ||
process.exit() | ||
} | ||
let configFile = Dynamic.getConfigFile(Program.dynamic) | ||
Exec('stop', false, configFile.path) | ||
} else { | ||
Exec('stop') | ||
} |
@@ -17,27 +17,29 @@ const request = require('then-request') | ||
program.option("-d, --direct", "Direct(without proxy)") | ||
.option("-p, --proxy", "Through connected SSR proxy") | ||
program.option('-d, --direct', 'Direct(without proxy)') | ||
.option('-p, --proxy', 'Through connected SSR proxy') | ||
.parse(process.argv) | ||
new Promise((resolve, reject) => { | ||
if (program.proxy) return resolve(new SocksProxyAgent(socksaddress)); | ||
else if (program.direct) return resolve(false); | ||
//interactive mode | ||
else resolve(inquirer.prompt([ | ||
{ | ||
type: 'list', | ||
name: 'proxy', | ||
message: 'Do you want to update list through proxy?', | ||
choices: [{ | ||
name: 'Direct(without proxy)', | ||
value: 0 | ||
}, { | ||
name: 'Through connected SSR proxy', | ||
value: 1 | ||
}] | ||
} | ||
]).then(function (answers) { | ||
return answers.proxy ? new SocksProxyAgent(socksaddress) : false | ||
})) | ||
if (program.proxy) return resolve(new SocksProxyAgent(socksaddress)) | ||
else if (program.direct) return resolve(false) | ||
// interactive mode | ||
else { | ||
resolve(inquirer.prompt([ | ||
{ | ||
type: 'list', | ||
name: 'proxy', | ||
message: 'Do you want to update list through proxy?', | ||
choices: [{ | ||
name: 'Direct(without proxy)', | ||
value: 0 | ||
}, { | ||
name: 'Through connected SSR proxy', | ||
value: 1 | ||
}] | ||
} | ||
]).then(function (answers) { | ||
return answers.proxy ? new SocksProxyAgent(socksaddress) : false | ||
})) | ||
} | ||
}).then(proxy => { | ||
//fetch and update | ||
// fetch and update | ||
while (i--) { | ||
@@ -44,0 +46,0 @@ const spinner = ora(chalk.green(chalk.green(list[i]))).start() |
@@ -7,12 +7,22 @@ const Conf = require('conf') | ||
function main () { | ||
let i = servers.length | ||
while (i--) { | ||
if (!servers[i].group) servers[i].group = 'Ungrouped' | ||
if (!t[servers[i].group]) t[servers[i].group] = [] | ||
t[servers[i].group].push(servers[i]) | ||
function main (multi = false) { | ||
if (!multi) { | ||
let i = servers.length | ||
while (i--) { | ||
if (!servers[i].group) servers[i].group = 'Ungrouped' | ||
if (!t[servers[i].group]) t[servers[i].group] = [] | ||
t[servers[i].group].push(servers[i]) | ||
} | ||
return t | ||
} else { | ||
let i = servers.length | ||
while (i--) { | ||
if (!t[servers[i].group]) t[servers[i].group] = {} | ||
t[servers[i].group][servers[i].remarks] = servers[i] | ||
} | ||
return t | ||
} | ||
return t | ||
} | ||
module.exports = main |
const shell = require('shelljs') | ||
const Conf = require('conf') | ||
const config = new Conf() | ||
const defaultConfig = new Conf({configName: 'default'}) | ||
function main (order, back) { | ||
const defaultConfig = new Conf({ configName: 'default' }) | ||
const isRoot = require('is-root') | ||
function main (order, back, configPath = defaultConfig.path, damon = true) { | ||
if (!shell.which('python')) { | ||
@@ -11,5 +11,10 @@ shell.echo('You need install python for the script!') | ||
} | ||
if (defaultConfig.size === 0) console.error('Error: the default connection is unset!') | ||
if (configPath === defaultConfig.path && defaultConfig.size === 0) console.error('Error: the default connection is unset!') | ||
else { | ||
order = (back ? '' : 'sudo ') + '/usr/bin/python ' + config.get('ssr-path') + '/shadowsocks/local.py --fast-open -c ' + defaultConfig.path + ' -d ' + order | ||
if (damon) { | ||
order = ' -d ' + order | ||
} else { | ||
order = '' | ||
} | ||
order = (back ? '' : isRoot() ? '' : 'sudo ') + '/usr/bin/python ' + config.get('ssr-path') + '/shadowsocks/local.py --fast-open -c ' + configPath + order | ||
if (back) return order | ||
@@ -16,0 +21,0 @@ else { |
@@ -1,2 +0,2 @@ | ||
const net = require("net") | ||
const net = require('net') | ||
const chalk = require('chalk') | ||
@@ -6,35 +6,31 @@ const ora = require('ora') | ||
exports.delayTest = function (host, port, timeout = 3000) { | ||
return new Promise((resolve, reject) => { | ||
return new Promise((resolve, reject) => { | ||
const spinner = ora(chalk.green('Connection testing...')).start() | ||
// sock init | ||
let sock = net.Socket() | ||
sock.setNoDelay(true) | ||
sock.on('error', function (err) { | ||
clearTimeout(timerId) | ||
spinner.fail('Connection error : \n' + err) | ||
sock.destroy() | ||
reject(new Error('Connection error : \n' + err)) | ||
}) | ||
// time init | ||
let timerId = setTimeout(() => { | ||
// sock.removeListener('connection'); | ||
sock.destroy() | ||
spinner.fail('Establish Connection timeout') | ||
reject(new Error('Establish Connection timeout')) | ||
}, timeout) | ||
let oldTime = Date.now() | ||
const spinner = ora(chalk.green('Connection testing...')).start() | ||
//sock init | ||
let sock = net.Socket(); | ||
sock.setNoDelay(true); | ||
sock.on('error', function (err) { | ||
clearTimeout(timerId); | ||
spinner.fail('Connection error : \n' + err); | ||
sock.destroy(); | ||
reject(); | ||
}); | ||
//time init | ||
let timerId = setTimeout(() => { | ||
//sock.removeListener('connection'); | ||
sock.destroy(); | ||
spinner.fail("Establish Connection timeout"); | ||
reject(); | ||
}, timeout); | ||
let oldTime = Date.now(); | ||
sock.connect(port, host, () => { | ||
clearTimeout(timerId); | ||
sock.end(); | ||
let newTime = Date.now(); | ||
let delay = newTime - oldTime; | ||
spinner.succeed(`delay:${delay}ms`); | ||
resolve() | ||
}); | ||
sock.connect(port, host, () => { | ||
clearTimeout(timerId) | ||
sock.end() | ||
let newTime = Date.now() | ||
let delay = newTime - oldTime | ||
spinner.succeed(`delay:${delay}ms`) | ||
resolve() | ||
}) | ||
}) | ||
} | ||
const Conf = require('conf') | ||
const config = new Conf() | ||
const queryString = require('query-string') | ||
const base64 = require('base64-js') | ||
@@ -40,3 +39,3 @@ function main (t) { | ||
Object.assign(tConfig, queryString.parse(t[1])) | ||
// 解析 Base64 编码的分组、备注 | ||
@@ -43,0 +42,0 @@ tConfig.group = !tConfig.group ? 'Unknown' : Buffer.from(tConfig.group, 'base64').toString() |
{ | ||
"name": "ssr-helper", | ||
"version": "1.1.0", | ||
"version": "1.1.2", | ||
"description": "A CLI Helper designed for Python port of ShadowsocksR", | ||
"main": "index.js", | ||
"scripts": { | ||
"commitmsg": "commitlint -e $GIT_PARAMS", | ||
"release": "standard-version", | ||
"pre-commit": "npm run lint", | ||
"pre-push": "npm prune", | ||
"lint": "eslint --ext .js bin lib", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
@@ -23,3 +28,2 @@ }, | ||
"dependencies": { | ||
"base64-js": "^1.2.1", | ||
"bluebird": "^3.5.0", | ||
@@ -33,3 +37,5 @@ "chalk": "^1.1.3", | ||
"inquirer": "^3.0.6", | ||
"is-root": "^1.0.0", | ||
"ora": "^1.2.0", | ||
"qrcode-terminal": "^0.12.0", | ||
"query-string": "^5.0.0", | ||
@@ -39,3 +45,15 @@ "shelljs": "^0.7.8", | ||
"then-request": "^4.1.0" | ||
}, | ||
"devDependencies": { | ||
"@commitlint/cli": "^6.1.3", | ||
"@commitlint/config-conventional": "^6.1.3", | ||
"eslint": "^4.19.1", | ||
"eslint-config-standard": "^11.0.0", | ||
"eslint-plugin-import": "^2.12.0", | ||
"eslint-plugin-node": "^6.0.1", | ||
"eslint-plugin-promise": "^3.8.0", | ||
"eslint-plugin-standard": "^3.1.0", | ||
"husky": "^0.14.3", | ||
"standard-version": "^4.3.0" | ||
} | ||
} |
@@ -21,2 +21,3 @@ # SSR Helper CLI | ||
6. 默认开启TCP FastOpen(Linux Kernel 3.7+) | ||
7. 测试延迟功能 | ||
@@ -70,2 +71,3 @@ ## 安装 | ||
* `ssr unstartup` : 关闭服务开机自启,仅在Systemd启动的Linux平台下有效 | ||
* `ssr delay` : 测试服务器的延迟 | ||
* `ssr-subscribe add [url]` : 添加新的SSR订阅地址 | ||
@@ -72,0 +74,0 @@ * `ssr-subscribe ls` : 列出所有SSR订阅地址和他们的当前标号 |
Sorry, the diff of this file is not supported yet
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
128906
134.44%38
11.76%677
25.37%85
2.41%15
7.14%10
Infinity%+ Added
+ Added
+ Added
+ Added
- Removed
- Removed