-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2969f52
Showing
25 changed files
with
2,117 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
build/ |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
[![NPM version][npm-image]][npm-url] | ||
[![npm license][license-image]][download-url] | ||
|
||
[npm-image]: https://img.shields.io/npm/v/shadowsocks-manager.svg?style=flat-square | ||
[npm-url]: https://npmjs.org/package/shadowsocks-manager | ||
[download-url]: https://npmjs.org/package/shadowsocks-manager | ||
[license-image]: https://img.shields.io/npm/l/shadowsocks-manager.svg | ||
|
||
# shadowsocks-manager | ||
|
||
A shadowsocks manager tool for multi user and traffic control. | ||
Base on Node.js and SQLite. | ||
|
||
For more details, you can see [the wiki page](https://github.com/shadowsocks/shadowsocks-manager/wiki). | ||
|
||
If you want to use the old version, please switch to [this branch](https://github.com/shadowsocks/shadowsocks-manager/tree/version1). | ||
|
||
## WebGUI Demo: | ||
|
||
[https://wall.gyteng.com](https://wall.gyteng.com) | ||
|
||
## Dependencies | ||
|
||
Node.js 6.* | ||
|
||
## Install | ||
|
||
### From source: | ||
|
||
``` | ||
git clone https://github.com/shadowsocks/shadowsocks-manager.git | ||
cd shadowsocks-manager | ||
npm i | ||
``` | ||
use `node server.js` to run this program. | ||
|
||
### From npm: | ||
``` | ||
npm i -g shadowsocks-manager | ||
``` | ||
use `ssmgr` to run this program. | ||
|
||
### From docker: | ||
``` | ||
docker run --name ssmgr -idt -v ~/.ssmgr:/root/.ssmgr --net=host gyteng/ssmgr [ssmgr params...] | ||
``` | ||
|
||
### Build docker image: | ||
|
||
here is the `Dockerfile` | ||
|
||
``` | ||
FROM ubuntu:16.04 | ||
MAINTAINER gyteng <igyteng@gmail.com> | ||
RUN apt-get update && \ | ||
apt-get install tzdata net-tools curl git sudo software-properties-common python-pip -y && \ | ||
pip install git+https://github.com/shadowsocks/shadowsocks.git@master && \ | ||
add-apt-repository ppa:max-c-lv/shadowsocks-libev -y && \ | ||
curl -sL https://deb.nodesource.com/setup_6.x | bash - && \ | ||
apt-get install -y nodejs shadowsocks-libev && \ | ||
npm i -g shadowsocks-manager && \ | ||
echo "Asia/Shanghai" > /etc/timezone && \ | ||
rm /etc/localtime && \ | ||
dpkg-reconfigure -f noninteractive tzdata | ||
ENTRYPOINT ["/usr/bin/ssmgr"] | ||
``` | ||
|
||
### Usage | ||
1. Start shadowsocks with [manager API](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users), it supports `shadowsocks-python` and `shadowsocks-libev`. | ||
For example, you can run this command: | ||
`ss-manager -m aes-256-cfb -u --manager-address 127.0.0.1:6001` | ||
2. run ssmgr with type s: | ||
|
||
config file: | ||
``` | ||
type: s | ||
shadowsocks: | ||
address: 127.0.0.1:6001 | ||
manager: | ||
address: 0.0.0.0:4001 | ||
password: '123456' | ||
db: 'ss.sqlite' | ||
``` | ||
|
||
If you want to use MySQL, the `db` must like this: | ||
|
||
``` | ||
db: | ||
host: '1.1.1.1' | ||
user: 'root' | ||
password: 'abcdefg' | ||
database: 'ssmgr' | ||
``` | ||
|
||
And you have to close `only_full_group_by` when the version of MySQL is greater than 5.7 | ||
|
||
command: | ||
`ssmgr -c /your/config/file/path.yml` | ||
|
||
3. If you have several servers, you have to run step 1 and step 2 in every server. | ||
The listening address in `--manager-address` of step 1 and in `shadowsocks -> address` of step 2's config file must be same. For security reseon, we recommend you to use `127.0.0.1` instead of `0.0.0.0`. | ||
4. Now you can use the plugins to manage them. You can read the details in plugins readme page. | ||
|
||
``` | ||
+-------------+ +-------------+ +------+ | ||
| Shadowsocks | | Shadowsocks | ... | | | ||
| manager API | | manager API | | | | ||
+-------------+ +-------------+ +------+ | ||
| | | | ||
| | | | ||
+-------------+ +-------------+ +------+ | ||
| ssmgr | | ssmgr | ... | | | ||
| with type s | | with type s | | | | ||
+-------------+ +-------------+ +------+ | ||
| | | | ||
+------------+----+-------- ... ---+ | ||
| | ||
| | ||
+---------------+ | ||
| ssmgr plugins | | ||
| with type m | | ||
+---------------+ | ||
``` | ||
|
||
### Plugins | ||
[cli](https://github.com/shadowsocks/shadowsocks-manager/blob/master/plugins/cli/README.md) | ||
[telegram](https://github.com/shadowsocks/shadowsocks-manager/blob/master/plugins/telegram/README.md) | ||
[freeAccount](https://github.com/shadowsocks/shadowsocks-manager/blob/master/plugins/freeAccount/README.md) | ||
[webgui](https://github.com/shadowsocks/shadowsocks-manager/blob/master/plugins/webgui/README.md) | ||
|
||
### Parameter | ||
|
||
`ssmgr --help` will show startup parameters info. | ||
|
||
``` | ||
Usage: ssmgr [options] | ||
Options: | ||
-h, --help output usage information | ||
-V, --version output the version number | ||
-c, --config [file] config file, default: ~/.ssmgr/default.yml | ||
-d, --db [file] sqlite3 file, sample: ~/.ssmgr/db.sqlite | ||
-t, --type [type] type, s for server side, m for manager side | ||
-s, --shadowsocks [address] ss-manager address, sample: 127.0.0.1:6001 | ||
-m, --manager [address] manager address, sample: 0.0.0.0:6002 | ||
-p, --password [password] manager password, both server side and manager side must be equals | ||
-r, --run [type] run shadowsocks from child_process, sample: libev / libev:aes-256-cfb / python / python:aes-256-cfb | ||
--debug show debug message | ||
``` | ||
|
||
First, ssmgr will read the config file in `--config`, and other parameters(`-detsmp`) will replace the config file values. | ||
|
||
### Translate | ||
|
||
If your want to help to translate it to other languages, please edit files [here](https://github.com/shadowsocks/shadowsocks-manager/tree/dev/plugins/webgui/public/translate) and give me a pull request. | ||
|
||
### Telegram | ||
Join the group if you have some problem: [https://t.me/ssmgr](https://t.me/ssmgr) | ||
|
||
### VPS recommendation | ||
|
||
* [Linode](https://www.linode.com/?r=bbc24323b3adaf3d74f242fd958d91b55cc6fdea) | ||
|
||
* [DigitalOcean](https://m.do.co/c/d43891b79a52) | ||
|
||
* [Vultr](http://www.vultr.com/?ref=6926595) | ||
|
||
* [AlibabaCloud](https://account-intl.aliyun.com/register/intl_register.htm?biz_params=%7B%22intl%22%3A%22%7B%5C%22referralCode%5C%22%3A%5C%22koa26v%5C%22%7D%22%7D) | ||
|
||
* [BandwagonHost](https://bandwagonhost.com/aff.php?aff=19999) | ||
|
||
* [dediserve](https://manage.dediserve.com/?affid=841) | ||
|
||
### Donate | ||
If you find this project helpful, please consider making a donation: | ||
|
||
* Alipay | ||
<img src="https://github.com/gyteng/gyteng.github.com/raw/master/media/pic/alipay.jpg" width="160"> | ||
|
||
* WeChat Pay | ||
<img src="https://github.com/gyteng/gyteng.github.com/raw/master/media/pic/wechat.png" width="160"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/usr/bin/env node | ||
process.env.NODE_ENV = 'production'; | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib/'); | ||
console.log(lib); | ||
process.chdir(lib); | ||
require(lib + '/server'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
type: s | ||
|
||
shadowsocks: | ||
address: 127.0.0.1:6001 | ||
#portRange: 50000-51000,55000,55002 | ||
|
||
manager: | ||
address: 0.0.0.0:6002 | ||
password: '123456' | ||
|
||
db: 'db.sqlite' | ||
|
||
# db: | ||
# host: '1.1.1.1' | ||
# user: 'root' | ||
# password: 'abcdefg' | ||
# database: 'ssmgr' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
const del = require('del'); | ||
const gulp = require('gulp'); | ||
const path = require('path'); | ||
const babel = require('gulp-babel'); | ||
const webpack = require('webpack'); | ||
const webpackStream = require('webpack-stream'); | ||
|
||
gulp.task('clean', () => { | ||
return del([ | ||
'lib', | ||
'plugins/webgui/libs/bundle.js', | ||
]); | ||
}); | ||
|
||
gulp.task('freeAccountCopy', ['clean'], () => { | ||
return gulp | ||
.src([ | ||
'plugins/freeAccount/libs/**', | ||
'plugins/freeAccount/views/**', | ||
], { | ||
base: './' | ||
}) | ||
.pipe(gulp.dest('lib')); | ||
}); | ||
|
||
gulp.task('webguiBuild', () => { | ||
return gulp.src([ | ||
'plugins/webgui/public/**', | ||
]) | ||
.pipe(webpackStream({ | ||
entry: './plugins/webgui/public/app.js', | ||
output: { | ||
path: path.resolve(__dirname, 'libs'), | ||
filename: 'bundle.js' | ||
}, | ||
externals: [ | ||
{ | ||
window: 'window' | ||
} | ||
], | ||
module: { | ||
loaders: [{ | ||
test: /\.js$/, | ||
loader: 'babel-loader', | ||
query: { | ||
presets: [ | ||
[ | ||
'env', { | ||
targets: { | ||
browsers: [ | ||
'Chrome >= 52', | ||
'FireFox >= 44', | ||
'Safari >= 7', | ||
'Explorer 11', | ||
'last 4 Edge versions' | ||
] | ||
} | ||
} | ||
] | ||
] | ||
} | ||
}] | ||
}, | ||
plugins: [ new webpack.optimize.UglifyJsPlugin({ | ||
compress: { | ||
warnings: false | ||
} | ||
}) ] | ||
})) | ||
.pipe(gulp.dest('plugins/webgui/libs')); | ||
}); | ||
|
||
gulp.task('webguiCopy', ['webguiBuild'], () => { | ||
return gulp | ||
.src([ | ||
'plugins/webgui/libs/**', | ||
'plugins/webgui/public/**', | ||
'plugins/webgui/views/**', | ||
], { | ||
base: './' | ||
}) | ||
.pipe(gulp.dest('lib')); | ||
}); | ||
|
||
gulp.task('babelCopy', ['clean'], () => { | ||
return gulp | ||
.src([ | ||
'config/*.yml', | ||
'package.json', | ||
], { | ||
base: './' | ||
}) | ||
.pipe(gulp.dest('lib')); | ||
}); | ||
|
||
gulp.task('babel', ['webguiCopy', 'freeAccountCopy', 'babelCopy'], () => { | ||
return gulp.src([ | ||
'**/*.js', | ||
'!node_modules/**', | ||
'!lib/**', | ||
'!plugins/freeAccount/libs/**', | ||
'!plugins/webgui/libs/**', | ||
'!plugins/webgui/public/**', | ||
]) | ||
.pipe(babel({ | ||
presets: [ | ||
[ | ||
'env', { | ||
targets: { | ||
node: '6.0' | ||
}, | ||
} | ||
] | ||
], | ||
})) | ||
.pipe(gulp.dest('lib')); | ||
}); | ||
|
||
gulp.task('webguiWatch', function () { | ||
gulp.watch('plugins/webgui/public/**', ['webguiBuild']); | ||
}); | ||
|
||
gulp.task('default', ['clean', 'babel'], () => { | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
const os = require('os'); | ||
const path = require('path'); | ||
const program = require('commander'); | ||
const version = appRequire('package').version; | ||
const log = appRequire('init/log'); | ||
|
||
const log4js = require('log4js'); | ||
const logger = log4js.getLogger('system'); | ||
|
||
const ssmgrPath = path.resolve(os.homedir(), './.ssmgr/'); | ||
|
||
program | ||
.version('shadowsocks-manager ' + version) | ||
.option('-c, --config [file]', 'config file, default: ~/.ssmgr/default.yml') | ||
.option('-d, --db [file]', 'sqlite3 file, sample: ~/.ssmgr/db.sqlite') | ||
.option('-t, --type [type]', 'type, s for server side, m for manager side') | ||
.option('-s, --shadowsocks [address]', 'ss-manager address, sample: 127.0.0.1:6001') | ||
.option('-m, --manager [address]', 'manager address, sample: 0.0.0.0:6002') | ||
.option('-p, --password [password]', 'manager password, both server side and manager side must be equals') | ||
.option('-r, --run [type]', 'run shadowsocks from child_process, sample: libev / libev:aes-256-cfb / python / python:aes-256-cfb') | ||
.option('--debug', 'show debug message') | ||
.parse(process.argv); | ||
|
||
if(program.config) { global.configFile = program.config; } | ||
|
||
if(!program.debug) { | ||
log.setConsoleLevel('ERROR'); | ||
} | ||
|
||
const config = appRequire('services/config'); | ||
let logName = 'uname'; | ||
|
||
if(program.type) {config.set('type', program.type);} | ||
if(program.shadowsocks) {config.set('shadowsocks.address', program.shadowsocks);} | ||
if(program.manager) {config.set('manager.address', program.manager);} | ||
if(program.password) {config.set('manager.password', program.password);} | ||
if(program.db) { | ||
config.set('db', program.db); | ||
} | ||
if (typeof config.get('db') === 'object') { | ||
logName = config.get('db.database'); | ||
} else { | ||
const dbpath = config.get('db'); | ||
logName = path.basename(dbpath).split('.')[0]; | ||
if (dbpath[0] === '/' || dbpath[0] === '.' || dbpath[0] === '~') { | ||
config.set('db', path.resolve(dbpath)); | ||
} else { | ||
config.set('db', path.resolve(ssmgrPath, dbpath)); | ||
} | ||
} | ||
log.setFileAppenders(logName); | ||
|
||
if(program.run) { | ||
config.set('runShadowsocks', program.run); | ||
} |
Oops, something went wrong.