asd123a20 4 năm trước cách đây
mục cha
commit
60a9f9b3d2
47 tập tin đã thay đổi với 1789 bổ sung0 xóa
  1. 29 0
      .autod.conf.js
  2. 1 0
      .eslintignore
  3. 3 0
      .eslintrc
  4. 14 0
      .gitignore
  5. 12 0
      .travis.yml
  6. 33 0
      README.md
  7. 60 0
      app/controller/admin.js
  8. 86 0
      app/controller/cacert.js
  9. 76 0
      app/controller/enccert.js
  10. 14 0
      app/controller/home.js
  11. 85 0
      app/controller/ipsecvpn.js
  12. 54 0
      app/controller/lan.js
  13. 45 0
      app/controller/log.js
  14. 127 0
      app/controller/sigcert.js
  15. 84 0
      app/controller/sslvpn.js
  16. 225 0
      app/controller/systemctl.js
  17. 53 0
      app/controller/wan.js
  18. 20 0
      app/middleware/error_handler.js
  19. 1 0
      app/public/css/app.fba0a0ac.css
  20. 1 0
      app/public/css/chunk-vendors.c470e980.css
  21. BIN
      app/public/favicon.ico
  22. BIN
      app/public/fonts/element-icons.535877f5.woff
  23. BIN
      app/public/fonts/element-icons.732389de.ttf
  24. BIN
      app/public/img/bg.4f6e6589.jpg
  25. BIN
      app/public/img/logo.48e50617.jpg
  26. 1 0
      app/public/index.html
  27. 1 0
      app/public/js/app.aa1e9780.js
  28. 33 0
      app/public/js/chunk-vendors.d4475822.js
  29. 63 0
      app/router.js
  30. 69 0
      app/service/fileshandler.js
  31. 105 0
      app/service/shell.js
  32. 16 0
      app/view/dhcp.nj
  33. 13 0
      app/view/ipsecalog.nj
  34. 24 0
      app/view/ipsecavpn.nj
  35. 26 0
      app/view/ipsecavpnservice.nj
  36. 11 0
      app/view/lan.nj
  37. 28 0
      app/view/sslvpn.nj
  38. 37 0
      app/view/sslvpnservice.nj
  39. 14 0
      app/view/wan.nj
  40. 14 0
      appveyor.yml
  41. 79 0
      config/config.default.js
  42. 40 0
      config/filespath.js
  43. 17 0
      config/plugin.js
  44. 101 0
      config/shells.js
  45. 5 0
      jsconfig.json
  46. 49 0
      package.json
  47. 20 0
      test/app/controller/home.test.js

+ 29 - 0
.autod.conf.js

@@ -0,0 +1,29 @@
+'use strict';
+
+module.exports = {
+  write: true,
+  prefix: '^',
+  plugin: 'autod-egg',
+  test: [
+    'test',
+    'benchmark',
+  ],
+  dep: [
+    'egg',
+    'egg-scripts',
+  ],
+  devdep: [
+    'egg-ci',
+    'egg-bin',
+    'egg-mock',
+    'autod',
+    'autod-egg',
+    'eslint',
+    'eslint-config-egg',
+  ],
+  exclude: [
+    './test/fixtures',
+    './dist',
+  ],
+};
+

+ 1 - 0
.eslintignore

@@ -0,0 +1 @@
+coverage

+ 3 - 0
.eslintrc

@@ -0,0 +1,3 @@
+{
+  "extends": "eslint-config-egg"
+}

+ 14 - 0
.gitignore

@@ -0,0 +1,14 @@
+logs/
+npm-debug.log
+yarn-error.log
+node_modules/
+package-lock.json
+yarn.lock
+coverage/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+typings/
+.nyc_output/

+ 12 - 0
.travis.yml

@@ -0,0 +1,12 @@
+
+language: node_js
+node_js:
+  - '10'
+before_install:
+  - npm i npminstall -g
+install:
+  - npminstall
+script:
+  - npm run ci
+after_script:
+  - npminstall codecov && codecov

+ 33 - 0
README.md

@@ -0,0 +1,33 @@
+# Y
+
+
+
+## QuickStart
+
+<!-- add docs here for user -->
+
+see [egg docs][egg] for more detail.
+
+### Development
+
+```bash
+$ npm i
+$ npm run dev
+$ open http://localhost:7001/
+```
+
+### Deploy
+
+```bash
+$ npm start
+$ npm stop
+```
+
+### npm scripts
+
+- Use `npm run lint` to check code style.
+- Use `npm test` to run unit test.
+- Use `npm run autod` to auto detect dependencies upgrade, see [autod](https://www.npmjs.com/package/autod) for more detail.
+
+
+[egg]: https://eggjs.org

+ 60 - 0
app/controller/admin.js

@@ -0,0 +1,60 @@
+// 用户登录
+/* eslint-disable array-callback-return */
+'use strict';
+const Controller = require('egg').Controller;
+const filePath = require('../../config/filespath');
+class AdminController extends Controller {
+  async login() {
+    const { ctx, app } = this;
+    const { userName, password } = ctx.request.body;
+    const configJson = require(filePath.configJson);
+    const data = configJson.admin.filter(p => p.userName === userName);
+    console.log(data);
+    let msg;
+    if (data.length <= 0) {
+      msg = { errcode: -1, errmsg: '用户不存在' };
+    } else {
+      if (data[0].password === password) {
+        const token = app.jwt.sign({ userName, name: data[0].name }, app.config.jwt.secret, {
+          expiresIn: 60 * 60 * 60,
+        });
+        msg = { errcode: 0, errmsg: '', token, userName, name: data[0].name };
+      } else {
+        msg = { errcode: -1, errmsg: '密码错误' };
+      }
+    }
+    ctx.body = msg;
+  }
+  async editPwd() {
+    const { ctx } = this;
+    const { userName, password, newpassword } = ctx.request.body;
+    const configJson = require(filePath.configJson);
+    const data = configJson.admin.filter(p => p.userName === userName);
+    let msg;
+    try {
+      if (data.length <= 0) {
+        msg = { errcode: -1, errmsg: '用户不存在' };
+      } else {
+        if (data[0].password === password) {
+          configJson.admin.map(p => {
+            if (p.userName === userName) {
+              p.password = newpassword;
+            }
+          });
+          const jsonstr = JSON.stringify(configJson);
+          await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+          msg = { errcode: 0, errmsg: '' };
+        } else {
+          msg = { errcode: -1, errmsg: '密码错误' };
+        }
+      }
+      ctx.body = msg;
+    } catch (error) {
+      const body = { errcode: -1003, errmsg: '密码修改失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+}
+
+
+module.exports = AdminController;

+ 86 - 0
app/controller/cacert.js

@@ -0,0 +1,86 @@
+// 证书链
+'use strict';
+
+const Controller = require('egg').Controller;
+const UUID = require('uuid');
+const filePath = require('../../config/filespath');
+class CAcertController extends Controller {
+  async caupload() {
+    const { ctx } = this;
+    const configJson = require(filePath.configJson);
+    const uuid = UUID.v1();
+    // 获取数据流
+    const stream = await ctx.getFileStream();
+    // 路径 + 文件名
+    const name = `${filePath.CAcert}${uuid}.cer`;
+    try {
+      // 文件存储
+      const files = await this.service.fileshandler.upload({ name, stream });
+      if (files.errcode === 0) {
+        // 解析证书
+        const dns = await this.service.shell.read({ filePath: name });
+        let dn;
+        if (dns.errcode === 0 && dns.data) {
+          dns.data.trim().split('\n').forEach(function(v) {
+            if (v.includes('Subject:')) {
+              dn = v.replace('Subject:', '');
+            }
+          });
+          const form = { uuid, dn };
+          configJson.ca.push(form);
+          const jsonstr = JSON.stringify(configJson);
+          // 存储数据
+          await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+          this.ctx.body = { errcode: 0, errmsg: '' };
+        }
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '证书上传失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 删除ca证书
+  async cadelete() {
+    const uuid = this.ctx.query.uuid;
+    const configJson = require(filePath.configJson);
+    // 过滤掉当前uuid数据
+    const data = configJson.ca.filter(p => p.uuid !== uuid);
+    configJson.ca = data;
+    const jsonstr = JSON.stringify(configJson);
+    try {
+      // 存储到数据文件
+      await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+      // 删除证书文件
+      const res = await this.service.fileshandler.filesDel(`${filePath.CAcert}${uuid}.cer`);
+      if (res.errcode === 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        throw new Error(res);
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '证书删除失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 查询ca信息
+  async caquery() {
+    const { ctx } = this;
+    const configJson = require(filePath.configJson);
+    const data = configJson.ca;
+    ctx.body = { errcode: 0, errmsg: '', data };
+  }
+  // ca证书下载
+  async cacertdownload() {
+    try {
+      const uuid = this.ctx.query.uuid;
+      const cafilePath = `${filePath.CAcert}${uuid}.cer`;
+      const res = await this.service.fileshandler.download({ filePath: cafilePath });
+      this.ctx.body = res;
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '证书下载失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+}
+
+module.exports = CAcertController;

+ 76 - 0
app/controller/enccert.js

@@ -0,0 +1,76 @@
+// 加密证书
+'use strict';
+
+const Controller = require('egg').Controller;
+const UUID = require('uuid');
+const assert = require('assert');
+const filePath = require('../../config/filespath');
+class EnccertController extends Controller {
+  // 加密证书上传
+  async enccertupload() {
+    const { ctx } = this;
+    // 获取文件流
+    const stream = await ctx.getFileStream();
+    // 创建uuid
+    const uuid = UUID.v1();
+    // 获取参数
+    const password = stream.fields.password;
+    const name = stream.fields.name;
+    assert(password, '请输入密码');
+    assert(name, '请输入名称');
+    // 创建文件名
+    const fileName = `${filePath.p12}${uuid}.p12`;
+    // 获取数据文件
+    const configJson = require(filePath.configJson);
+    try {
+      // 存储P12文件
+      const res = await this.service.fileshandler.upload({ name: fileName, stream });
+      // 存储成功
+      if (res.errcode === 0) {
+        // 拆出key
+        const keys = await this.service.shell.keys({ password, fileName });
+        // 拆出成功
+        if (keys.errcode === 0) {
+          // 存储p8文件
+          const p8 = await this.service.fileshandler.write({ filePath: `${filePath.keys}${uuid}.p8`, str: keys.data });
+          if (p8.errcode === 0) {
+            // 转换p8文件
+            await this.service.shell.transform({ files: `${filePath.keys}${uuid}.p8`, target: `${filePath.keys}${uuid}.key` });
+          }
+        }
+        // 拆出cer文件
+        const certs = await this.service.shell.certs({ password, fileName });
+        if (certs.errcode === 0) {
+          let dn,
+            pwatype;
+          // 存储cer文件
+          await this.service.fileshandler.write({ filePath: `${filePath.cert}${uuid}.cer`, str: certs.data });
+          // 获取cer信息
+          const dns = await this.service.shell.read({ filePath: `${filePath.cert}${uuid}.cer` });
+          // 获取dn
+          if (dns.errcode === 0 && dns.data) {
+            dns.data.trim().split('\n').forEach(function(v) {
+              if (v.includes('Subject:')) {
+                dn = v.replace('Subject:', '');
+              }
+              if (v.includes('ASN1 OID:')) {
+                pwatype = v.replace('ASN1 OID:', '');
+              }
+            });
+          }
+          // 制作数据
+          configJson.cert.push({ uuid, pwatype, dn, name, state: 1 });
+          const jsonstr = JSON.stringify(configJson);
+          // 存储数据文件写入
+          await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+          ctx.body = { errcode: 0, errmsg: '' };
+        }
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '证书上传失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+}
+
+module.exports = EnccertController;

+ 14 - 0
app/controller/home.js

@@ -0,0 +1,14 @@
+/* eslint-disable array-callback-return */
+'use strict';
+const fs = require('fs');
+const path = require('path');
+const Controller = require('egg').Controller;
+class HomeController extends Controller {
+  async home() {
+    const { ctx } = this;
+    ctx.response.type = 'html';
+    ctx.body = fs.readFileSync(path.resolve(__dirname, '../public/index.html'));
+  }
+}
+
+module.exports = HomeController;

+ 85 - 0
app/controller/ipsecvpn.js

@@ -0,0 +1,85 @@
+// ipsecvpn
+'use strict';
+
+const Controller = require('egg').Controller;
+const filePath = require('../../config/filespath');
+
+class IpsecvpnController extends Controller {
+  // 客户端
+  async secclient() {
+    const { ctx } = this;
+    const { address, addressTow, cert, digit, loglevel, pwa } = ctx.request.body;
+    const form = { address, addressTow, cert, digit, loglevel, pwa };
+    const person = require(filePath.configJson);
+    person.ipsecvpn = form;
+    const jsonstr = JSON.stringify(person);
+    try {
+      // 写入数据文件
+      await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+      form.certpath = `${filePath.cert}${form.cert}.cer`;
+      // 写入配置字符串模板
+      const ipsecavpnStr = await ctx.renderView('ipsecavpn.nj', form);
+      // 写入log字符串模板
+      const ipsecalog = await ctx.renderView('ipsecalog.nj', form);
+      if (ipsecavpnStr && ipsecalog) {
+        // 写入配置文件
+        await this.service.fileshandler.write({ filePath: filePath.ipsecClient, str: ipsecavpnStr });
+        await this.service.fileshandler.write({ filePath: filePath.swanlog, str: ipsecalog });
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '设置失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 服务端
+  async secservice() {
+    const { ctx } = this;
+    const form = ctx.request.body;
+    const person = require(filePath.configJson);
+    person.ipsecservice = form;
+    const jsonstr = JSON.stringify(person);
+    try {
+      // 存储数据
+      await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+      form.certpath = `${filePath.cert}${form.cert}.cer`;
+      // 写入配置字符串模板
+      const ipsecavpnStr = await ctx.renderView('ipsecavpnservice.nj', form);
+      // 写入log字符串模板
+      const ipsecalog = await ctx.renderView('ipsecalog.nj', form);
+      if (ipsecavpnStr && ipsecalog) {
+        // 写入配置文件
+        await this.service.fileshandler.write({ filePath: filePath.ipsecServer, str: ipsecavpnStr });
+        await this.service.fileshandler.write({ filePath: filePath.swanlog, str: ipsecalog });
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '设置失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 客户端查询
+  async secclientquery() {
+    try {
+      const { ctx } = this;
+      const person = require(filePath.configJson);
+      const data = person.ipsecvpn;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      throw error;
+    }
+  }
+  // 服务端查询
+  async ipsecservicequery() {
+    try {
+      const { ctx } = this;
+      const person = require(filePath.configJson);
+      const data = person.ipsecservice;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = IpsecvpnController;

+ 54 - 0
app/controller/lan.js

@@ -0,0 +1,54 @@
+// lan
+'use strict';
+
+const Controller = require('egg').Controller;
+const filePath = require('../../config/filespath');
+const shells = require('../../config/shells');
+class LanController extends Controller {
+  // 修改lan信息
+  async lanupdate() {
+    const lanpath = filePath.lan;
+    const configJson = require(filePath.configJson);
+    const { address, start, end, type } = this.ctx.request.body;
+    const form = { address, start, end, type };
+    form.addressTow = form.address.substring(0, form.address.lastIndexOf('.'));
+    // 数据文件赋值
+    configJson.lan = form;
+    // 数据文件对象变字符串
+    const jsonstr = JSON.stringify(configJson);
+    try {
+      // 写入数据文件
+      await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+      // 写入字符串模板
+      const lanstr = await this.ctx.renderView('lan.nj', form);
+      // 写入lan文件
+      await this.service.fileshandler.write({ filePath: lanpath, str: lanstr });
+      // dhcp部分
+      if (type === '0') {
+        // 写入dhcp字符串模板
+        const dhcpstr = await this.ctx.renderView('dhcp.nj', form);
+        const dhcpres = await this.service.fileshandler.write({ filePath: filePath.dhcpd, str: dhcpstr });
+        // 启动dhcp
+        if (dhcpres.errcode === 0) {
+          await this.service.shell.shell(shells.dhcpRestart);
+        }
+      } else {
+        // 停止dhcp服务
+        await this.service.shell.shell(shells.dhcpStop);
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '设置失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 查询lan信息
+  async lanquery() {
+    const { ctx } = this;
+    const configJson = require(filePath.configJson);
+    const data = configJson.lan;
+    ctx.body = { errcode: 0, errmsg: '', data };
+  }
+}
+
+module.exports = LanController;

+ 45 - 0
app/controller/log.js

@@ -0,0 +1,45 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+const filePath = require('../../config/filespath');
+class LogController extends Controller {
+  // ssl日志查询
+  async logquery() {
+    const { ctx } = this;
+    try {
+      const type = ctx.request.query.type;
+      let res;
+      if (type === 'ssl') res = await this.service.shell.shell(`tail -n 100 ${filePath.ssllog}`);
+      if (type === 'sec') res = await this.service.shell.shell(`tail -n 100 ${filePath.swanlog}`);
+      if (type === 'systemct') res = await this.service.shell.shell(`tail -n 100 ${filePath.systemctllog}`);
+      if (res.errcode === 0) {
+        ctx.body = { errcode: 0, errmsg: '', data: res.data };
+      } else {
+        this.ctx.body = { errcode: -0, errmsg: '获取日志失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '日志查询失败失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // ssl日志下载
+  async logdownload() {
+    try {
+      const type = this.ctx.request.query.type;
+      let res;
+      if (type === 'ssl') res = await this.secservice.fileshandler.download({ filePath: filePath.ssllog });
+      if (type === 'sec') res = await this.secservice.fileshandler.download({ filePath: filePath.ssllog });
+      if (type === 'systemct') res = await this.secservice.fileshandler.download({ filePath: filePath.ssllog });
+      if (res) {
+        this.ctx.body = res;
+      } else {
+        this.ctx.body = { errcode: -0, errmsg: '下载日志失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '下载失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+}
+
+module.exports = LogController;

+ 127 - 0
app/controller/sigcert.js

@@ -0,0 +1,127 @@
+// 签名证书证书
+'use strict';
+
+const Controller = require('egg').Controller;
+const UUID = require('uuid');
+const filePath = require('../../config/filespath');
+class SigcertController extends Controller {
+  // 添加申请书
+  async sigcertreq() {
+    const { ctx } = this;
+    const uuid = UUID.v1();
+    const { dn, pwatype, name } = ctx.request.body;
+    const state = 0;
+    try {
+    // 创建key
+      const reskey = await this.service.shell.applykey({ ...ctx.request.body, filePath: `${filePath.keys}${uuid}.key` });
+      if (reskey.errcode === 0) {
+      // 创建req
+        const resreq = await this.service.shell.applyreq({ ...ctx.request.body, keyPath: `${filePath.keys}${uuid}.key`, filePath: `${filePath.req}${uuid}.pem` });
+        if (resreq.errcode === 0) {
+          const form = { state, dn, pwatype, name, uuid };
+          const person = require(filePath.configJson);
+          person.cert.push(form);
+          const jsonstr = JSON.stringify(person);
+          // 添加到数据文件
+          await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+          this.ctx.body = { errcode: 0, errmsg: '' };
+        }
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '创建申请书失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 签名证书查询
+  async sigcacertquery() {
+    const { ctx } = this;
+    const person = require(filePath.configJson);
+    const data = person.cert;
+    const total = data.length || 0;
+    ctx.body = { errcode: 0, errmsg: '', data, total };
+  }
+  // 删除签名证书
+  async sigcertdelete() {
+    const uuid = this.ctx.query.uuid;
+    const configJson = require(filePath.configJson);
+    // 过滤掉当前uuid数据
+    const data = configJson.cert.filter(p => p.uuid !== uuid);
+    const isdata = configJson.cert.filter(p => p.uuid === uuid);
+    configJson.cert = data;
+    const jsonstr = JSON.stringify(configJson);
+    try {
+      // 存储到数据文件
+      await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+      const files = [];
+      if (isdata[0].state === 1) {
+        files.push({ path: `${filePath.cert}${uuid}.cer` }, { path: `${filePath.cert}${uuid}.key` });
+      } else {
+        files.push({ path: `${filePath.req}${uuid}.pem` });
+      }
+      // 删除证书文件
+      const res = await Promise.all(files.filter(async p => {
+        await this.service.fileshandler.filesDel(p.path);
+      }));
+      if (res.length > 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '证书删除失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '证书删除失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 签名证书上传
+  async sigcacertupload() {
+    const { ctx } = this;
+    const person = require(filePath.configJson);
+    const stream = await this.ctx.getFileStream();
+    const uuid = stream.fields.uuid;
+    // 路径 + 文件名
+    const name = `${filePath.cert}${uuid}.cer`;
+    try {
+      const res = await this.service.fileshandler.upload({ stream, name });
+      if (res.errcode === 0) {
+        person.cert.map(p => {
+          if (p.uuid === uuid) {
+            p.state = 1;
+          }
+          return p;
+        });
+        const jsonstr = JSON.stringify(person);
+        await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+        ctx.body = { errcode: 0, errmsg: '' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '证书上传失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 申请书下载
+  async reqdownload() {
+    try {
+      const uuid = this.ctx.query.uuid;
+      const reqfilePath = `${filePath.req}${uuid}.pem`;
+      const res = await this.service.fileshandler.download({ filePath: reqfilePath });
+      this.ctx.body = res;
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '申请书下载失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 签名证书下载
+  async sigcertdownload() {
+    try {
+      const uuid = this.ctx.query.uuid;
+      const sigfilePath = `${filePath.cert}${uuid}.cer`;
+      const res = await this.service.fileshandler.download({ filePath: sigfilePath });
+      this.ctx.body = res;
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '证书下载失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+}
+
+module.exports = SigcertController;

+ 84 - 0
app/controller/sslvpn.js

@@ -0,0 +1,84 @@
+// sslvpn
+'use strict';
+
+const Controller = require('egg').Controller;
+const filePath = require('../../config/filespath');
+class SslvpnController extends Controller {
+  // sslvpn客户端
+  async sslvpnclient() {
+    const { ctx } = this;
+    const form = ctx.request.body;
+    // 引入数据文件
+    const person = require(filePath.configJson);
+    person.sslvpn = form;
+    const jsonstr = JSON.stringify(person);
+    try {
+      // 写入数据文件
+      await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+      form.capath = `${filePath.CAcert}${form.ca}.cer`;
+      form.certpath = `${filePath.cert}${form.cert}.cer`;
+      form.keys = `${filePath.keys}${form.cert}.key`;
+      // 写入字符串模板
+      const sslvpnStr = await ctx.renderView('sslvpn.nj', form);
+      if (sslvpnStr) {
+        // 写入sslvpn配置文件
+        await this.service.fileshandler.write({ filePath: filePath.sslConf, str: sslvpnStr });
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '设置失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // ssl服务端
+  async sslvpnservice() {
+    const { ctx } = this;
+    const form = ctx.request.body;
+    const person = require(filePath.configJson);
+    person.sslvpnservice = form;
+    const jsonstr = JSON.stringify(person);
+    try {
+      // 写入数据文件
+      await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+      form.capath = `${filePath.CAcert}${form.ca}.cer`;
+      form.certpath = `${filePath.cert}${form.cert}.cer`;
+      form.keys = `${filePath.key}${form.cert}.key`;
+      // 写入字符串模板
+      const sslvpnserviceStr = await ctx.renderView('sslvpnservice.nj', form);
+      if (sslvpnserviceStr) {
+        // 写入sslvpn配置文件
+        await this.service.fileshandler.write({ filePath: filePath.sslConf, str: sslvpnserviceStr });
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '设置失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 客户端查询
+  async sslquery() {
+    try {
+      const { ctx } = this;
+      const person = require(filePath.configJson);
+      const data = person.sslvpn;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      const body = { errcode: -1001, errmsg: '查询失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 服务端查询
+  async sslserivcequery() {
+    try {
+      const { ctx } = this;
+      const person = require(filePath.configJson);
+      const data = person.sslvpnservice;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      const body = { errcode: -1001, errmsg: '查询失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+}
+
+module.exports = SslvpnController;

+ 225 - 0
app/controller/systemctl.js

@@ -0,0 +1,225 @@
+// 系统管理
+'use strict';
+
+const Controller = require('egg').Controller;
+const shells = require('../../config/shells');
+const filePath = require('../../config/filespath');
+class SystemctlController extends Controller {
+  // 重启机器
+  async reboot() {
+    try {
+      await this.service.shell.shell(shells.reboot);
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '重启机器失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 禁用wan网卡
+  async wanDown() {
+    try {
+      const res = await this.service.shell.shell(shells.wanDown);
+      if (res.errcode === 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '禁用wan网卡失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '禁用wan网卡失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 启用wan网卡
+  async wanup() {
+    try {
+      const res = await this.service.shell.shell(shells.wanUp);
+      if (res.errcode === 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '启用wan网卡失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '启用wan网卡失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 启用lan网卡
+  async lanup() {
+    try {
+      const res = await this.service.shell.shell(shells.lanUp);
+      if (res.errcode === 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '启用lan网卡失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '启用lan网卡失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 禁用lan网卡
+  async lanDown() {
+    try {
+      const res = await this.service.shell.shell(shells.lanDown);
+      if (res.errcode === 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '禁用lan网卡失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '禁用lan网卡失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // ping
+  async ping() {
+    const { address } = this.ctx.request.body;
+    try {
+      const res = await this.service.shell.shell(`ping ${address} -c 3`);
+      console.log(res, 'res');
+      if (res.errcode === 0 && res.data !== '') {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '地址链接失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '地址链接异常', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 获取时间
+  async getdate() {
+    try {
+      const res = await this.service.shell.shell('date "+%Y-%m-%d %H:%M:%S"');
+      if (res.errcode === 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '获取时间失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '获取时间失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 设置系统时间
+  async setdate() {
+    const { date } = this.ctx.request.body;
+    try {
+      const res = await this.service.shell.shell(`date -s "${date}"`);
+      console.log(res);
+      if (res.errcode === 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -0, errmsg: '设置系统时间失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '设置系统时间失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 获取vpn链接状态
+  async vpnstate() {
+    try {
+      const res = await this.service.shell.shell('swanctl -l | grep established');
+      if (res.errcode === 0 && res.data.length > 0) {
+        this.ctx.body = { errcode: 0, errmsg: '', data: '已链接' };
+      } else {
+        this.ctx.body = { errcode: 0, errmsg: '', data: '未链接' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '获取VPN链接状态失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 获取cpu使用率
+  async cpu() {
+    try {
+      const res = await this.service.shell.shell('vmstat | tail -n 1 | awk \'{print $13}\'');
+      if (res.errcode === 0 && res.data) {
+        this.ctx.body = { errcode: 0, errmsg: '', data: { cpu: res.data } };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '获取CPU使用率失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '获取CPU使用率失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 获取内存使用率
+  async memory() {
+    try {
+      const res = await this.service.shell.shell('free -t -m |tail -n 1 | awk \'{print $3/$2*100}\'');
+      if (res.errcode === 0 && res.data) {
+        this.ctx.body = { errcode: 0, errmsg: '', data: { memory: res.data } };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '获取内存使用率失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '获取内存使用率失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 获取设备信息
+  async devinfo() {
+    try {
+      const configJson = require(filePath.configJson);
+      const model = configJson.model;
+      const version = configJson.version;
+      this.ctx.body = { errcode: 0, errmsg: '', data: { model, version } };
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '获取设备信息失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // sslvpn 启动 停止 重启
+  async sslvpnstate() {
+    const { type } = this.ctx.request.query;
+    let data;
+    if (type === 'stop') {
+      data = shells.opStop;
+    }
+    if (type === 'start') {
+      data = shells.opStart;
+    }
+    if (type === 'restart') {
+      data = shells.opRestart;
+    }
+    try {
+      const res = await this.service.shell.shell(data);
+      if (res.errcode === 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '操作失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '操作失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // ipsecvpn 启动 停止 重启
+  async ipsecvpnstate() {
+    const { type } = this.ctx.request.query;
+    let data;
+    if (type === 'stop') {
+      data = shells.swStop;
+    }
+    if (type === 'start') {
+      data = shells.swStart;
+    }
+    if (type === 'restart') {
+      data = shells.swRestart;
+    }
+    try {
+      const res = await this.service.shell.shell(data);
+      if (res.errcode === 0) {
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      } else {
+        this.ctx.body = { errcode: -1, errmsg: '操作失败' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '操作失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+}
+
+module.exports = SystemctlController;

+ 53 - 0
app/controller/wan.js

@@ -0,0 +1,53 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+const filePath = require('../../config/filespath');
+class WanController extends Controller {
+  // 修改wan信息
+  async wanupdate() {
+    const wanpath = filePath.wan;
+    const configJson = require(filePath.configJson);
+    const { address, netmask, gateway, type, dns, staticip } = this.ctx.request.body;
+    const form = { address, netmask, gateway, type, dns, staticip };
+    console.log(address, netmask, gateway, type, dns, staticip);
+    if (type === 1) form.staticip = 0;
+    try {
+      if (staticip === 1) {
+        const resolvstring = await this.service.fileshandler.fileread({ filePath: filePath.resolv });
+        if (resolvstring.errcode === 0) {
+          resolvstring.data.trim().split('\n').forEach(function(v) {
+            if (v.includes('nameserver')) {
+              form.dns = v.replace('nameserver', '');
+            }
+          });
+        }
+      }
+      // 数据文件赋值
+      configJson.wan = form;
+      // 数据文件对象变字符串
+      const jsonstr = JSON.stringify(configJson);
+      // 写入数据文件
+      await this.service.fileshandler.write({ filePath: filePath.configJson, str: jsonstr });
+      // 写入字符串模板返回字符串
+      const wanstr = await this.ctx.renderView('wan.nj', form);
+      console.log(wanstr);
+      if (wanstr) {
+        // 写入wan文件
+        await this.service.fileshandler.write({ filePath: wanpath, str: wanstr });
+        this.ctx.body = { errcode: 0, errmsg: '' };
+      }
+    } catch (error) {
+      const body = { errcode: -1002, errmsg: '设置失败', error };
+      throw new Error(JSON.stringify(body));
+    }
+  }
+  // 查询wan信息
+  async wanquery() {
+    const { ctx } = this;
+    const configJson = require(filePath.configJson);
+    const data = configJson.wan;
+    ctx.body = { errcode: 0, errmsg: '', data };
+  }
+}
+
+module.exports = WanController;

+ 20 - 0
app/middleware/error_handler.js

@@ -0,0 +1,20 @@
+'use strict';
+module.exports = () => {
+  return async function errorHandler(ctx, next) {
+    try {
+      await next();
+    } catch (err) {
+      console.log(err);
+      if (err.status === 401) {
+        ctx.body = { errcode: err.status, errmsg: '请登录' };
+        ctx.status = err.status;
+        return false;
+      }
+      const { message } = err;
+      const json = JSON.parse(message);
+      ctx.logger.error(json.error);
+      ctx.body = json;
+      ctx.status = 400;
+    }
+  };
+};

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
app/public/css/app.fba0a0ac.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
app/public/css/chunk-vendors.c470e980.css


BIN
app/public/favicon.ico


BIN
app/public/fonts/element-icons.535877f5.woff


BIN
app/public/fonts/element-icons.732389de.ttf


BIN
app/public/img/bg.4f6e6589.jpg


BIN
app/public/img/logo.48e50617.jpg


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
app/public/index.html


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
app/public/js/app.aa1e9780.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 33 - 0
app/public/js/chunk-vendors.d4475822.js


+ 63 - 0
app/router.js

@@ -0,0 +1,63 @@
+'use strict';
+
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller, jwt } = app;
+  router.get('/', controller.home.home);
+  router.get('/public/:frame', controller.home.home);
+  router.get('/public/:frame/:type', controller.home.home);
+  router.get('/public/:frame/:type/:path', controller.home.home);
+  // wan
+  router.post('/api/wanupdate', jwt, controller.wan.wanupdate);
+  router.get('/api/wanquery', jwt, controller.wan.wanquery);
+  // lan
+  router.post('/api/lanupdate', jwt, controller.lan.lanupdate);
+  router.get('/api/lanquery', controller.lan.lanquery);
+  // admin
+  router.post('/api/login', controller.admin.login);
+  router.post('/api/editPwd', jwt, controller.admin.editPwd);
+  // CAcert
+  router.post('/api/caupload', jwt, controller.cacert.caupload);
+  router.get('/api/cadelete', jwt, controller.cacert.cadelete);
+  router.get('/api/caquery', jwt, controller.cacert.caquery);
+  router.get('/api/cacertdownload', controller.cacert.cacertdownload);
+  // Enccert
+  router.post('/api/enccertupload', jwt, controller.enccert.enccertupload);
+  // Sigcert
+  router.post('/api/sigcertreq', jwt, controller.sigcert.sigcertreq);
+  router.post('/api/sigcacertupload', jwt, controller.sigcert.sigcacertupload);
+  router.get('/api/sigcacertquery', jwt, controller.sigcert.sigcacertquery);
+  router.get('/api/sigcertdelete', jwt, controller.sigcert.sigcertdelete);
+  router.get('/api/sigcertdownload', controller.sigcert.sigcertdownload);
+  router.get('/api/reqdownload', controller.sigcert.reqdownload);
+  // systemctl
+  router.get('/api/reboot', jwt, controller.systemctl.reboot);
+  router.get('/api/wanDown', jwt, controller.systemctl.wanDown);
+  router.get('/api/wanup', jwt, controller.systemctl.wanup);
+  router.get('/api/lanup', jwt, controller.systemctl.lanup);
+  router.get('/api/lanDown', jwt, controller.systemctl.lanDown);
+  router.post('/api/ping', jwt, controller.systemctl.ping);
+  router.get('/api/getdate', jwt, controller.systemctl.getdate);
+  router.post('/api/setdate', jwt, controller.systemctl.setdate);
+  router.get('/api/vpnstate', jwt, controller.systemctl.vpnstate);
+  router.get('/api/cpu', jwt, controller.systemctl.cpu);
+  router.get('/api/memory', jwt, controller.systemctl.memory);
+  router.get('/api/devinfo', jwt, controller.systemctl.devinfo);
+  router.get('/api/ipsecvpnstate', jwt, controller.systemctl.ipsecvpnstate);
+  router.get('/api/sslvpnstate', jwt, controller.systemctl.sslvpnstate);
+  // ipsecvpn
+  router.post('/api/secclient', jwt, controller.ipsecvpn.secclient);
+  router.post('/api/secservice', jwt, controller.ipsecvpn.secservice);
+  router.get('/api/secclientquery', jwt, controller.ipsecvpn.secclientquery);
+  router.get('/api/ipsecservicequery', jwt, controller.ipsecvpn.ipsecservicequery);
+  // sslvpn
+  router.post('/api/sslvpnclient', jwt, controller.sslvpn.sslvpnclient);
+  router.post('/api/sslvpnservice', jwt, controller.sslvpn.sslvpnservice);
+  router.get('/api/sslquery', jwt, controller.sslvpn.sslquery);
+  router.get('/api/sslserivcequery', jwt, controller.sslvpn.sslserivcequery);
+  // log
+  router.get('/api/logquery', jwt, controller.log.logquery);
+  router.get('/api/logdownload', controller.log.logdownload);
+};

+ 69 - 0
app/service/fileshandler.js

@@ -0,0 +1,69 @@
+// 公共文件
+'use strict';
+const Service = require('egg').Service;
+const fs = require('fs');
+const path = require('path');
+class FileService extends Service {
+  // 文件下载
+  async download({ filePath }) {
+    const target = path.join(filePath);
+    this.ctx.attachment(target);
+    this.ctx.set('Content-Type', 'application/octet-stream');
+    const msg = fs.createReadStream(target);
+    return msg;
+  }
+  // 文件上传
+  async upload({ name, stream }) {
+    return new Promise((resolve, reject) => {
+      const target = path.join(`${name}`);
+      const remoteFileStream = fs.createWriteStream(target);
+      stream.pipe(remoteFileStream);
+      let errFlag;
+      remoteFileStream.on('error', err => {
+        errFlag = true;
+        remoteFileStream.destroy();
+        reject(err);
+      });
+
+      remoteFileStream.on('finish', async () => {
+        if (errFlag) return;
+        resolve({ errcode: 0, errmsg: '' });
+      });
+    });
+  }
+  // 文件写入
+  async write({ filePath, str }) {
+    return new Promise((resolve, reject) => {
+      fs.writeFile(path.resolve(filePath), str, {}, function(err) {
+        if (err) {
+          reject(err);
+        }
+        resolve({ errmsg: '', errcode: 0 });
+      });
+    });
+  }
+  // 文件删除
+  async filesDel(filePath) {
+    const cafile = path.join(filePath);
+    return new Promise((resolve, reject) => {
+      fs.unlink(cafile, function(err) {
+        if (err) {
+          reject(err);
+        }
+        resolve({ errmsg: '', errcode: 0 });
+      });
+    });
+  }
+  // 文件读取
+  async fileread(filePath) {
+    return new Promise((resolve, reject) => {
+      fs.readFile(filePath, (err, data) => {
+        if (err) {
+          reject(err);
+        }
+        resolve({ errmsg: '', errcode: 0, data });
+      });
+    });
+  }
+}
+module.exports = FileService;

+ 105 - 0
app/service/shell.js

@@ -0,0 +1,105 @@
+// 调用命令
+'use strict';
+const Service = require('egg').Service;
+const exec = require('child_process').exec;
+const fs = require('fs');
+class ShellService extends Service {
+  async shell(shellString) {
+    console.log(shellString, 'shellString');
+    return new Promise((resolve, reject) => {
+      exec(shellString, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        resolve({ errcode: 0, errmsg: '', data: stdout });
+      });
+    });
+  }
+  // 解析ca证书
+  async read({ filePath }) {
+    return new Promise((resolve, reject) => {
+      exec(`openssl x509 -in ${filePath} -noout -text -certopt no_header,no_version,no_extensions,no_sigdump,no_serial`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        resolve({ errcode: 0, errmsg: '', data: stdout });
+      });
+    });
+  }
+  // 创建key
+  async applykey({ pwatype, filePath }) {
+    return new Promise((resolve, reject) => {
+      // 创建密钥对
+      exec(`pki --gen --type ${pwatype} ${pwatype === 'rsa' ? '--size 2048' : ''} --outform pem`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        fs.writeFile(filePath, stdout, {}, function(err) {
+          if (err) {
+            reject(err);
+          }
+          resolve({ errmsg: '', errcode: 0 });
+        });
+      });
+    });
+  }
+  async applyreq({ dn, keyPath, filePath }) {
+    return new Promise((resolve, reject) => {
+      // 创建申请书
+      exec(`pki --req --type priv --in ${keyPath} \ --dn ${dn} \ --outform pem`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        fs.writeFile(filePath, stdout, {}, function(err) {
+          if (err) {
+            fs.unlink(keyPath, function(err) {
+              if (err) {
+                reject(err);
+              }
+            });
+            reject(err);
+          }
+          resolve({ errmsg: '', errcode: 0 });
+        });
+      });
+    });
+  }
+  // 拆出key
+  async keys({ fileName, password }) {
+    return new Promise((resolve, reject) => {
+      exec(`openssl pkcs12 -info -in ${fileName} -nodes -nocerts -password pass:${password}`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        const srart = stdout.indexOf('-----BEGIN PRIVATE KEY-----');
+        const data = stdout.slice(srart, stdout.length);
+        resolve({ errcode: 0, errmsg: '', data });
+      });
+    });
+  }
+  // key格式转换
+  async transform({ files, target }) {
+    return new Promise((resolve, reject) => {
+      exec(`openssl pkcs8 -in ${files}  -traditional -out ${target} -nocrypt`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        resolve({ errcode: 0, errmsg: '', data: stdout });
+      });
+    });
+  }
+  // 拆出证书
+  async certs({ fileName, password }) {
+    return new Promise((resolve, reject) => {
+      exec(`openssl pkcs12 -info -in ${fileName} -password pass:${password} -nokeys -clcerts`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        const srart = stdout.indexOf('-----BEGIN CERTIFICATE-----');
+        const data = stdout.slice(srart, stdout.length);
+        resolve({ errcode: 0, errmsg: '', data });
+      });
+    });
+  }
+}
+module.exports = ShellService;

+ 16 - 0
app/view/dhcp.nj

@@ -0,0 +1,16 @@
+option domain-name "example.org";
+option domain-name-servers 114.114.114.114;
+default-lease-time 600;
+max-lease-time 7200;
+subnet 192.168.100.0 netmask 255.255.255.0{
+  range 192.168.100.101 192.168.100.200;
+  option subnet-mask 255.255.255.0;
+  option routers 192.168.100.100;
+  option broadcast-address 192.168.100.255;
+}
+subnet {{ addressTow }}.0 netmask 255.255.255.0 {
+  range {{ addressTow }}.{{ start }} {{ addressTow }}.{{ end }};
+  option subnet-mask 255.255.255.0;
+  option routers {{ address }};
+  option broadcast-address {{ addressTow }}.255;
+}

+ 13 - 0
app/view/ipsecalog.nj

@@ -0,0 +1,13 @@
+charon {
+  filelog {
+    charon {
+      path = /var/log/charon.log
+      time_format = %b %e %T
+      ike_name = yes
+      append = no
+      default = {{ loglevel }}
+      flush_line = yes
+    }
+  }
+}
+

+ 24 - 0
app/view/ipsecavpn.nj

@@ -0,0 +1,24 @@
+connections {
+	home {
+		version = 1
+		remote_addrs = {{ address }}
+		proposals = sm4-sm3-modpnone
+		vips = 0.0.0.0
+		local {
+			auth = pubkey
+			certs = {{ certpath }}
+		}
+		remote {
+			auth = pubkey
+		}	
+		children {
+			home {
+				remote_ts  = {{ addressTow }}/{{ digit }}
+				start_action = start
+				close_action = start
+				esp_proposals = sm4-sm3-modpnone
+			}
+		}
+	}
+}
+

+ 26 - 0
app/view/ipsecavpnservice.nj

@@ -0,0 +1,26 @@
+connections {
+	rw {
+		version = 1
+		pools = rw_pool
+		proposals = sm4-sm3-modpnone
+		local {
+			auth = pubkey
+			certs = {{ certpath }}
+		}
+		remote {
+			auth = pubkey
+		}
+		children {
+			net-net {
+				local_ts  = {{ address }}/{{ digit }}
+				esp_proposals = sm4-sm3-modpnone
+			}
+		}
+	}
+}
+pools {
+	rw_pool {
+		addrs = {{ addressTow }}/{{ digitTow }}
+	}
+}
+

+ 11 - 0
app/view/lan.nj

@@ -0,0 +1,11 @@
+auto br-lan
+iface br-lan inet static
+    pre-up ifconfig lan1 up
+    pre-up ifconfig lan2 up
+    pre-up ifconfig lan3 up
+    address {{ address }}
+    netmask 255.255.255.0
+    broadcast {{ addressTow }}.255
+    bridge_ports lan1
+    bridge_ports lan2
+    bridge_ports lan3

+ 28 - 0
app/view/sslvpn.nj

@@ -0,0 +1,28 @@
+client
+
+dev tun
+
+data-ciphers SMS4-CBC:SMS4-CFB:SMS4-OFB
+cipher SMS4-CBC
+auth SM3
+auth-nocache
+tls-version-min 1.1
+tls-version-max 1.2
+tls-cipher ECDHE-SM2-WITH-SMS4-GCM-SM3:ECDHE-SM2-WITH-SMS4-SM3:SM2-WITH-SMS4-SM3:SM2DHE-WITH-SMS4-SM3
+
+#compress lzo
+
+resolv-retry infinite
+script-security 2
+nobind
+persist-key
+persist-tun
+mute-replay-warnings
+log /var/log/openvpn.log
+
+proto {{ agreement }}
+remote {{ address }} {{ port }}
+ca {{ capath }}
+cert {{ certpath }}
+key {{ keys }}
+verb {{ loglevel }}

+ 37 - 0
app/view/sslvpnservice.nj

@@ -0,0 +1,37 @@
+dev tun
+
+dh none
+
+#crl-verify /etc/openvpn/server/crl.pem
+#push "dhcp-option DNS 84.200.69.80"
+#push "dhcp-option DNS 84.200.70.40"
+
+duplicate-cn
+
+data-ciphers SMS4-CBC:SMS4-CFB:SMS4-OFB
+cipher SMS4-CBC
+auth SM3
+auth-nocache
+tls-version-min 1.1
+tls-version-max 1.2
+tls-cipher ECDHE-SM2-WITH-SMS4-GCM-SM3:ECDHE-SM2-WITH-SMS4-SM3:SM2-WITH-SMS4-SM3:SM2DHE-WITH-SMS4-SM3
+
+keepalive 20 60
+persist-key
+persist-tun
+#comp-lzo yes
+daemon
+#user nobody
+#group nobody
+
+log-append /var/log/openvpn.log
+
+
+proto  {{ agreement  }}
+server  {{ address }}  {{ netmask }}
+port  {{ port }}
+ca  {{ capath }}
+cert  {{ certpath }}
+key  {{ keys }}
+push "route  {{ routerAddress  }}  {{ routerNetmask  }}"
+verb  {{ loglevel  }}

+ 14 - 0
app/view/wan.nj

@@ -0,0 +1,14 @@
+{% if type == 1 %}
+auto wan
+iface wan inet static
+    pre-up ifconfig eth0 up
+    address {{ address }}
+    netmask {{ netmask }}
+    gateway {{ gateway }}
+    dns-nameservers {{ dns }}
+{% else %}
+    auto wan
+    iface wan inet dhcp
+        pre-up ifconfig eth0 up
+        dns-nameservers {{ dns }}
+{% endif %}

+ 14 - 0
appveyor.yml

@@ -0,0 +1,14 @@
+environment:
+  matrix:
+    - nodejs_version: '10'
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm i npminstall && node_modules\.bin\npminstall
+
+test_script:
+  - node --version
+  - npm --version
+  - npm run test
+
+build: off

+ 79 - 0
config/config.default.js

@@ -0,0 +1,79 @@
+/* eslint valid-jsdoc: "off" */
+
+'use strict';
+
+/**
+ * @param {Egg.EggAppInfo} appInfo app info
+ */
+module.exports = appInfo => {
+  /**
+   * built-in config
+   * @type {Egg.EggAppConfig}
+   **/
+  const config = exports = {};
+
+  // use for cookie sign key, should change to your own and keep security
+  config.keys = appInfo.name + '_1614667010858_9935';
+
+  // add your middleware config here
+  config.middleware = [];
+
+  // add your user config here
+  const userConfig = {
+    // myAppName: 'egg',
+  };
+
+  // 安全协议
+  config.security = {
+    csrf: {
+      enable: false,
+      ignoreJSON: true,
+    },
+    // 允许访问接口的白名单
+    // domainWhiteList: [ 'http://localhost:8080' ],
+  };
+
+  // 访问端口地址
+  config.cluster = {
+    listen: {
+      path: '',
+      port: 7002,
+      // hostname: '0.0.0.0',
+    },
+  };
+
+  // 字符串模板
+  config.view = {
+    mapping: {
+      '.nj': 'nunjucks',
+    },
+  };
+  // 访问路径
+  config.assets = {
+    publicPath: '/public/',
+  };
+
+  // 文件上传白名单
+  config.multipart = {
+    mode: 'stream',
+    whitelist: [ '.pem', '.crt', '.der', '.cer', '.pfx', '.p12', '.jks' ],
+  };
+
+  // jwt密钥
+  config.jwt = {
+    secret: '123456',
+  };
+
+  // 异常捕获
+  config.middleware = [ 'errorHandler' ];
+
+  // 日志级别
+  config.logger = {
+    level: 'ERROR',
+  };
+
+  return {
+    ...config,
+    ...userConfig,
+  };
+};

+ 40 - 0
config/filespath.js

@@ -0,0 +1,40 @@
+'use strict';
+
+module.exports = {
+  wan: '/etc/network/interfaces.d/wan',
+  // wan配置(可通过管理服务配置)
+  lan: '/etc/network/interfaces.d/br-lan',
+  // lan234桥接配置(可通过管理服务配置)
+  dhcp: '/etc/default/isc-dhcp-server',
+  // dhcp配置
+  dhcpd: '/etc/dhcp/dhcpd.conf',
+  // dhcp配置(可通过管理服务配置)
+  ipsecClient: '/ipsec/etc/swanctl/conf.d/client.conf',
+  // swan客户端配置文件(可通过管理服务配置)
+  ipsecServer: '/ipsec/etc/swanctl/conf.d/server.conf',
+  // swan服务端配置文件(可通过管理服务配置)
+  CAcert: '/ipsec/etc/swanctl/x509ca/',
+  // CA证书存放路径
+  cert: '/ipsec/etc/swanctl/x509/',
+  // 证书存放路径 (加密证书enc.cert)(签名证书sig.cert)
+  keys: '/ipsec/etc/swanctl/private/',
+  // 密钥存放路径(加密密钥enc.key)(签名证书sig.key)
+  p12: '/ipsec/etc/swanctl/pkcs12/',
+  // p12 存储位置
+  req: '/etc/vpn/req/',
+  // req存储位置
+  swanLogConf: '/ipsec/etc/strongswan.d/charon-logging.conf',
+  // swan日志配置文件
+  swanlog: '/var/log/charon.log',
+  // swan日志路径
+  ssllog: '/var/log/openvpn.log',
+  // sslvpn日志文件路径
+  sslConf: '/etc/openvpn/openvpn.conf',
+  // ssl配置文件
+  configJson: '/etc/vpn/config.json',
+  // 数据存放文件路径
+  resolv: '/etc/resolv.conf',
+  // 上层配置文件
+  systemctllog: '/usr/local/vpnserve/logs/Y/common-error.log',
+  // 系统日志
+};

+ 17 - 0
config/plugin.js

@@ -0,0 +1,17 @@
+'use strict';
+
+/** @type Egg.EggPlugin */
+module.exports = {
+  jwt: {
+    enable: true,
+    package: 'egg-jwt',
+  },
+  static: {
+    enable: true,
+  },
+  nunjucks: {
+    enable: true,
+    package: 'egg-view-nunjucks',
+  },
+};
+

+ 101 - 0
config/shells.js

@@ -0,0 +1,101 @@
+'use strict';
+
+module.exports = {
+  // strongswan相关命令
+  swIsEnabled: 'systemctl is-enabled strongswan-swanctl',
+  // 查看strongswan服务是否开机自启动
+  swEnable: 'systemctl enable strongswan-swanctl',
+  // 开启strongswan服务的自启动
+  swDisable: 'systemctl disable strongswan-swanctl',
+  // 关闭strongswan服务的自启动
+  swStatus: 'systemctl status strongswan-swanctl',
+  // 查看strongswan服务是否正在运行
+  swStart: 'systemctl start strongswan-swanctl',
+  // 启动strongswan服务
+  swRestart: 'systemctl restart strongswan-swanctl',
+  // 重启strongswan服务
+  swStop: 'systemctl stop strongswan-swanctl',
+  // 停止strongswan服务
+  swReload: 'systemctl reload strongswan-swanctl',
+
+  // openvpn相关命令
+  opIsEnabled: 'systemctl is-enabled openvpn',
+  // 查看Openvpn是否开机自启动
+  opEnable: 'systemctl enable openvpn',
+  // 打开Openvpn服务的自启动
+  opDisable: 'systemctl disable openvpn',
+  // 关闭Openvpn服务的自启动
+  opStatus: 'systemctl status openvpn',
+  // 查看Openvpn服务是否正在运行
+  opStart: 'systemctl start openvpn',
+  // 启动Openvpn服务
+  opRestart: 'systemctl restart openvpn',
+  // 重启Openvpn服务
+  opStop: 'systemctl stop openvpn',
+  // 停止Openvpn服务
+
+  //  dhcp相关命令
+  dhcpIsEnabled: 'systemctl is-enabled isc-dhcp-server',
+  // 查看dhcp是否开机自启动
+  dhcpEnable: 'systemctl enable isc-dhcp-server',
+  // 打开dhcp服务的自启动
+  dhcpDisable: 'systemctl disable isc-dhcp-server',
+  // 关闭dhcp服务的自启动
+  dhcpStatus: 'systemctl status isc-dhcp-server',
+  // 查看dhcp服务是否正在运行
+  dhcpStart: 'systemctl start isc-dhcp-server',
+  // 启动dhcp服务
+  dhcpRestart: 'systemctl restart isc-dhcp-server',
+  // 重启dhcp服务
+  dhcpStop: 'systemctl stop isc-dhcp-server',
+  // 停止dhcp服务
+
+  // 网络配置相关命令
+  wanDown: 'ifconfig wan down',
+  // 禁用wan网卡
+  wanUp: 'ifconfig wan up',
+  // 启用wan网卡
+  lanDown: 'ifconfig br-lan down',
+  // 禁用br-lan网卡
+  lanUp: 'ifconfig br-lan up',
+  // 启用br-lan网卡
+
+  // 系统重启命令
+  reboot: 'reboot',
+  // reboot后系统将自动重启
+
+  // 状态检测相关命令
+  // cpu使用率和内存使用率
+  deviceState: 'top | head -n 5',
+  // 结果:
+  // top - 08:51:46 up  2:49,  1 user,  load average: 0.01, 0.11, 0.15
+  // Tasks:  87 total,   1 running,  46 sleeping,   0 stopped,   0 zombie
+  // %Cpu(s):  1.4 us,  0.5 sy,  0.0 ni, 97.9 id,  0.0 wa,  0.1 hi,  0.1 si,  0.0 st
+  // KiB Mem :   997064 total,   682744 free,   154900 used,   159420 buff/cache
+  // KiB Swap:        0 total,        0 free,        0 used.   747584 avail Mem
+
+  // CPU使用率:取第3行 	97.9id(比如空闲CPU,100-97.9=2.1 即CPU使用率)
+  // 内存使用率:取第4行 	(997064-682744)/997064
+
+  // VPN连接状态
+  vpnState: 'swanctl -l | grep established',
+  // 结果(如果已建立连接此显示类似如下信息):
+  //     如果命令结果为空,表示未建立连接
+  //     如果命令显示类似:established 74s ago, rekeying in 13516s,表示已建立连接74s
+
+  // 时间命令
+  // 获取当前时间
+  // date "+%Y-%m-%d %H:%M:%S"
+  // 结果:2021-03-01 06:19:50
+
+  // 设置系统时间
+  // date -s "2021-03-01 06:19:50"
+  // 结果:系统时间将被修改为:2021-03-01 06:19:50
+
+  // ntp时间同步命令
+
+  // 连接测试
+  // ping 192.168.88.10
+
+};
+

+ 5 - 0
jsconfig.json

@@ -0,0 +1,5 @@
+{
+  "include": [
+    "**/*"
+  ]
+}

+ 49 - 0
package.json

@@ -0,0 +1,49 @@
+{
+  "name": "Y",
+  "version": "1.0.0",
+  "description": "",
+  "private": true,
+  "egg": {
+    "declarations": true
+  },
+  "dependencies": {
+    "egg": "^2.15.1",
+    "egg-jwt": "^3.1.7",
+    "egg-scripts": "^2.11.0",
+    "egg-view-nunjucks": "^2.3.0",
+    "uuid": "^8.3.2"
+  },
+  "devDependencies": {
+    "autod": "^3.0.1",
+    "autod-egg": "^1.1.0",
+    "egg-bin": "^4.11.0",
+    "egg-ci": "^1.11.0",
+    "egg-mock": "^3.21.0",
+    "eslint": "^5.13.0",
+    "eslint-config-egg": "^7.1.0"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "start": "egg-scripts start --daemon --title=egg-server-Y",
+    "stop": "egg-scripts stop --title=egg-server-Y",
+    "dev": "egg-bin dev",
+    "debug": "egg-bin debug",
+    "test": "npm run lint -- --fix && npm run test-local",
+    "test-local": "egg-bin test",
+    "cov": "egg-bin cov",
+    "lint": "eslint .",
+    "ci": "npm run lint && npm run cov",
+    "autod": "autod"
+  },
+  "ci": {
+    "version": "10"
+  },
+  "repository": {
+    "type": "git",
+    "url": ""
+  },
+  "author": "",
+  "license": "MIT"
+}

+ 20 - 0
test/app/controller/home.test.js

@@ -0,0 +1,20 @@
+'use strict';
+
+const { app, assert } = require('egg-mock/bootstrap');
+
+describe('test/app/controller/home.test.js', () => {
+  it('should assert', () => {
+    const pkg = require('../../../package.json');
+    assert(app.config.keys.startsWith(pkg.name));
+
+    // const ctx = app.mockContext({});
+    // yield ctx.service.xx();
+  });
+
+  it('should GET /', () => {
+    return app.httpRequest()
+      .get('/')
+      .expect('hi, egg')
+      .expect(200);
+  });
+});